4 * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
6 * This software may be copied and distributed for educational, research,
7 * and not for profit purposes provided that this copyright and statement
8 * are included in all such copies. Other copyrights may also apply.
17 * Helper function -- return a "nearby" race for polymorphing
19 * Note that this function is one of the more "dangerous" ones...
21 s16b
poly_r_idx(int r_idx
)
23 monster_race
*r_ptr
= &r_info
[r_idx
];
27 /* Hack -- Uniques never polymorph */
28 if (r_ptr
->flags1
& (RF1_UNIQUE
)) return (r_idx
);
30 /* Allowable range of "levels" for resulting monster */
31 lev1
= r_ptr
->level
- ((randint(20)/randint(9))+1);
32 lev2
= r_ptr
->level
+ ((randint(20)/randint(9))+1);
34 /* Pick a (possibly new) non-unique race */
35 for (i
= 0; i
< 1000; i
++)
37 /* Pick a new race, using a level calculation */
38 r
= get_mon_num((p_ptr
->depth
+ r_ptr
->level
) / 2 + 5);
46 /* Ignore unique monsters */
47 if (r_ptr
->flags1
& (RF1_UNIQUE
)) continue;
49 /* Ignore monsters with incompatible levels */
50 if ((r_ptr
->level
< lev1
) || (r_ptr
->level
> lev2
)) continue;
65 * Teleport a monster, normally up to "dis" grids away.
67 * Attempt to move the monster at least "dis/2" grids away.
69 * But allow variation to prevent infinite loops.
71 void teleport_away(int m_idx
, int dis
)
73 int ny
, nx
, oy
, ox
, d
, i
, min
;
77 monster_type
*m_ptr
= &mon_list
[m_idx
];
81 if (!m_ptr
->r_idx
) return;
83 /* Save the old location */
87 /* Minimum distance */
93 /* Verify max distance */
94 if (dis
> 200) dis
= 200;
96 /* Try several locations */
97 for (i
= 0; i
< 500; i
++)
99 /* Pick a (possibly illegal) location */
102 ny
= rand_spread(oy
, dis
);
103 nx
= rand_spread(ox
, dis
);
104 d
= distance(oy
, ox
, ny
, nx
);
105 if ((d
>= min
) && (d
<= dis
)) break;
108 /* Ignore illegal locations */
109 if (!in_bounds_fully(ny
, nx
)) continue;
111 /* Require "empty" floor space */
112 if (!cave_empty_bold(ny
, nx
)) continue;
114 /* Hack -- no teleport onto glyph of warding */
115 if (cave_feat
[ny
][nx
] == FEAT_GLYPH
) continue;
117 /* No teleporting into vaults and such */
118 /* if (cave_info[ny][nx] & (CAVE_ICKY)) continue; */
120 /* This grid looks good */
127 /* Increase the maximum distance */
130 /* Decrease the minimum distance */
137 /* Swap the monsters */
138 monster_swap(oy
, ox
, ny
, nx
);
143 * Teleport the player to a location up to "dis" grids away.
145 * If no such spaces are readily available, the distance may increase.
146 * Try very hard to move the player at least a quarter that distance.
148 void teleport_player(int dis
)
162 /* Minimum distance */
165 /* Look until done */
168 /* Verify max distance */
169 if (dis
> 200) dis
= 200;
171 /* Try several locations */
172 for (i
= 0; i
< 500; i
++)
174 /* Pick a (possibly illegal) location */
177 y
= rand_spread(py
, dis
);
178 x
= rand_spread(px
, dis
);
179 d
= distance(py
, px
, y
, x
);
180 if ((d
>= min
) && (d
<= dis
)) break;
183 /* Ignore illegal locations */
184 if (!in_bounds_fully(y
, x
)) continue;
186 /* Require "naked" floor space */
187 if (!cave_naked_bold(y
, x
)) continue;
189 /* No teleporting into vaults and such */
190 if (cave_info
[y
][x
] & (CAVE_ICKY
)) continue;
192 /* This grid looks good */
199 /* Increase the maximum distance */
202 /* Decrease the minimum distance */
210 monster_swap(py
, px
, y
, x
);
212 /* Handle stuff XXX XXX XXX */
219 * Teleport player to a grid near the given location
221 * This function is slightly obsessive about correctness.
222 * This function allows teleporting into vaults (!)
224 void teleport_player_to(int ny
, int nx
)
231 int dis
= 0, ctr
= 0;
237 /* Find a usable location */
240 /* Pick a nearby legal location */
243 y
= rand_spread(ny
, dis
);
244 x
= rand_spread(nx
, dis
);
245 if (in_bounds_fully(y
, x
)) break;
248 /* Accept "naked" floor grids */
249 if (cave_naked_bold(y
, x
)) break;
251 /* Occasionally advance the distance */
252 if (++ctr
> (4 * dis
* dis
+ 4 * dis
+ 1))
263 monster_swap(py
, px
, y
, x
);
265 /* Handle stuff XXX XXX XXX */
272 * Teleport the player one level up or down (random when legal)
274 void teleport_player_level(void)
278 msg_print("Nothing happens.");
285 message(MSG_TPLEVEL
, 0, "You sink through the floor.");
291 p_ptr
->leaving
= TRUE
;
294 else if (is_quest(p_ptr
->depth
) || (p_ptr
->depth
>= MAX_DEPTH
-1))
296 message(MSG_TPLEVEL
, 0, "You rise up through the ceiling.");
302 p_ptr
->leaving
= TRUE
;
305 else if (rand_int(100) < 50)
307 message(MSG_TPLEVEL
, 0, "You rise up through the ceiling.");
313 p_ptr
->leaving
= TRUE
;
318 message(MSG_TPLEVEL
, 0, "You sink through the floor.");
324 p_ptr
->leaving
= TRUE
;
334 * Return a color to use for the bolt/ball spells
336 static byte
spell_color(int type
)
341 case GF_MISSILE
: return (TERM_VIOLET
);
342 case GF_ACID
: return (TERM_SLATE
);
343 case GF_ELEC
: return (TERM_BLUE
);
344 case GF_FIRE
: return (TERM_RED
);
345 case GF_COLD
: return (TERM_WHITE
);
346 case GF_POIS
: return (TERM_GREEN
);
347 case GF_HOLY_ORB
: return (TERM_L_DARK
);
348 case GF_MANA
: return (TERM_L_DARK
);
349 case GF_ARROW
: return (TERM_WHITE
);
350 case GF_WATER
: return (TERM_SLATE
);
351 case GF_NETHER
: return (TERM_L_GREEN
);
352 case GF_CHAOS
: return (TERM_VIOLET
);
353 case GF_DISENCHANT
: return (TERM_VIOLET
);
354 case GF_NEXUS
: return (TERM_L_RED
);
355 case GF_CONFUSION
: return (TERM_L_UMBER
);
356 case GF_SOUND
: return (TERM_YELLOW
);
357 case GF_SHARD
: return (TERM_UMBER
);
358 case GF_FORCE
: return (TERM_UMBER
);
359 case GF_INERTIA
: return (TERM_L_WHITE
);
360 case GF_GRAVITY
: return (TERM_L_WHITE
);
361 case GF_TIME
: return (TERM_L_BLUE
);
362 case GF_LITE_WEAK
: return (TERM_ORANGE
);
363 case GF_LITE
: return (TERM_ORANGE
);
364 case GF_DARK_WEAK
: return (TERM_L_DARK
);
365 case GF_DARK
: return (TERM_L_DARK
);
366 case GF_PLASMA
: return (TERM_RED
);
367 case GF_METEOR
: return (TERM_RED
);
368 case GF_ICE
: return (TERM_WHITE
);
371 /* Standard "color" */
378 * Find the attr/char pair to use for a spell effect
380 * It is moving (or has moved) from (x,y) to (nx,ny).
382 * If the distance is not "one", we (may) return "*".
384 static u16b
bolt_pict(int y
, int x
, int ny
, int nx
, int typ
)
393 if (!(use_graphics
&& (arg_graphics
== GRAPHICS_DAVID_GERVAIS
)))
396 if ((ny
== y
) && (nx
== x
)) base
= 0x30;
399 else if (nx
== x
) base
= 0x40;
402 else if (ny
== y
) base
= 0x50;
405 else if ((ny
-y
) == (x
-nx
)) base
= 0x60;
408 else if ((ny
-y
) == (nx
-x
)) base
= 0x70;
413 /* Basic spell color */
414 k
= spell_color(typ
);
416 /* Obtain attr/char */
417 a
= misc_to_attr
[base
+k
];
418 c
= misc_to_char
[base
+k
];
425 if ((ny
== y
) && (nx
== x
)) {base
= 0x00; add
= 0;}
428 else if (nx
== x
) {base
= 0x40; add
= 0;}
431 else if (ny
== y
) {base
= 0x40; add
= 1;}
434 else if ((ny
-y
) == (x
-nx
)) {base
= 0x40; add
= 2;}
437 else if ((ny
-y
) == (nx
-x
)) {base
= 0x40; add
= 3;}
440 else {base
= 0x00; add
= 0;}
442 if (typ
>= 0x40) k
= 0;
445 /* Obtain attr/char */
446 a
= misc_to_attr
[base
+k
];
447 c
= misc_to_char
[base
+k
] + add
;
458 * Decreases players hit points and sets death flag if necessary
460 * Invulnerability needs to be changed into a "shield" XXX XXX XXX
462 * Hack -- this function allows the user to save (or quit) the game
463 * when he dies, since the "You die." message is shown before setting
464 * the player to "dead".
466 void take_hit(int dam
, cptr kb_str
)
468 int old_chp
= p_ptr
->chp
;
470 int warning
= (p_ptr
->mhp
* op_ptr
->hitpoint_warn
/ 10);
474 if (p_ptr
->is_dead
) return;
480 /* Mega-Hack -- Apply "invulnerability" */
481 if (p_ptr
->timed
[TMD_INVULN
] && (dam
< 9000)) return;
483 /* Hurt the player */
486 /* Display the hitpoints */
487 p_ptr
->redraw
|= (PR_HP
);
490 p_ptr
->window
|= (PW_PLAYER_0
| PW_PLAYER_1
);
495 /* Hack -- Note death */
496 message(MSG_DEATH
, 0, "You die.");
499 /* Note cause of death */
500 my_strcpy(p_ptr
->died_from
, kb_str
, sizeof(p_ptr
->died_from
));
502 /* No longer a winner */
503 p_ptr
->total_winner
= FALSE
;
506 p_ptr
->is_dead
= TRUE
;
509 p_ptr
->leaving
= TRUE
;
515 /* Hitpoint warning */
516 if (p_ptr
->chp
< warning
)
518 /* Hack -- bell on first notice */
519 if (old_chp
> warning
)
521 bell("Low hitpoint warning!");
525 message(MSG_HITPOINT_WARN
, 0, "*** LOW HITPOINT WARNING! ***");
535 * Does a given class of objects (usually) hate acid?
536 * Note that acid can either melt or corrode something.
538 static bool hates_acid(const object_type
*o_ptr
)
540 /* Analyze the type */
563 /* Staffs/Scrolls are wood/paper */
576 /* Junk is useless */
590 * Does a given object (usually) hate electricity?
592 static bool hates_elec(const object_type
*o_ptr
)
609 * Does a given object (usually) hate fire?
610 * Hafted/Polearm weapons have wooden shafts.
611 * Arrows/Bows are mostly wooden.
613 static bool hates_fire(const object_type
*o_ptr
)
615 /* Analyze the type */
645 /* Staffs/Scrolls burn */
658 * Does a given object (usually) hate cold?
660 static bool hates_cold(const object_type
*o_ptr
)
686 static int set_acid_destroy(const object_type
*o_ptr
)
689 if (!hates_acid(o_ptr
)) return (FALSE
);
690 object_flags(o_ptr
, &f1
, &f2
, &f3
);
691 if (f3
& (TR3_IGNORE_ACID
)) return (FALSE
);
699 static int set_elec_destroy(const object_type
*o_ptr
)
702 if (!hates_elec(o_ptr
)) return (FALSE
);
703 object_flags(o_ptr
, &f1
, &f2
, &f3
);
704 if (f3
& (TR3_IGNORE_ELEC
)) return (FALSE
);
712 static int set_fire_destroy(const object_type
*o_ptr
)
715 if (!hates_fire(o_ptr
)) return (FALSE
);
716 object_flags(o_ptr
, &f1
, &f2
, &f3
);
717 if (f3
& (TR3_IGNORE_FIRE
)) return (FALSE
);
725 static int set_cold_destroy(const object_type
*o_ptr
)
728 if (!hates_cold(o_ptr
)) return (FALSE
);
729 object_flags(o_ptr
, &f1
, &f2
, &f3
);
730 if (f3
& (TR3_IGNORE_COLD
)) return (FALSE
);
738 * This seems like a pretty standard "typedef"
740 typedef int (*inven_func
)(const object_type
*);
743 * Destroys a type of item on a given percent chance
744 * Note that missiles are no longer necessarily all destroyed
746 * Returns number of items destroyed.
748 static int inven_damage(inven_func typ
, int perc
)
758 /* Count the casualties */
761 /* Scan through the slots backwards */
762 for (i
= 0; i
< INVEN_PACK
; i
++)
764 o_ptr
= &inventory
[i
];
766 /* Skip non-objects */
767 if (!o_ptr
->k_idx
) continue;
769 /* Hack -- for now, skip artifacts */
770 if (artifact_p(o_ptr
)) continue;
772 /* Give this item slot a shot at death */
775 /* Scale the destruction chance up */
776 int chance
= perc
* 100;
780 /* Analyze the type to see if we just damage it */
790 /* Chance to damage it */
791 if (rand_int(10000) < perc
)
793 /* Damage the item */
816 /* Chance to damage it */
817 if (rand_int(10000) < perc
)
819 /* Damage the item */
833 chance
= (chance
/ 4);
839 /* Damage instead of destroy */
842 /* Calculate bonuses */
843 p_ptr
->update
|= (PU_BONUS
);
846 p_ptr
->window
|= (PW_EQUIP
| PW_PLAYER_0
| PW_PLAYER_1
);
852 /* Count the casualties */
853 else for (amt
= j
= 0; j
< o_ptr
->number
; ++j
)
855 if (rand_int(10000) < chance
) amt
++;
858 /* Some casualities */
861 /* Get a description */
862 object_desc(o_name
, sizeof(o_name
), o_ptr
, FALSE
, 3);
865 message_format(MSG_DESTROY
, 0, "%sour %s (%c) %s %s!",
866 ((o_ptr
->number
> 1) ?
867 ((amt
== o_ptr
->number
) ? "All of y" :
868 (amt
> 1 ? "Some of y" : "One of y")) : "Y"),
869 o_name
, index_to_label(i
),
870 ((amt
> 1) ? "were" : "was"),
871 (damage
? "damaged" : "destroyed"));
873 /* Damage already done? */
874 if (damage
) continue;
876 /* Hack -- If rods, wands, or staves are destroyed, the total
877 * maximum timeout or charges of the stack needs to be reduced,
878 * unless all the items are being destroyed. -LM-
880 if (((o_ptr
->tval
== TV_WAND
) ||
881 (o_ptr
->tval
== TV_STAFF
) ||
882 (o_ptr
->tval
== TV_ROD
)) &&
883 (amt
< o_ptr
->number
))
885 o_ptr
->pval
-= o_ptr
->pval
* amt
/ o_ptr
->number
;
888 /* Destroy "amt" items */
889 inven_item_increase(i
, -amt
);
890 inven_item_optimize(i
);
892 /* Count the casualties */
898 /* Return the casualty count */
906 * Acid has hit the player, attempt to affect some armor.
908 * Note that the "base armor" of an object never changes.
910 * If any armor is damaged (or resists), the player takes less damage.
912 static int minus_ac(void)
914 object_type
*o_ptr
= NULL
;
921 /* Pick a (possibly empty) inventory slot */
924 case 1: o_ptr
= &inventory
[INVEN_BODY
]; break;
925 case 2: o_ptr
= &inventory
[INVEN_ARM
]; break;
926 case 3: o_ptr
= &inventory
[INVEN_OUTER
]; break;
927 case 4: o_ptr
= &inventory
[INVEN_HANDS
]; break;
928 case 5: o_ptr
= &inventory
[INVEN_HEAD
]; break;
929 case 6: o_ptr
= &inventory
[INVEN_FEET
]; break;
932 /* Nothing to damage */
933 if (!o_ptr
->k_idx
) return (FALSE
);
935 /* No damage left to be done */
936 if (o_ptr
->ac
+ o_ptr
->to_a
<= 0) return (FALSE
);
940 object_desc(o_name
, sizeof(o_name
), o_ptr
, FALSE
, 0);
942 /* Extract the flags */
943 object_flags(o_ptr
, &f1
, &f2
, &f3
);
946 if (f3
& (TR3_IGNORE_ACID
))
948 msg_format("Your %s is unaffected!", o_name
);
954 msg_format("Your %s is damaged!", o_name
);
956 /* Damage the item */
959 /* Calculate bonuses */
960 p_ptr
->update
|= (PU_BONUS
);
963 p_ptr
->window
|= (PW_EQUIP
| PW_PLAYER_0
| PW_PLAYER_1
);
965 /* Item was damaged */
971 * Hurt the player with Acid
973 void acid_dam(int dam
, cptr kb_str
)
975 int inv
= (dam
< 30) ? 1 : (dam
< 60) ? 2 : 3;
978 if (p_ptr
->immune_acid
|| (dam
<= 0)) return;
980 /* Resist the damage */
981 if (p_ptr
->resist_acid
) dam
= (dam
+ 2) / 3;
982 if (p_ptr
->timed
[TMD_OPP_ACID
]) dam
= (dam
+ 2) / 3;
984 /* If any armor gets hit, defend the player */
985 if (minus_ac()) dam
= (dam
+ 1) / 2;
988 take_hit(dam
, kb_str
);
990 /* Inventory damage */
991 inven_damage(set_acid_destroy
, inv
);
996 * Hurt the player with electricity
998 void elec_dam(int dam
, cptr kb_str
)
1000 int inv
= (dam
< 30) ? 1 : (dam
< 60) ? 2 : 3;
1002 /* Total immunity */
1003 if (p_ptr
->immune_elec
|| (dam
<= 0)) return;
1005 /* Resist the damage */
1006 if (p_ptr
->timed
[TMD_OPP_ELEC
]) dam
= (dam
+ 2) / 3;
1007 if (p_ptr
->resist_elec
) dam
= (dam
+ 2) / 3;
1010 take_hit(dam
, kb_str
);
1012 /* Inventory damage */
1013 inven_damage(set_elec_destroy
, inv
);
1020 * Hurt the player with Fire
1022 void fire_dam(int dam
, cptr kb_str
)
1024 int inv
= (dam
< 30) ? 1 : (dam
< 60) ? 2 : 3;
1026 /* Totally immune */
1027 if (p_ptr
->immune_fire
|| (dam
<= 0)) return;
1029 /* Resist the damage */
1030 if (p_ptr
->resist_fire
) dam
= (dam
+ 2) / 3;
1031 if (p_ptr
->timed
[TMD_OPP_FIRE
]) dam
= (dam
+ 2) / 3;
1034 take_hit(dam
, kb_str
);
1036 /* Inventory damage */
1037 inven_damage(set_fire_destroy
, inv
);
1042 * Hurt the player with Cold
1044 void cold_dam(int dam
, cptr kb_str
)
1046 int inv
= (dam
< 30) ? 1 : (dam
< 60) ? 2 : 3;
1048 /* Total immunity */
1049 if (p_ptr
->immune_cold
|| (dam
<= 0)) return;
1051 /* Resist the damage */
1052 if (p_ptr
->resist_cold
) dam
= (dam
+ 2) / 3;
1053 if (p_ptr
->timed
[TMD_OPP_COLD
]) dam
= (dam
+ 2) / 3;
1056 take_hit(dam
, kb_str
);
1058 /* Inventory damage */
1059 inven_damage(set_cold_destroy
, inv
);
1067 * Increase a stat by one randomized level
1069 * Most code will "restore" a stat before calling this function,
1070 * in particular, stat potions will always restore the stat and
1071 * then increase the fully restored value.
1073 bool inc_stat(int stat
)
1077 /* Then augment the current/max stat */
1078 value
= p_ptr
->stat_cur
[stat
];
1080 /* Cannot go above 18/100 */
1083 /* Gain one (sometimes two) points */
1086 gain
= ((rand_int(100) < 75) ? 1 : 2);
1090 /* Gain 1/6 to 1/3 of distance to 18/100 */
1091 else if (value
< 18+98)
1093 /* Approximate gain value */
1094 gain
= (((18+100) - value
) / 2 + 3) / 2;
1097 if (gain
< 1) gain
= 1;
1099 /* Apply the bonus */
1100 value
+= randint(gain
) + gain
/ 2;
1103 if (value
> 18+99) value
= 18 + 99;
1106 /* Gain one point at a time */
1112 /* Save the new value */
1113 p_ptr
->stat_cur
[stat
] = value
;
1115 /* Bring up the maximum too */
1116 if (value
> p_ptr
->stat_max
[stat
])
1118 p_ptr
->stat_max
[stat
] = value
;
1121 /* Recalculate bonuses */
1122 p_ptr
->update
|= (PU_BONUS
);
1128 /* Nothing to gain */
1135 * Decreases a stat by an amount indended to vary from 0 to 100 percent.
1137 * Note that "permanent" means that the *given* amount is permanent,
1138 * not that the new value becomes permanent. This may not work exactly
1139 * as expected, due to "weirdness" in the algorithm, but in general,
1140 * if your stat is already drained, the "max" value will not drop all
1141 * the way down to the "cur" value.
1143 bool dec_stat(int stat
, int amount
, bool permanent
)
1145 int cur
, max
, loss
, same
, res
= FALSE
;
1148 /* Get the current value */
1149 cur
= p_ptr
->stat_cur
[stat
];
1150 max
= p_ptr
->stat_max
[stat
];
1152 /* Note when the values are identical */
1153 same
= (cur
== max
);
1155 /* Damage "current" value */
1158 /* Handle "low" values */
1161 if (amount
> 90) cur
--;
1162 if (amount
> 50) cur
--;
1163 if (amount
> 20) cur
--;
1167 /* Handle "high" values */
1170 /* Hack -- Decrement by a random amount between one-quarter */
1171 /* and one-half of the stat bonus times the percentage, with a */
1172 /* minimum damage of half the percentage. -CWS */
1173 loss
= (((cur
-18) / 2 + 1) / 2 + 1);
1176 if (loss
< 1) loss
= 1;
1178 /* Randomize the loss */
1179 loss
= ((randint(loss
) + loss
) * amount
) / 100;
1182 if (loss
< amount
/2) loss
= amount
/2;
1184 /* Lose some points */
1187 /* Hack -- Only reduce stat to 17 sometimes */
1188 if (cur
< 18) cur
= (amount
<= 20) ? 18 : 17;
1191 /* Prevent illegal values */
1192 if (cur
< 3) cur
= 3;
1194 /* Something happened */
1195 if (cur
!= p_ptr
->stat_cur
[stat
]) res
= TRUE
;
1198 /* Damage "max" value */
1199 if (permanent
&& (max
> 3))
1201 /* Handle "low" values */
1204 if (amount
> 90) max
--;
1205 if (amount
> 50) max
--;
1206 if (amount
> 20) max
--;
1210 /* Handle "high" values */
1213 /* Hack -- Decrement by a random amount between one-quarter */
1214 /* and one-half of the stat bonus times the percentage, with a */
1215 /* minimum damage of half the percentage. -CWS */
1216 loss
= (((max
-18) / 2 + 1) / 2 + 1);
1217 if (loss
< 1) loss
= 1;
1218 loss
= ((randint(loss
) + loss
) * amount
) / 100;
1219 if (loss
< amount
/2) loss
= amount
/2;
1221 /* Lose some points */
1224 /* Hack -- Only reduce stat to 17 sometimes */
1225 if (max
< 18) max
= (amount
<= 20) ? 18 : 17;
1228 /* Hack -- keep it clean */
1229 if (same
|| (max
< cur
)) max
= cur
;
1231 /* Something happened */
1232 if (max
!= p_ptr
->stat_max
[stat
]) res
= TRUE
;
1238 /* Actually set the stat to its new value. */
1239 p_ptr
->stat_cur
[stat
] = cur
;
1240 p_ptr
->stat_max
[stat
] = max
;
1242 /* Recalculate bonuses */
1243 p_ptr
->update
|= (PU_BONUS
);
1252 * Restore a stat. Return TRUE only if this actually makes a difference.
1254 bool res_stat(int stat
)
1256 /* Restore if needed */
1257 if (p_ptr
->stat_cur
[stat
] != p_ptr
->stat_max
[stat
])
1260 p_ptr
->stat_cur
[stat
] = p_ptr
->stat_max
[stat
];
1262 /* Recalculate bonuses */
1263 p_ptr
->update
|= (PU_BONUS
);
1269 /* Nothing to restore */
1277 * Apply disenchantment to the player's stuff
1279 * This function is also called from the "melee" code.
1281 * The "mode" is currently unused.
1283 * Return "TRUE" if the player notices anything.
1285 bool apply_disenchant(int mode
)
1294 /* Unused parameter */
1297 /* Pick a random slot */
1300 case 1: t
= INVEN_WIELD
; break;
1301 case 2: t
= INVEN_BOW
; break;
1302 case 3: t
= INVEN_BODY
; break;
1303 case 4: t
= INVEN_OUTER
; break;
1304 case 5: t
= INVEN_ARM
; break;
1305 case 6: t
= INVEN_HEAD
; break;
1306 case 7: t
= INVEN_HANDS
; break;
1307 case 8: t
= INVEN_FEET
; break;
1311 o_ptr
= &inventory
[t
];
1313 /* No item, nothing happens */
1314 if (!o_ptr
->k_idx
) return (FALSE
);
1317 /* Nothing to disenchant */
1318 if ((o_ptr
->to_h
<= 0) && (o_ptr
->to_d
<= 0) && (o_ptr
->to_a
<= 0))
1320 /* Nothing to notice */
1325 /* Describe the object */
1326 object_desc(o_name
, sizeof(o_name
), o_ptr
, FALSE
, 0);
1329 /* Artifacts have 60% chance to resist */
1330 if (artifact_p(o_ptr
) && (rand_int(100) < 60))
1333 msg_format("Your %s (%c) resist%s disenchantment!",
1334 o_name
, index_to_label(t
),
1335 ((o_ptr
->number
!= 1) ? "" : "s"));
1342 /* Disenchant tohit */
1343 if (o_ptr
->to_h
> 0) o_ptr
->to_h
--;
1344 if ((o_ptr
->to_h
> 5) && (rand_int(100) < 20)) o_ptr
->to_h
--;
1346 /* Disenchant todam */
1347 if (o_ptr
->to_d
> 0) o_ptr
->to_d
--;
1348 if ((o_ptr
->to_d
> 5) && (rand_int(100) < 20)) o_ptr
->to_d
--;
1350 /* Disenchant toac */
1351 if (o_ptr
->to_a
> 0) o_ptr
->to_a
--;
1352 if ((o_ptr
->to_a
> 5) && (rand_int(100) < 20)) o_ptr
->to_a
--;
1355 msg_format("Your %s (%c) %s disenchanted!",
1356 o_name
, index_to_label(t
),
1357 ((o_ptr
->number
!= 1) ? "were" : "was"));
1359 /* Recalculate bonuses */
1360 p_ptr
->update
|= (PU_BONUS
);
1363 p_ptr
->window
|= (PW_EQUIP
| PW_PLAYER_0
| PW_PLAYER_1
);
1373 static void apply_nexus(const monster_type
*m_ptr
)
1375 int max1
, cur1
, max2
, cur2
, ii
, jj
;
1379 case 1: case 2: case 3:
1381 teleport_player(200);
1387 teleport_player_to(m_ptr
->fy
, m_ptr
->fx
);
1393 if (rand_int(100) < p_ptr
->skills
[SKILL_SAV
])
1395 msg_print("You resist the effects!");
1399 /* Teleport Level */
1400 teleport_player_level();
1406 if (rand_int(100) < p_ptr
->skills
[SKILL_SAV
])
1408 msg_print("You resist the effects!");
1412 msg_print("Your body starts to scramble...");
1414 /* Pick a pair of stats */
1415 ii
= rand_int(A_MAX
);
1416 for (jj
= ii
; jj
== ii
; jj
= rand_int(A_MAX
)) /* loop */;
1418 max1
= p_ptr
->stat_max
[ii
];
1419 cur1
= p_ptr
->stat_cur
[ii
];
1420 max2
= p_ptr
->stat_max
[jj
];
1421 cur2
= p_ptr
->stat_cur
[jj
];
1423 p_ptr
->stat_max
[ii
] = max2
;
1424 p_ptr
->stat_cur
[ii
] = cur2
;
1425 p_ptr
->stat_max
[jj
] = max1
;
1426 p_ptr
->stat_cur
[jj
] = cur1
;
1428 p_ptr
->update
|= (PU_BONUS
);
1440 * Mega-Hack -- track "affected" monsters (see "project()" comments)
1442 static int project_m_n
;
1443 static int project_m_x
;
1444 static int project_m_y
;
1449 * We are called from "project()" to "damage" terrain features
1451 * We are called both for "beam" effects and "ball" effects.
1453 * The "r" parameter is the "distance from ground zero".
1455 * Note that we determine if the player can "see" anything that happens
1456 * by taking into account: blindness, line-of-sight, and illumination.
1458 * We return "TRUE" if the effect of the projection is "obvious".
1460 * Hack -- We also "see" grids which are "memorized".
1462 * Perhaps we should affect doors and/or walls.
1464 static bool project_f(int who
, int r
, int y
, int x
, int dam
, int typ
)
1466 bool obvious
= FALSE
;
1468 /* Unused parameters */
1474 /* Reduce damage by distance */
1475 dam
= (dam
+ r
) / (r
+ 1);
1478 /* Analyze the type */
1481 /* Ignore most effects */
1498 /* Destroy Traps (and Locks) */
1501 /* Reveal secret doors */
1502 if (cave_feat
[y
][x
] == FEAT_SECRET
)
1504 place_closed_door(y
, x
);
1506 /* Check line of sight */
1507 if (player_has_los_bold(y
, x
))
1514 if ((cave_feat
[y
][x
] == FEAT_INVIS
) ||
1515 ((cave_feat
[y
][x
] >= FEAT_TRAP_HEAD
) &&
1516 (cave_feat
[y
][x
] <= FEAT_TRAP_TAIL
)))
1518 /* Check line of sight */
1519 if (player_has_los_bold(y
, x
))
1521 msg_print("There is a bright flash of light!");
1525 /* Forget the trap */
1526 cave_info
[y
][x
] &= ~(CAVE_MARK
);
1528 /* Destroy the trap */
1529 cave_set_feat(y
, x
, FEAT_FLOOR
);
1532 /* Locked doors are unlocked */
1533 else if ((cave_feat
[y
][x
] >= FEAT_DOOR_HEAD
+ 0x01) &&
1534 (cave_feat
[y
][x
] <= FEAT_DOOR_HEAD
+ 0x07))
1536 /* Unlock the door */
1537 cave_set_feat(y
, x
, FEAT_DOOR_HEAD
+ 0x00);
1539 /* Check line of sound */
1540 if (player_has_los_bold(y
, x
))
1542 msg_print("Click!");
1550 /* Destroy Doors (and traps) */
1553 /* Destroy all doors and traps */
1554 if ((cave_feat
[y
][x
] == FEAT_OPEN
) ||
1555 (cave_feat
[y
][x
] == FEAT_BROKEN
) ||
1556 (cave_feat
[y
][x
] == FEAT_INVIS
) ||
1557 ((cave_feat
[y
][x
] >= FEAT_TRAP_HEAD
) &&
1558 (cave_feat
[y
][x
] <= FEAT_TRAP_TAIL
)) ||
1559 ((cave_feat
[y
][x
] >= FEAT_DOOR_HEAD
) &&
1560 (cave_feat
[y
][x
] <= FEAT_DOOR_TAIL
)))
1562 /* Check line of sight */
1563 if (player_has_los_bold(y
, x
))
1566 msg_print("There is a bright flash of light!");
1569 /* Visibility change */
1570 if ((cave_feat
[y
][x
] >= FEAT_DOOR_HEAD
) &&
1571 (cave_feat
[y
][x
] <= FEAT_DOOR_TAIL
))
1573 /* Update the visuals */
1574 p_ptr
->update
|= (PU_UPDATE_VIEW
| PU_MONSTERS
);
1578 /* Forget the door */
1579 cave_info
[y
][x
] &= ~(CAVE_MARK
);
1581 /* Destroy the feature */
1582 cave_set_feat(y
, x
, FEAT_FLOOR
);
1588 /* Destroy walls (and doors) */
1591 /* Non-walls (etc) */
1592 if (cave_floor_bold(y
, x
)) break;
1594 /* Permanent walls */
1595 if (cave_feat
[y
][x
] >= FEAT_PERM_EXTRA
) break;
1598 if (cave_feat
[y
][x
] >= FEAT_WALL_EXTRA
)
1601 if (cave_info
[y
][x
] & (CAVE_MARK
))
1603 msg_print("The wall turns into mud!");
1607 /* Forget the wall */
1608 cave_info
[y
][x
] &= ~(CAVE_MARK
);
1610 /* Destroy the wall */
1611 cave_set_feat(y
, x
, FEAT_FLOOR
);
1614 /* Quartz / Magma with treasure */
1615 else if (cave_feat
[y
][x
] >= FEAT_MAGMA_H
)
1618 if (cave_info
[y
][x
] & (CAVE_MARK
))
1620 msg_print("The vein turns into mud!");
1621 msg_print("You have found something!");
1625 /* Forget the wall */
1626 cave_info
[y
][x
] &= ~(CAVE_MARK
);
1628 /* Destroy the wall */
1629 cave_set_feat(y
, x
, FEAT_FLOOR
);
1631 /* Place some gold */
1635 /* Quartz / Magma */
1636 else if (cave_feat
[y
][x
] >= FEAT_MAGMA
)
1639 if (cave_info
[y
][x
] & (CAVE_MARK
))
1641 msg_print("The vein turns into mud!");
1645 /* Forget the wall */
1646 cave_info
[y
][x
] &= ~(CAVE_MARK
);
1648 /* Destroy the wall */
1649 cave_set_feat(y
, x
, FEAT_FLOOR
);
1653 else if (cave_feat
[y
][x
] == FEAT_RUBBLE
)
1656 if (cave_info
[y
][x
] & (CAVE_MARK
))
1658 msg_print("The rubble turns into mud!");
1662 /* Forget the wall */
1663 cave_info
[y
][x
] &= ~(CAVE_MARK
);
1665 /* Destroy the rubble */
1666 cave_set_feat(y
, x
, FEAT_FLOOR
);
1668 /* Hack -- place an object */
1669 if (rand_int(100) < 10)
1671 /* Found something */
1672 if (player_can_see_bold(y
, x
))
1674 msg_print("There was something buried in the rubble!");
1679 place_object(y
, x
, FALSE
, FALSE
);
1683 /* Destroy doors (and secret doors) */
1684 else /* if (cave_feat[y][x] >= FEAT_DOOR_HEAD) */
1686 /* Hack -- special message */
1687 if (cave_info
[y
][x
] & (CAVE_MARK
))
1689 msg_print("The door turns into mud!");
1693 /* Forget the wall */
1694 cave_info
[y
][x
] &= ~(CAVE_MARK
);
1696 /* Destroy the feature */
1697 cave_set_feat(y
, x
, FEAT_FLOOR
);
1700 /* Update the visuals */
1701 p_ptr
->update
|= (PU_UPDATE_VIEW
| PU_MONSTERS
);
1703 /* Fully update the flow */
1704 p_ptr
->update
|= (PU_FORGET_FLOW
| PU_UPDATE_FLOW
);
1712 /* Require a "naked" floor grid */
1713 if (!cave_naked_bold(y
, x
)) break;
1715 /* Create closed door */
1716 cave_set_feat(y
, x
, FEAT_DOOR_HEAD
+ 0x00);
1719 if (cave_info
[y
][x
] & (CAVE_MARK
)) obvious
= TRUE
;
1721 /* Update the visuals */
1722 p_ptr
->update
|= (PU_UPDATE_VIEW
| PU_MONSTERS
);
1730 /* Require a "naked" floor grid */
1731 if (!cave_naked_bold(y
, x
)) break;
1739 /* Lite up the grid */
1743 /* Turn on the light */
1744 cave_info
[y
][x
] |= (CAVE_GLOW
);
1746 /* Grid is in line of sight */
1747 if (player_has_los_bold(y
, x
))
1749 if (!p_ptr
->timed
[TMD_BLIND
])
1755 /* Fully update the visuals */
1756 p_ptr
->update
|= (PU_FORGET_VIEW
| PU_UPDATE_VIEW
| PU_MONSTERS
);
1762 /* Darken the grid */
1766 /* Turn off the light */
1767 cave_info
[y
][x
] &= ~(CAVE_GLOW
);
1769 /* Hack -- Forget "boring" grids */
1770 if (cave_feat
[y
][x
] <= FEAT_INVIS
)
1773 cave_info
[y
][x
] &= ~(CAVE_MARK
);
1776 /* Grid is in line of sight */
1777 if (player_has_los_bold(y
, x
))
1782 /* Fully update the visuals */
1783 p_ptr
->update
|= (PU_FORGET_VIEW
| PU_UPDATE_VIEW
| PU_MONSTERS
);
1791 /* Return "Anything seen?" */
1798 * We are called from "project()" to "damage" objects
1800 * We are called both for "beam" effects and "ball" effects.
1802 * Perhaps we should only SOMETIMES damage things on the ground.
1804 * The "r" parameter is the "distance from ground zero".
1806 * Note that we determine if the player can "see" anything that happens
1807 * by taking into account: blindness, line-of-sight, and illumination.
1809 * Hack -- We also "see" objects which are "memorized".
1811 * We return "TRUE" if the effect of the projection is "obvious".
1813 static bool project_o(int who
, int r
, int y
, int x
, int dam
, int typ
)
1815 s16b this_o_idx
, next_o_idx
= 0;
1817 bool obvious
= FALSE
;
1824 /* Unused parameters */
1830 /* Reduce damage by distance */
1831 dam
= (dam
+ r
) / (r
+ 1);
1835 /* Scan all objects in the grid */
1836 for (this_o_idx
= cave_o_idx
[y
][x
]; this_o_idx
; this_o_idx
= next_o_idx
)
1840 bool is_art
= FALSE
;
1841 bool ignore
= FALSE
;
1842 bool plural
= FALSE
;
1843 bool do_kill
= FALSE
;
1845 cptr note_kill
= NULL
;
1847 /* Get the object */
1848 o_ptr
= &o_list
[this_o_idx
];
1850 /* Get the next object */
1851 next_o_idx
= o_ptr
->next_o_idx
;
1853 /* Extract the flags */
1854 object_flags(o_ptr
, &f1
, &f2
, &f3
);
1856 /* Get the "plural"-ness */
1857 if (o_ptr
->number
> 1) plural
= TRUE
;
1859 /* Check for artifact */
1860 if (artifact_p(o_ptr
)) is_art
= TRUE
;
1862 /* Analyze the type */
1865 /* Acid -- Lots of things */
1868 if (hates_acid(o_ptr
))
1871 note_kill
= (plural
? " melt!" : " melts!");
1872 if (f3
& (TR3_IGNORE_ACID
)) ignore
= TRUE
;
1877 /* Elec -- Rings and Wands */
1880 if (hates_elec(o_ptr
))
1883 note_kill
= (plural
? " are destroyed!" : " is destroyed!");
1884 if (f3
& (TR3_IGNORE_ELEC
)) ignore
= TRUE
;
1889 /* Fire -- Flammable objects */
1892 if (hates_fire(o_ptr
))
1895 note_kill
= (plural
? " burn up!" : " burns up!");
1896 if (f3
& (TR3_IGNORE_FIRE
)) ignore
= TRUE
;
1901 /* Cold -- potions and flasks */
1904 if (hates_cold(o_ptr
))
1906 note_kill
= (plural
? " shatter!" : " shatters!");
1908 if (f3
& (TR3_IGNORE_COLD
)) ignore
= TRUE
;
1916 if (hates_fire(o_ptr
))
1919 note_kill
= (plural
? " burn up!" : " burns up!");
1920 if (f3
& (TR3_IGNORE_FIRE
)) ignore
= TRUE
;
1922 if (hates_elec(o_ptr
))
1926 note_kill
= (plural
? " are destroyed!" : " is destroyed!");
1927 if (f3
& (TR3_IGNORE_ELEC
)) ignore
= TRUE
;
1935 if (hates_fire(o_ptr
))
1938 note_kill
= (plural
? " burn up!" : " burns up!");
1939 if (f3
& (TR3_IGNORE_FIRE
)) ignore
= TRUE
;
1941 if (hates_cold(o_ptr
))
1945 note_kill
= (plural
? " shatter!" : " shatters!");
1946 if (f3
& (TR3_IGNORE_COLD
)) ignore
= TRUE
;
1951 /* Hack -- break potions and such */
1957 if (hates_cold(o_ptr
))
1959 note_kill
= (plural
? " shatter!" : " shatters!");
1965 /* Mana -- destroys everything */
1969 note_kill
= (plural
? " are destroyed!" : " is destroyed!");
1973 /* Holy Orb -- destroys cursed non-artifacts */
1976 if (cursed_p(o_ptr
))
1979 note_kill
= (plural
? " are destroyed!" : " is destroyed!");
1988 /* Chests are noticed only if trapped or locked */
1989 if (o_ptr
->tval
== TV_CHEST
)
1991 /* Disarm/Unlock traps */
1992 if (o_ptr
->pval
> 0)
1994 /* Disarm or Unlock */
1995 o_ptr
->pval
= (0 - o_ptr
->pval
);
1998 object_known(o_ptr
);
2003 msg_print("Click!");
2014 /* Attempt to destroy the object */
2017 /* Effect "observed" */
2021 object_desc(o_name
, sizeof(o_name
), o_ptr
, FALSE
, 0);
2024 /* Artifacts, and other objects, get to resist */
2025 if (is_art
|| ignore
)
2027 /* Observe the resist */
2030 msg_format("The %s %s unaffected!",
2031 o_name
, (plural
? "are" : "is"));
2038 /* Describe if needed */
2039 if (o_ptr
->marked
&& note_kill
)
2041 message_format(MSG_DESTROY
, 0, "The %s%s", o_name
, note_kill
);
2044 /* Delete the object */
2045 delete_object_idx(this_o_idx
);
2053 /* Return "Anything seen?" */
2060 * Helper function for "project()" below.
2062 * Handle a beam/bolt/ball causing damage to a monster.
2064 * This routine takes a "source monster" (by index) which is mostly used to
2065 * determine if the player is causing the damage, and a "radius" (see below),
2066 * which is used to decrease the power of explosions with distance, and a
2067 * location, via integers which are modified by certain types of attacks
2068 * (polymorph and teleport being the obvious ones), a default damage, which
2069 * is modified as needed based on various properties, and finally a "damage
2070 * type" (see below).
2072 * Note that this routine can handle "no damage" attacks (like teleport) by
2073 * taking a "zero" damage, and can even take "parameters" to attacks (like
2074 * confuse) by accepting a "damage", using it to calculate the effect, and
2075 * then setting the damage to zero. Note that the "damage" parameter is
2076 * divided by the radius, so monsters not at the "epicenter" will not take
2077 * as much damage (or whatever)...
2079 * Note that "polymorph" is dangerous, since a failure in "place_monster()"'
2080 * may result in a dereference of an invalid pointer. XXX XXX XXX
2082 * Various messages are produced, and damage is applied.
2084 * Just "casting" a substance (i.e. plasma) does not make you immune, you must
2085 * actually be "made" of that substance, or "breathe" big balls of it.
2087 * We assume that "Plasma" monsters, and "Plasma" breathers, are immune
2090 * We assume "Nether" is an evil, necromantic force, so it doesn't hurt undead,
2091 * and hurts evil less. If can breath nether, then it resists it as well.
2093 * Damage reductions use the following formulas:
2094 * Note that "dam = dam * 6 / (randint(6) + 6);"
2095 * gives avg damage of .655, ranging from .858 to .500
2096 * Note that "dam = dam * 5 / (randint(6) + 6);"
2097 * gives avg damage of .544, ranging from .714 to .417
2098 * Note that "dam = dam * 4 / (randint(6) + 6);"
2099 * gives avg damage of .444, ranging from .556 to .333
2100 * Note that "dam = dam * 3 / (randint(6) + 6);"
2101 * gives avg damage of .327, ranging from .427 to .250
2102 * Note that "dam = dam * 2 / (randint(6) + 6);"
2103 * gives something simple.
2105 * In this function, "result" messages are postponed until the end, where
2106 * the "note" string is appended to the monster name, if not NULL. So,
2107 * to make a spell have "no effect" just set "note" to NULL. You should
2108 * also set "notice" to FALSE, or the player will learn what the spell does.
2110 * We attempt to return "TRUE" if the player saw anything "useful" happen.
2112 static bool project_m(int who
, int r
, int y
, int x
, int dam
, int typ
)
2116 monster_type
*m_ptr
;
2117 monster_race
*r_ptr
;
2118 monster_lore
*l_ptr
;
2122 /* Is the monster "seen"? */
2125 /* Were the effects "obvious" (if seen)? */
2126 bool obvious
= FALSE
;
2128 /* Were the effects "irrelevant"? */
2129 bool skipped
= FALSE
;
2132 /* Polymorph setting (true or false) */
2135 /* Teleport setting (max distance) */
2138 /* Confusion setting (amount to confuse) */
2141 /* Stunning setting (amount to stun) */
2144 /* Sleep amount (amount to sleep) */
2147 /* Fear amount (amount to fear) */
2151 /* Hold the monster name */
2154 /* Assume no note */
2157 /* Assume a default death */
2158 cptr note_dies
= " dies.";
2161 /* Walls protect monsters */
2162 if (!cave_floor_bold(y
,x
)) return (FALSE
);
2165 /* No monster here */
2166 if (!(cave_m_idx
[y
][x
] > 0)) return (FALSE
);
2168 /* Never affect projector */
2169 if (cave_m_idx
[y
][x
] == who
) return (FALSE
);
2172 /* Obtain monster info */
2173 m_ptr
= &mon_list
[cave_m_idx
[y
][x
]];
2174 r_ptr
= &r_info
[m_ptr
->r_idx
];
2175 l_ptr
= &l_list
[m_ptr
->r_idx
];
2176 name
= (r_name
+ r_ptr
->name
);
2177 if (m_ptr
->ml
) seen
= TRUE
;
2180 /* Reduce damage by distance */
2181 dam
= (dam
+ r
) / (r
+ 1);
2184 /* Get the monster name (BEFORE polymorphing) */
2185 monster_desc(m_name
, sizeof(m_name
), m_ptr
, 0);
2189 /* Some monsters get "destroyed" */
2190 if ((r_ptr
->flags3
& (RF3_DEMON
)) ||
2191 (r_ptr
->flags3
& (RF3_UNDEAD
)) ||
2192 (r_ptr
->flags2
& (RF2_STUPID
)) ||
2193 (strchr("Evg", r_ptr
->d_char
)))
2195 /* Special note at death */
2196 note_dies
= " is destroyed.";
2200 /* Analyze the damage type */
2203 /* Magic Missile -- pure damage */
2206 if (seen
) obvious
= TRUE
;
2213 if (seen
) obvious
= TRUE
;
2214 if (r_ptr
->flags3
& (RF3_IM_ACID
))
2216 note
= " resists a lot.";
2218 if (seen
) l_ptr
->flags3
|= (RF3_IM_ACID
);
2226 if (seen
) obvious
= TRUE
;
2227 if (r_ptr
->flags3
& (RF3_IM_ELEC
))
2229 note
= " resists a lot.";
2231 if (seen
) l_ptr
->flags3
|= (RF3_IM_ELEC
);
2239 if (seen
) obvious
= TRUE
;
2240 if (r_ptr
->flags3
& (RF3_IM_FIRE
))
2242 note
= " resists a lot.";
2244 if (seen
) l_ptr
->flags3
|= (RF3_IM_FIRE
);
2252 if (seen
) obvious
= TRUE
;
2253 if (r_ptr
->flags3
& (RF3_IM_COLD
))
2255 note
= " resists a lot.";
2257 if (seen
) l_ptr
->flags3
|= (RF3_IM_COLD
);
2265 if (seen
) obvious
= TRUE
;
2266 if (r_ptr
->flags3
& (RF3_IM_POIS
))
2268 note
= " resists a lot.";
2270 if (seen
) l_ptr
->flags3
|= (RF3_IM_POIS
);
2275 /* Holy Orb -- hurts Evil */
2278 if (seen
) obvious
= TRUE
;
2279 if (r_ptr
->flags3
& (RF3_EVIL
))
2282 note
= " is hit hard.";
2283 if (seen
) l_ptr
->flags3
|= (RF3_EVIL
);
2288 /* Arrow -- no defense XXX */
2291 if (seen
) obvious
= TRUE
;
2298 if (seen
) obvious
= TRUE
;
2299 if (r_ptr
->flags3
& RF3_RES_PLAS
)
2302 dam
*= 3; dam
/= (randint(6)+6);
2303 if (seen
) l_ptr
->flags3
|= RF3_RES_PLAS
;
2308 /* Nether -- see above */
2311 if (seen
) obvious
= TRUE
;
2312 if (r_ptr
->flags3
& (RF3_UNDEAD
))
2314 note
= " is immune.";
2316 if (seen
) l_ptr
->flags3
|= (RF3_UNDEAD
);
2318 else if (r_ptr
->flags4
& (RF4_BR_NETH
))
2321 dam
*= 3; dam
/= (randint(6)+6);
2323 else if (r_ptr
->flags3
& (RF3_EVIL
))
2326 note
= " resists somewhat.";
2327 if (seen
) l_ptr
->flags3
|= (RF3_EVIL
);
2335 if (seen
) obvious
= TRUE
;
2336 if (r_ptr
->flags3
& RF3_IM_WATER
)
2338 note
= " is immune.";
2340 if (seen
) l_ptr
->flags3
|= RF3_IM_WATER
;
2345 /* Chaos -- Chaos breathers resist */
2348 if (seen
) obvious
= TRUE
;
2350 do_conf
= (5 + randint(11) + r
) / (r
+ 1);
2351 if (r_ptr
->flags4
& (RF4_BR_CHAO
))
2354 dam
*= 3; dam
/= (randint(6)+6);
2360 /* Shards -- Shard breathers resist */
2363 if (seen
) obvious
= TRUE
;
2364 if (r_ptr
->flags4
& (RF4_BR_SHAR
))
2367 dam
*= 3; dam
/= (randint(6)+6);
2372 /* Sound -- Sound breathers resist */
2375 if (seen
) obvious
= TRUE
;
2376 do_stun
= (10 + randint(15) + r
) / (r
+ 1);
2377 if (r_ptr
->flags4
& (RF4_BR_SOUN
))
2380 dam
*= 2; dam
/= (randint(6)+6);
2388 if (seen
) obvious
= TRUE
;
2389 do_conf
= (10 + randint(15) + r
) / (r
+ 1);
2390 if (r_ptr
->flags4
& (RF4_BR_CONF
))
2393 dam
*= 2; dam
/= (randint(6)+6);
2395 else if (r_ptr
->flags3
& (RF3_NO_CONF
))
2397 note
= " resists somewhat.";
2403 /* Disenchantment */
2406 if (seen
) obvious
= TRUE
;
2407 if (r_ptr
->flags3
& RF3_RES_DISE
)
2410 dam
*= 3; dam
/= (randint(6)+6);
2411 if (seen
) l_ptr
->flags3
|= RF3_RES_DISE
;
2419 if (seen
) obvious
= TRUE
;
2420 if (r_ptr
->flags3
& RF3_RES_NEXUS
)
2423 dam
*= 3; dam
/= (randint(6)+6);
2424 if (seen
) l_ptr
->flags3
|= RF3_RES_NEXUS
;
2432 if (seen
) obvious
= TRUE
;
2433 do_stun
= (randint(15) + r
) / (r
+ 1);
2434 if (r_ptr
->flags4
& (RF4_BR_WALL
))
2437 dam
*= 3; dam
/= (randint(6)+6);
2442 /* Inertia -- breathers resist */
2445 if (seen
) obvious
= TRUE
;
2446 if (r_ptr
->flags4
& (RF4_BR_INER
))
2449 dam
*= 3; dam
/= (randint(6)+6);
2454 /* Time -- breathers resist */
2457 if (seen
) obvious
= TRUE
;
2458 if (r_ptr
->flags4
& (RF4_BR_TIME
))
2461 dam
*= 3; dam
/= (randint(6)+6);
2466 /* Gravity -- breathers resist */
2469 if (seen
) obvious
= TRUE
;
2471 /* Higher level monsters can resist the teleportation better */
2472 if (randint(127) > r_ptr
->level
)
2475 if (r_ptr
->flags4
& (RF4_BR_GRAV
))
2478 dam
*= 3; dam
/= (randint(6)+6);
2487 if (seen
) obvious
= TRUE
;
2491 /* Meteor -- powerful magic missile */
2494 if (seen
) obvious
= TRUE
;
2498 /* Ice -- Cold + Cuts + Stun */
2501 if (seen
) obvious
= TRUE
;
2502 do_stun
= (randint(15) + 1) / (r
+ 1);
2503 if (r_ptr
->flags3
& (RF3_IM_COLD
))
2505 note
= " resists a lot.";
2507 if (seen
) l_ptr
->flags3
|= (RF3_IM_COLD
);
2516 if (seen
) obvious
= TRUE
;
2517 if ((r_ptr
->flags3
& (RF3_UNDEAD
)) ||
2518 (r_ptr
->flags3
& (RF3_DEMON
)) ||
2519 (strchr("Egv", r_ptr
->d_char
)))
2521 if (r_ptr
->flags3
& (RF3_UNDEAD
))
2523 if (seen
) l_ptr
->flags3
|= (RF3_UNDEAD
);
2525 if (r_ptr
->flags3
& (RF3_DEMON
))
2527 if (seen
) l_ptr
->flags3
|= (RF3_DEMON
);
2530 note
= " is unaffected!";
2538 /* Polymorph monster (Use "dam" as "power") */
2541 if (seen
) obvious
= TRUE
;
2543 /* Attempt to polymorph (see below) */
2546 /* Powerful monsters can resist */
2547 if ((r_ptr
->flags1
& (RF1_UNIQUE
)) ||
2548 (r_ptr
->level
> randint((dam
- 10) < 1 ? 1 : (dam
- 10)) + 10))
2550 note
= " is unaffected!";
2555 /* No "real" damage */
2562 /* Clone monsters (Ignore "dam") */
2565 if (seen
) obvious
= TRUE
;
2568 m_ptr
->hp
= m_ptr
->maxhp
;
2571 if (m_ptr
->mspeed
< 150) m_ptr
->mspeed
+= 10;
2573 /* Attempt to clone. */
2574 if (multiply_monster(cave_m_idx
[y
][x
]))
2579 /* No "real" damage */
2586 /* Heal Monster (use "dam" as amount of healing) */
2589 if (seen
) obvious
= TRUE
;
2598 if (m_ptr
->hp
> m_ptr
->maxhp
) m_ptr
->hp
= m_ptr
->maxhp
;
2600 /* Redraw (later) if needed */
2601 if (p_ptr
->health_who
== cave_m_idx
[y
][x
]) p_ptr
->redraw
|= (PR_HEALTH
);
2604 note
= " looks healthier.";
2606 /* No "real" damage */
2612 /* Speed Monster (Ignore "dam") */
2615 if (seen
) obvious
= TRUE
;
2618 if (m_ptr
->mspeed
< 150) m_ptr
->mspeed
+= 10;
2619 note
= " starts moving faster.";
2621 /* No "real" damage */
2627 /* Slow Monster (Use "dam" as "power") */
2630 if (seen
) obvious
= TRUE
;
2632 /* Powerful monsters can resist */
2633 if ((r_ptr
->flags1
& (RF1_UNIQUE
)) ||
2634 (r_ptr
->level
> randint((dam
- 10) < 1 ? 1 : (dam
- 10)) + 10))
2636 note
= " is unaffected!";
2640 /* Normal monsters slow down */
2643 if (m_ptr
->mspeed
> 60) m_ptr
->mspeed
-= 10;
2644 note
= " starts moving slower.";
2647 /* No "real" damage */
2653 /* Sleep (Use "dam" as "power") */
2656 if (seen
) obvious
= TRUE
;
2658 /* Attempt a saving throw */
2659 if ((r_ptr
->flags1
& (RF1_UNIQUE
)) ||
2660 (r_ptr
->flags3
& (RF3_NO_SLEEP
)) ||
2661 (r_ptr
->level
> randint((dam
- 10) < 1 ? 1 : (dam
- 10)) + 10))
2663 /* Memorize a flag */
2664 if (r_ptr
->flags3
& (RF3_NO_SLEEP
))
2666 if (seen
) l_ptr
->flags3
|= (RF3_NO_SLEEP
);
2669 /* No obvious effect */
2670 note
= " is unaffected!";
2675 /* Go to sleep (much) later */
2676 note
= " falls asleep!";
2680 /* No "real" damage */
2686 /* Confusion (Use "dam" as "power") */
2689 if (seen
) obvious
= TRUE
;
2691 /* Get confused later */
2692 do_conf
= damroll(3, (dam
/ 2)) + 1;
2694 /* Attempt a saving throw */
2695 if ((r_ptr
->flags1
& (RF1_UNIQUE
)) ||
2696 (r_ptr
->flags3
& (RF3_NO_CONF
)) ||
2697 (r_ptr
->level
> randint((dam
- 10) < 1 ? 1 : (dam
- 10)) + 10))
2699 /* Memorize a flag */
2700 if (r_ptr
->flags3
& (RF3_NO_CONF
))
2702 if (seen
) l_ptr
->flags3
|= (RF3_NO_CONF
);
2708 /* No obvious effect */
2709 note
= " is unaffected!";
2713 /* No "real" damage */
2720 /* Lite, but only hurts susceptible creatures */
2724 if (r_ptr
->flags3
& (RF3_HURT_LITE
))
2726 /* Obvious effect */
2727 if (seen
) obvious
= TRUE
;
2729 /* Memorize the effects */
2730 if (seen
) l_ptr
->flags3
|= (RF3_HURT_LITE
);
2732 /* Special effect */
2733 note
= " cringes from the light!";
2734 note_dies
= " shrivels away in the light!";
2737 /* Normally no damage */
2749 /* Lite -- opposite of Dark */
2752 if (seen
) obvious
= TRUE
;
2753 if (r_ptr
->flags4
& (RF4_BR_LITE
))
2756 dam
*= 2; dam
/= (randint(6)+6);
2758 else if (r_ptr
->flags3
& (RF3_HURT_LITE
))
2760 if (seen
) l_ptr
->flags3
|= (RF3_HURT_LITE
);
2761 note
= " cringes from the light!";
2762 note_dies
= " shrivels away in the light!";
2769 /* Dark -- opposite of Lite */
2772 if (seen
) obvious
= TRUE
;
2773 if (r_ptr
->flags4
& (RF4_BR_DARK
))
2776 dam
*= 2; dam
/= (randint(6)+6);
2785 /* Hurt by rock remover */
2786 if (r_ptr
->flags3
& (RF3_HURT_ROCK
))
2789 if (seen
) obvious
= TRUE
;
2791 /* Memorize the effects */
2792 if (seen
) l_ptr
->flags3
|= (RF3_HURT_ROCK
);
2794 /* Cute little message */
2795 note
= " loses some skin!";
2796 note_dies
= " dissolves!";
2799 /* Usually, ignore the effects */
2810 /* Teleport undead (Use "dam" as "power") */
2811 case GF_AWAY_UNDEAD
:
2813 /* Only affect undead */
2814 if (r_ptr
->flags3
& (RF3_UNDEAD
))
2816 if (seen
) obvious
= TRUE
;
2817 if (seen
) l_ptr
->flags3
|= (RF3_UNDEAD
);
2828 /* No "real" damage */
2834 /* Teleport evil (Use "dam" as "power") */
2837 /* Only affect undead */
2838 if (r_ptr
->flags3
& (RF3_EVIL
))
2840 if (seen
) obvious
= TRUE
;
2841 if (seen
) l_ptr
->flags3
|= (RF3_EVIL
);
2852 /* No "real" damage */
2858 /* Teleport monster (Use "dam" as "power") */
2862 if (seen
) obvious
= TRUE
;
2864 /* Prepare to teleport */
2867 /* No "real" damage */
2873 /* Turn undead (Use "dam" as "power") */
2874 case GF_TURN_UNDEAD
:
2876 /* Only affect undead */
2877 if (r_ptr
->flags3
& (RF3_UNDEAD
))
2879 /* Learn about type */
2880 if (seen
) l_ptr
->flags3
|= (RF3_UNDEAD
);
2883 if (seen
) obvious
= TRUE
;
2885 /* Apply some fear */
2886 do_fear
= damroll(3, (dam
/ 2)) + 1;
2888 /* Attempt a saving throw */
2889 if (r_ptr
->level
> randint((dam
- 10) < 1 ? 1 : (dam
- 10)) + 10)
2891 /* No obvious effect */
2892 note
= " is unaffected!";
2905 /* No "real" damage */
2911 /* Turn evil (Use "dam" as "power") */
2914 /* Only affect evil */
2915 if (r_ptr
->flags3
& (RF3_EVIL
))
2917 /* Learn about type */
2918 if (seen
) l_ptr
->flags3
|= (RF3_EVIL
);
2921 if (seen
) obvious
= TRUE
;
2923 /* Apply some fear */
2924 do_fear
= damroll(3, (dam
/ 2)) + 1;
2926 /* Attempt a saving throw */
2927 if (r_ptr
->level
> randint((dam
- 10) < 1 ? 1 : (dam
- 10)) + 10)
2929 /* No obvious effect */
2930 note
= " is unaffected!";
2943 /* No "real" damage */
2949 /* Turn monster (Use "dam" as "power") */
2953 if (seen
) obvious
= TRUE
;
2955 /* Apply some fear */
2956 do_fear
= damroll(3, (dam
/ 2)) + 1;
2958 /* Attempt a saving throw */
2959 if ((r_ptr
->flags1
& (RF1_UNIQUE
)) ||
2960 (r_ptr
->flags3
& (RF3_NO_FEAR
)) ||
2961 (r_ptr
->level
> randint((dam
- 10) < 1 ? 1 : (dam
- 10)) + 10))
2963 /* No obvious effect */
2964 note
= " is unaffected!";
2969 /* No "real" damage */
2976 case GF_DISP_UNDEAD
:
2978 /* Only affect undead */
2979 if (r_ptr
->flags3
& (RF3_UNDEAD
))
2981 /* Learn about type */
2982 if (seen
) l_ptr
->flags3
|= (RF3_UNDEAD
);
2985 if (seen
) obvious
= TRUE
;
2988 note
= " shudders.";
2989 note_dies
= " dissolves!";
3009 /* Only affect evil */
3010 if (r_ptr
->flags3
& (RF3_EVIL
))
3012 /* Learn about type */
3013 if (seen
) l_ptr
->flags3
|= (RF3_EVIL
);
3016 if (seen
) obvious
= TRUE
;
3019 note
= " shudders.";
3020 note_dies
= " dissolves!";
3037 /* Dispel monster */
3041 if (seen
) obvious
= TRUE
;
3044 note
= " shudders.";
3045 note_dies
= " dissolves!";
3065 /* Absolutely no effect */
3066 if (skipped
) return (FALSE
);
3069 /* "Unique" monsters cannot be polymorphed */
3070 if (r_ptr
->flags1
& (RF1_UNIQUE
)) do_poly
= FALSE
;
3073 /* "Unique" monsters can only be "killed" by the player */
3074 if (r_ptr
->flags1
& (RF1_UNIQUE
))
3076 /* Uniques may only be killed by the player */
3077 if ((who
> 0) && (dam
> m_ptr
->hp
)) dam
= m_ptr
->hp
;
3081 /* Check for death */
3082 if (dam
> m_ptr
->hp
)
3084 /* Extract method of death */
3088 /* Mega-Hack -- Handle "polymorph" -- monsters get a saving throw */
3089 else if (do_poly
&& (randint(90) > r_ptr
->level
))
3091 /* Default -- assume no polymorph */
3092 note
= " is unaffected!";
3094 /* Pick a "new" monster race */
3095 tmp
= poly_r_idx(m_ptr
->r_idx
);
3097 /* Handle polymorph */
3098 if (tmp
!= m_ptr
->r_idx
)
3101 if (seen
) obvious
= TRUE
;
3103 /* Monster polymorphs */
3106 /* Turn off the damage */
3109 /* "Kill" the "old" monster */
3110 delete_monster_idx(cave_m_idx
[y
][x
]);
3112 /* Create a new monster (no groups) */
3113 (void)place_monster_aux(y
, x
, tmp
, FALSE
, FALSE
);
3115 /* Hack -- Assume success XXX XXX XXX */
3117 /* Hack -- Get new monster */
3118 m_ptr
= &mon_list
[cave_m_idx
[y
][x
]];
3120 /* Hack -- Get new race */
3121 r_ptr
= &r_info
[m_ptr
->r_idx
];
3125 /* Handle "teleport" */
3129 if (seen
) obvious
= TRUE
;
3132 note
= " disappears!";
3135 teleport_away(cave_m_idx
[y
][x
], do_dist
);
3137 /* Hack -- get new location */
3142 /* Sound and Impact breathers never stun */
3144 !(r_ptr
->flags4
& (RF4_BR_SOUN
)) &&
3145 !(r_ptr
->flags4
& (RF4_BR_WALL
)))
3148 if (seen
) obvious
= TRUE
;
3153 note
= " is more dazed.";
3154 tmp
= m_ptr
->stunned
+ (do_stun
/ 2);
3158 note
= " is dazed.";
3163 m_ptr
->stunned
= (tmp
< 200) ? tmp
: 200;
3166 /* Confusion and Chaos breathers (and sleepers) never confuse */
3168 !(r_ptr
->flags3
& (RF3_NO_CONF
)) &&
3169 !(r_ptr
->flags4
& (RF4_BR_CONF
)) &&
3170 !(r_ptr
->flags4
& (RF4_BR_CHAO
)))
3173 if (seen
) obvious
= TRUE
;
3175 /* Already partially confused */
3176 if (m_ptr
->confused
)
3178 note
= " looks more confused.";
3179 tmp
= m_ptr
->confused
+ (do_conf
/ 2);
3182 /* Was not confused */
3185 note
= " looks confused.";
3189 /* Apply confusion */
3190 m_ptr
->confused
= (tmp
< 200) ? tmp
: 200;
3198 tmp
= m_ptr
->monfear
+ do_fear
;
3201 m_ptr
->monfear
= (tmp
< 200) ? tmp
: 200;
3205 /* If another monster did the damage, hurt the monster by hand */
3208 /* Redraw (later) if needed */
3209 if (p_ptr
->health_who
== cave_m_idx
[y
][x
]) p_ptr
->redraw
|= (PR_HEALTH
);
3211 /* Wake the monster up */
3214 /* Hurt the monster */
3220 /* Generate treasure, etc */
3221 monster_death(cave_m_idx
[y
][x
]);
3223 /* Delete the monster */
3224 delete_monster_idx(cave_m_idx
[y
][x
]);
3226 /* Give detailed messages if destroyed */
3227 if (note
) msg_format("%^s%s", m_name
, note
);
3230 /* Damaged monster */
3233 /* Give detailed messages if visible or destroyed */
3234 if (note
&& seen
) msg_format("%^s%s", m_name
, note
);
3236 /* Hack -- Pain message */
3237 else if (dam
> 0) message_pain(cave_m_idx
[y
][x
], dam
);
3239 /* Hack -- handle sleep */
3240 if (do_sleep
) m_ptr
->csleep
= do_sleep
;
3244 /* If the player did it, give him experience, check fear */
3249 /* Hurt the monster, check for fear and death */
3250 if (mon_take_hit(cave_m_idx
[y
][x
], dam
, &fear
, note_dies
))
3255 /* Damaged monster */
3258 /* Give detailed messages if visible or destroyed */
3259 if (note
&& seen
) msg_format("%^s%s", m_name
, note
);
3261 /* Hack -- Pain message */
3262 else if (dam
> 0) message_pain(cave_m_idx
[y
][x
], dam
);
3265 if ((fear
|| do_fear
) && (m_ptr
->ml
))
3268 message_format(MSG_FLEE
, m_ptr
->r_idx
,
3269 "%^s flees in terror!", m_name
);
3272 /* Hack -- handle sleep */
3273 if (do_sleep
) m_ptr
->csleep
= do_sleep
;
3278 /* Verify this code XXX XXX XXX */
3280 /* Update the monster */
3281 update_mon(cave_m_idx
[y
][x
], FALSE
);
3283 /* Redraw the monster grid */
3287 /* Update monster recall window */
3288 if (p_ptr
->monster_race_idx
== m_ptr
->r_idx
)
3291 p_ptr
->window
|= (PW_MONSTER
);
3301 /* Return "Anything seen?" */
3311 * Helper function for "project()" below.
3313 * Handle a beam/bolt/ball causing damage to the player.
3315 * This routine takes a "source monster" (by index), a "distance", a default
3316 * "damage", and a "damage type". See "project_m()" above.
3318 * If "rad" is non-zero, then the blast was centered elsewhere, and the damage
3319 * is reduced (see "project_m()" above). This can happen if a monster breathes
3320 * at the player and hits a wall instead.
3322 * We return "TRUE" if any "obvious" effects were observed.
3324 * Actually, for historical reasons, we just assume that the effects were
3325 * obvious. XXX XXX XXX
3327 static bool project_p(int who
, int r
, int y
, int x
, int dam
, int typ
)
3331 /* Hack -- assume obvious */
3332 bool obvious
= TRUE
;
3334 /* Player blind-ness */
3335 bool blind
= (p_ptr
->timed
[TMD_BLIND
] ? TRUE
: FALSE
);
3337 /* Source monster */
3338 monster_type
*m_ptr
;
3340 /* Monster name (for attacks) */
3343 /* Monster name (for damage) */
3346 /* Hack -- messages */
3350 /* No player here */
3351 if (!(cave_m_idx
[y
][x
] < 0)) return (FALSE
);
3353 /* Never affect projector */
3354 if (cave_m_idx
[y
][x
] == who
) return (FALSE
);
3357 /* Limit maximum damage XXX XXX XXX */
3358 if (dam
> 1600) dam
= 1600;
3360 /* Reduce damage by distance */
3361 dam
= (dam
+ r
) / (r
+ 1);
3364 /* Get the source monster */
3365 m_ptr
= &mon_list
[who
];
3367 /* Get the monster name */
3368 monster_desc(m_name
, sizeof(m_name
), m_ptr
, 0);
3370 /* Get the monster's real name */
3371 monster_desc(killer
, sizeof(killer
), m_ptr
, 0x88);
3374 /* Analyze the damage */
3377 /* Standard damage -- hurts inventory too */
3380 if (blind
) msg_print("You are hit by acid!");
3381 acid_dam(dam
, killer
);
3385 /* Standard damage -- hurts inventory too */
3388 if (blind
) msg_print("You are hit by fire!");
3389 fire_dam(dam
, killer
);
3393 /* Standard damage -- hurts inventory too */
3396 if (blind
) msg_print("You are hit by cold!");
3397 cold_dam(dam
, killer
);
3401 /* Standard damage -- hurts inventory too */
3404 if (blind
) msg_print("You are hit by lightning!");
3405 elec_dam(dam
, killer
);
3409 /* Standard damage -- also poisons player */
3412 if (blind
) msg_print("You are hit by poison!");
3413 if (p_ptr
->resist_pois
) dam
= (dam
+ 2) / 3;
3414 if (p_ptr
->timed
[TMD_OPP_POIS
]) dam
= (dam
+ 2) / 3;
3415 take_hit(dam
, killer
);
3416 if (!(p_ptr
->resist_pois
|| p_ptr
->timed
[TMD_OPP_POIS
]))
3418 (void)inc_timed(TMD_POISONED
, rand_int(dam
) + 10);
3423 /* Standard damage */
3426 if (blind
) msg_print("You are hit by something!");
3427 take_hit(dam
, killer
);
3431 /* Holy Orb -- Player only takes partial damage */
3434 if (blind
) msg_print("You are hit by something!");
3436 take_hit(dam
, killer
);
3440 /* Arrow -- no dodging XXX */
3443 if (blind
) msg_print("You are hit by something sharp!");
3444 take_hit(dam
, killer
);
3448 /* Plasma -- No resist XXX */
3451 if (blind
) msg_print("You are hit by something!");
3452 take_hit(dam
, killer
);
3453 if (!p_ptr
->resist_sound
)
3455 int k
= (randint((dam
> 40) ? 35 : (dam
* 3 / 4 + 5)));
3456 (void)inc_timed(TMD_STUN
, k
);
3461 /* Nether -- drain experience */
3464 if (blind
) msg_print("You are hit by something strange!");
3465 if (p_ptr
->resist_nethr
)
3467 dam
*= 6; dam
/= (randint(6) + 6);
3471 if (p_ptr
->hold_life
&& (rand_int(100) < 75))
3473 msg_print("You keep hold of your life force!");
3477 s32b d
= 200 + (p_ptr
->exp
/ 100) * MON_DRAIN_LIFE
;
3479 if (p_ptr
->hold_life
)
3481 msg_print("You feel your life slipping away!");
3486 msg_print("You feel your life draining away!");
3491 take_hit(dam
, killer
);
3495 /* Water -- stun/confuse */
3498 if (blind
) msg_print("You are hit by something!");
3499 if (!p_ptr
->resist_sound
)
3501 (void)inc_timed(TMD_STUN
, randint(40));
3503 if (!p_ptr
->resist_confu
)
3505 (void)inc_timed(TMD_CONFUSED
, randint(5) + 5);
3507 take_hit(dam
, killer
);
3511 /* Chaos -- many effects */
3514 if (blind
) msg_print("You are hit by something strange!");
3515 if (p_ptr
->resist_chaos
)
3517 dam
*= 6; dam
/= (randint(6) + 6);
3519 if (!p_ptr
->resist_confu
&& !p_ptr
->resist_chaos
)
3521 (void)inc_timed(TMD_CONFUSED
, rand_int(20) + 10);
3523 if (!p_ptr
->resist_chaos
)
3525 (void)inc_timed(TMD_IMAGE
, randint(10));
3527 if (!p_ptr
->resist_nethr
&& !p_ptr
->resist_chaos
)
3529 if (p_ptr
->hold_life
&& (rand_int(100) < 75))
3531 msg_print("You keep hold of your life force!");
3535 s32b d
= 5000 + (p_ptr
->exp
/ 100) * MON_DRAIN_LIFE
;
3537 if (p_ptr
->hold_life
)
3539 msg_print("You feel your life slipping away!");
3544 msg_print("You feel your life draining away!");
3549 take_hit(dam
, killer
);
3553 /* Shards -- mostly cutting */
3556 if (blind
) msg_print("You are hit by something sharp!");
3557 if (p_ptr
->resist_shard
)
3559 dam
*= 6; dam
/= (randint(6) + 6);
3563 (void)inc_timed(TMD_CUT
, dam
);
3565 take_hit(dam
, killer
);
3569 /* Sound -- mostly stunning */
3572 if (blind
) msg_print("You are hit by something!");
3573 if (p_ptr
->resist_sound
)
3575 dam
*= 5; dam
/= (randint(6) + 6);
3579 int k
= (randint((dam
> 90) ? 35 : (dam
/ 3 + 5)));
3580 (void)inc_timed(TMD_STUN
, k
);
3582 take_hit(dam
, killer
);
3586 /* Pure confusion */
3589 if (blind
) msg_print("You are hit by something!");
3590 if (p_ptr
->resist_confu
)
3592 dam
*= 5; dam
/= (randint(6) + 6);
3594 if (!p_ptr
->resist_confu
)
3596 (void)inc_timed(TMD_CONFUSED
, randint(20) + 10);
3598 take_hit(dam
, killer
);
3602 /* Disenchantment -- see above */
3605 if (blind
) msg_print("You are hit by something strange!");
3606 if (p_ptr
->resist_disen
)
3608 dam
*= 6; dam
/= (randint(6) + 6);
3612 (void)apply_disenchant(0);
3614 take_hit(dam
, killer
);
3618 /* Nexus -- see above */
3621 if (blind
) msg_print("You are hit by something strange!");
3622 if (p_ptr
->resist_nexus
)
3624 dam
*= 6; dam
/= (randint(6) + 6);
3630 take_hit(dam
, killer
);
3634 /* Force -- mostly stun */
3637 if (blind
) msg_print("You are hit by something!");
3638 if (!p_ptr
->resist_sound
)
3640 (void)inc_timed(TMD_STUN
, randint(20));
3642 take_hit(dam
, killer
);
3646 /* Inertia -- slowness */
3649 if (blind
) msg_print("You are hit by something strange!");
3650 (void)inc_timed(TMD_SLOW
, rand_int(4) + 4);
3651 take_hit(dam
, killer
);
3655 /* Lite -- blinding */
3658 if (blind
) msg_print("You are hit by something!");
3659 if (p_ptr
->resist_lite
)
3661 dam
*= 4; dam
/= (randint(6) + 6);
3663 else if (!blind
&& !p_ptr
->resist_blind
)
3665 (void)inc_timed(TMD_BLIND
, randint(5) + 2);
3667 take_hit(dam
, killer
);
3671 /* Dark -- blinding */
3674 if (blind
) msg_print("You are hit by something!");
3675 if (p_ptr
->resist_dark
)
3677 dam
*= 4; dam
/= (randint(6) + 6);
3679 else if (!blind
&& !p_ptr
->resist_blind
)
3681 (void)inc_timed(TMD_BLIND
, randint(5) + 2);
3683 take_hit(dam
, killer
);
3687 /* Time -- bolt fewer effects XXX */
3690 if (blind
) msg_print("You are hit by something strange!");
3692 switch (randint(10))
3694 case 1: case 2: case 3: case 4: case 5:
3696 msg_print("You feel life has clocked back.");
3697 lose_exp(100 + (p_ptr
->exp
/ 100) * MON_DRAIN_LIFE
);
3701 case 6: case 7: case 8: case 9:
3705 case 1: k
= A_STR
; act
= "strong"; break;
3706 case 2: k
= A_INT
; act
= "bright"; break;
3707 case 3: k
= A_WIS
; act
= "wise"; break;
3708 case 4: k
= A_DEX
; act
= "agile"; break;
3709 case 5: k
= A_CON
; act
= "hale"; break;
3710 case 6: k
= A_CHR
; act
= "beautiful"; break;
3713 msg_format("You're not as %s as you used to be...", act
);
3715 p_ptr
->stat_cur
[k
] = (p_ptr
->stat_cur
[k
] * 3) / 4;
3716 if (p_ptr
->stat_cur
[k
] < 3) p_ptr
->stat_cur
[k
] = 3;
3717 p_ptr
->update
|= (PU_BONUS
);
3723 msg_print("You're not as powerful as you used to be...");
3725 for (k
= 0; k
< A_MAX
; k
++)
3727 p_ptr
->stat_cur
[k
] = (p_ptr
->stat_cur
[k
] * 3) / 4;
3728 if (p_ptr
->stat_cur
[k
] < 3) p_ptr
->stat_cur
[k
] = 3;
3730 p_ptr
->update
|= (PU_BONUS
);
3734 take_hit(dam
, killer
);
3738 /* Gravity -- stun plus slowness plus teleport */
3741 if (blind
) msg_print("You are hit by something strange!");
3742 msg_print("Gravity warps around you.");
3744 /* Higher level players can resist the teleportation better */
3745 if (randint(127) > p_ptr
->lev
)
3748 (void)inc_timed(TMD_SLOW
, rand_int(4) + 4);
3749 if (!p_ptr
->resist_sound
)
3751 int k
= (randint((dam
> 90) ? 35 : (dam
/ 3 + 5)));
3752 (void)inc_timed(TMD_STUN
, k
);
3754 take_hit(dam
, killer
);
3761 if (blind
) msg_print("You are hit by something!");
3762 take_hit(dam
, killer
);
3769 if (blind
) msg_print("You are hit by something!");
3770 take_hit(dam
, killer
);
3774 /* Ice -- cold plus stun plus cuts */
3777 if (blind
) msg_print("You are hit by something sharp!");
3778 cold_dam(dam
, killer
);
3779 if (!p_ptr
->resist_shard
)
3781 (void)inc_timed(TMD_CUT
, damroll(5, 8));
3783 if (!p_ptr
->resist_sound
)
3785 (void)inc_timed(TMD_STUN
, randint(15));
3806 /* Return "Anything seen?" */
3815 * Generic "beam"/"bolt"/"ball" projection routine.
3818 * who: Index of "source" monster (negative for "player")
3819 * rad: Radius of explosion (0 = beam/bolt, 1 to 9 = ball)
3820 * y,x: Target location (or location to travel "towards")
3821 * dam: Base damage roll to apply to affected monsters (or player)
3822 * typ: Type of damage to apply to monsters (and objects)
3823 * flg: Extra bit flags (see PROJECT_xxxx in "defines.h")
3826 * TRUE if any "effects" of the projection were observed, else FALSE
3828 * Allows a monster (or player) to project a beam/bolt/ball of a given kind
3829 * towards a given location (optionally passing over the heads of interposing
3830 * monsters), and have it do a given amount of damage to the monsters (and
3831 * optionally objects) within the given radius of the final location.
3833 * A "bolt" travels from source to target and affects only the target grid.
3834 * A "beam" travels from source to target, affecting all grids passed through.
3835 * A "ball" travels from source to the target, exploding at the target, and
3836 * affecting everything within the given radius of the target location.
3838 * Traditionally, a "bolt" does not affect anything on the ground, and does
3839 * not pass over the heads of interposing monsters, much like a traditional
3840 * missile, and will "stop" abruptly at the "target" even if no monster is
3841 * positioned there, while a "ball", on the other hand, passes over the heads
3842 * of monsters between the source and target, and affects everything except
3843 * the source monster which lies within the final radius, while a "beam"
3844 * affects every monster between the source and target, except for the casting
3845 * monster (or player), and rarely affects things on the ground.
3847 * Two special flags allow us to use this function in special ways, the
3848 * "PROJECT_HIDE" flag allows us to perform "invisible" projections, while
3849 * the "PROJECT_JUMP" flag allows us to affect a specific grid, without
3850 * actually projecting from the source monster (or player).
3852 * The player will only get "experience" for monsters killed by himself
3853 * Unique monsters can only be destroyed by attacks from the player
3855 * Only 256 grids can be affected per projection, limiting the effective
3856 * "radius" of standard ball attacks to nine units (diameter nineteen).
3858 * One can project in a given "direction" by combining PROJECT_THRU with small
3859 * offsets to the initial location (see "line_spell()"), or by calculating
3860 * "virtual targets" far away from the player.
3862 * One can also use PROJECT_THRU to send a beam/bolt along an angled path,
3863 * continuing until it actually hits somethings (useful for "stone to mud").
3865 * Bolts and Beams explode INSIDE walls, so that they can destroy doors.
3867 * Balls must explode BEFORE hitting walls, or they would affect monsters
3868 * on both sides of a wall. Some bug reports indicate that this is still
3869 * happening in 2.7.8 for Windows, though it appears to be impossible.
3871 * We "pre-calculate" the blast area only in part for efficiency.
3872 * More importantly, this lets us do "explosions" from the "inside" out.
3873 * This results in a more logical distribution of "blast" treasure.
3874 * It also produces a better (in my opinion) animation of the explosion.
3875 * It could be (but is not) used to have the treasure dropped by monsters
3876 * in the middle of the explosion fall "outwards", and then be damaged by
3877 * the blast as it spreads outwards towards the treasure drop location.
3879 * Walls and doors are included in the blast area, so that they can be
3880 * "burned" or "melted" in later versions.
3882 * This algorithm is intended to maximize simplicity, not necessarily
3883 * efficiency, since this function is not a bottleneck in the code.
3885 * We apply the blast effect from ground zero outwards, in several passes,
3886 * first affecting features, then objects, then monsters, then the player.
3887 * This allows walls to be removed before checking the object or monster
3888 * in the wall, and protects objects which are dropped by monsters killed
3889 * in the blast, and allows the player to see all affects before he is
3890 * killed or teleported away. The semantics of this method are open to
3891 * various interpretations, but they seem to work well in practice.
3893 * We process the blast area from ground-zero outwards to allow for better
3894 * distribution of treasure dropped by monsters, and because it provides a
3895 * pleasing visual effect at low cost.
3897 * Note that the damage done by "ball" explosions decreases with distance.
3898 * This decrease is rapid, grids at radius "dist" take "1/dist" damage.
3900 * Notice the "napalm" effect of "beam" weapons. First they "project" to
3901 * the target, and then the damage "flows" along this beam of destruction.
3902 * The damage at every grid is the same as at the "center" of a "ball"
3903 * explosion, since the "beam" grids are treated as if they ARE at the
3904 * center of a "ball" explosion.
3906 * Currently, specifying "beam" plus "ball" means that locations which are
3907 * covered by the initial "beam", and also covered by the final "ball", except
3908 * for the final grid (the epicenter of the ball), will be "hit twice", once
3909 * by the initial beam, and once by the exploding ball. For the grid right
3910 * next to the epicenter, this results in 150% damage being done. The center
3911 * does not have this problem, for the same reason the final grid in a "beam"
3912 * plus "bolt" does not -- it is explicitly removed. Simply removing "beam"
3913 * grids which are covered by the "ball" will NOT work, as then they will
3914 * receive LESS damage than they should. Do not combine "beam" with "ball".
3916 * The array "gy[],gx[]" with current size "grids" is used to hold the
3917 * collected locations of all grids in the "blast area" plus "beam path".
3919 * Note the rather complex usage of the "gm[]" array. First, gm[0] is always
3920 * zero. Second, for N>1, gm[N] is always the index (in gy[],gx[]) of the
3921 * first blast grid (see above) with radius "N" from the blast center. Note
3922 * that only the first gm[1] grids in the blast area thus take full damage.
3923 * Also, note that gm[rad+1] is always equal to "grids", which is the total
3924 * number of blast grids.
3926 * Note that once the projection is complete, (y2,x2) holds the final location
3927 * of bolts/beams, and the "epicenter" of balls.
3929 * Note also that "rad" specifies the "inclusive" radius of projection blast,
3930 * so that a "rad" of "one" actually covers 5 or 9 grids, depending on the
3931 * implementation of the "distance" function. Also, a bolt can be properly
3932 * viewed as a "ball" with a "rad" of "zero".
3934 * Note that if no "target" is reached before the beam/bolt/ball travels the
3935 * maximum distance allowed (MAX_RANGE), no "blast" will be induced. This
3936 * may be relevant even for bolts, since they have a "1x1" mini-blast.
3938 * Note that for consistency, we "pretend" that the bolt actually takes "time"
3939 * to move from point A to point B, even if the player cannot see part of the
3940 * projection path. Note that in general, the player will *always* see part
3941 * of the path, since it either starts at the player or ends on the player.
3943 * Hack -- we assume that every "projection" is "self-illuminating".
3945 * Hack -- when only a single monster is affected, we automatically track
3946 * (and recall) that monster, unless "PROJECT_JUMP" is used.
3948 * Note that all projections now "explode" at their final destination, even
3949 * if they were being projected at a more distant destination. This means
3950 * that "ball" spells will *always* explode.
3952 * Note that we must call "handle_stuff()" after affecting terrain features
3953 * in the blast radius, in case the "illumination" of the grid was changed,
3954 * and "update_view()" and "update_monsters()" need to be called.
3956 bool project(int who
, int rad
, int y
, int x
, int dam
, int typ
, int flg
)
3966 int msec
= op_ptr
->delay_factor
* op_ptr
->delay_factor
;
3968 /* Assume the player sees nothing */
3969 bool notice
= FALSE
;
3971 /* Assume the player has seen nothing */
3972 bool visual
= FALSE
;
3974 /* Assume the player has seen no blast grids */
3977 /* Is the player blind? */
3978 bool blind
= (p_ptr
->timed
[TMD_BLIND
] ? TRUE
: FALSE
);
3980 /* Number of grids in the "path" */
3983 /* Actual grids in the "path" */
3986 /* Number of grids in the "blast area" (including the "beam" path) */
3989 /* Coordinates of the affected grids */
3990 byte gx
[256], gy
[256];
3992 /* Encoded "radius" info (see above) */
3996 /* Hack -- Jump to target */
3997 if (flg
& (PROJECT_JUMP
))
4002 /* Clear the flag */
4003 flg
&= ~(PROJECT_JUMP
);
4006 /* Start at player */
4013 /* Start at monster */
4016 x1
= mon_list
[who
].fx
;
4017 y1
= mon_list
[who
].fy
;
4028 /* Default "destination" */
4033 /* Hack -- verify stuff */
4034 if (flg
& (PROJECT_THRU
))
4036 if ((x1
== x2
) && (y1
== y2
))
4038 flg
&= ~(PROJECT_THRU
);
4043 /* Hack -- Assume there will be no blast (max radius 16) */
4044 for (dist
= 0; dist
< 16; dist
++) gm
[dist
] = 0;
4051 /* Collect beam grids */
4052 if (flg
& (PROJECT_BEAM
))
4060 /* Calculate the projection path */
4061 path_n
= project_path(path_g
, MAX_RANGE
, y1
, x1
, y2
, x2
, flg
);
4064 /* Hack -- Handle stuff */
4067 /* Project along the path */
4068 for (i
= 0; i
< path_n
; ++i
)
4073 int ny
= GRID_Y(path_g
[i
]);
4074 int nx
= GRID_X(path_g
[i
]);
4076 /* Hack -- Balls explode before reaching walls */
4077 if (!cave_floor_bold(ny
, nx
) && (rad
> 0)) break;
4083 /* Collect beam grids */
4084 if (flg
& (PROJECT_BEAM
))
4091 /* Only do visuals if requested */
4092 if (!blind
&& !(flg
& (PROJECT_HIDE
)))
4094 /* Only do visuals if the player can "see" the bolt */
4095 if (player_has_los_bold(y
, x
))
4102 /* Obtain the bolt pict */
4103 p
= bolt_pict(oy
, ox
, y
, x
, typ
);
4105 /* Extract attr/char */
4109 /* Visual effects */
4110 print_rel(c
, a
, y
, x
);
4111 move_cursor_relative(y
, x
);
4114 if (p_ptr
->window
) window_stuff();
4116 Term_xtra(TERM_XTRA_DELAY
, msec
);
4121 if (p_ptr
->window
) window_stuff();
4123 /* Display "beam" grids */
4124 if (flg
& (PROJECT_BEAM
))
4126 /* Obtain the explosion pict */
4127 p
= bolt_pict(y
, x
, y
, x
, typ
);
4129 /* Extract attr/char */
4133 /* Visual effects */
4134 print_rel(c
, a
, y
, x
);
4137 /* Hack -- Activate delay */
4141 /* Hack -- delay anyway for consistency */
4144 /* Delay for consistency */
4145 Term_xtra(TERM_XTRA_DELAY
, msec
);
4151 /* Save the "blast epicenter" */
4155 /* Start the "explosion" */
4158 /* Hack -- make sure beams get to "explode" */
4162 /* Hack -- remove final beam grid */
4163 if (flg
& (PROJECT_BEAM
))
4168 /* Determine the blast area, work from the inside out */
4169 for (dist
= 0; dist
<= rad
; dist
++)
4171 /* Scan the maximal blast area of radius "dist" */
4172 for (y
= y2
- dist
; y
<= y2
+ dist
; y
++)
4174 for (x
= x2
- dist
; x
<= x2
+ dist
; x
++)
4176 /* Ignore "illegal" locations */
4177 if (!in_bounds(y
, x
)) continue;
4179 /* Enforce a "circular" explosion */
4180 if (distance(y2
, x2
, y
, x
) != dist
) continue;
4182 /* Ball explosions are stopped by walls */
4183 if (!los(y2
, x2
, y
, x
)) continue;
4185 /* Save this grid */
4192 /* Encode some more "radius" info */
4197 /* Speed -- ignore "non-explosions" */
4198 if (!grids
) return (FALSE
);
4201 /* Display the "blast area" if requested */
4202 if (!blind
&& !(flg
& (PROJECT_HIDE
)))
4204 /* Then do the "blast", from inside out */
4205 for (t
= 0; t
<= rad
; t
++)
4207 /* Dump everything with this radius */
4208 for (i
= gm
[t
]; i
< gm
[t
+1]; i
++)
4210 /* Extract the location */
4214 /* Only do visuals if the player can "see" the blast */
4215 if (player_has_los_bold(y
, x
))
4224 /* Obtain the explosion pict */
4225 p
= bolt_pict(y
, x
, y
, x
, typ
);
4227 /* Extract attr/char */
4231 /* Visual effects -- Display */
4232 print_rel(c
, a
, y
, x
);
4236 /* Hack -- center the cursor */
4237 move_cursor_relative(y2
, x2
);
4239 /* Flush each "radius" separately */
4243 if (p_ptr
->window
) window_stuff();
4245 /* Delay (efficiently) */
4246 if (visual
|| drawn
)
4248 Term_xtra(TERM_XTRA_DELAY
, msec
);
4252 /* Flush the erasing */
4255 /* Erase the explosion drawn above */
4256 for (i
= 0; i
< grids
; i
++)
4258 /* Extract the location */
4262 /* Hack -- Erase if needed */
4263 if (player_has_los_bold(y
, x
))
4269 /* Hack -- center the cursor */
4270 move_cursor_relative(y2
, x2
);
4272 /* Flush the explosion */
4276 if (p_ptr
->window
) window_stuff();
4281 /* Check features */
4282 if (flg
& (PROJECT_GRID
))
4284 /* Start with "dist" of zero */
4287 /* Scan for features */
4288 for (i
= 0; i
< grids
; i
++)
4290 /* Hack -- Notice new "dist" values */
4291 if (gm
[dist
+1] == i
) dist
++;
4293 /* Get the grid location */
4297 /* Affect the feature in that grid */
4298 if (project_f(who
, dist
, y
, x
, dam
, typ
)) notice
= TRUE
;
4303 /* Update stuff if needed */
4304 if (p_ptr
->update
) update_stuff();
4308 if (flg
& (PROJECT_ITEM
))
4310 /* Start with "dist" of zero */
4313 /* Scan for objects */
4314 for (i
= 0; i
< grids
; i
++)
4316 /* Hack -- Notice new "dist" values */
4317 if (gm
[dist
+1] == i
) dist
++;
4319 /* Get the grid location */
4323 /* Affect the object in the grid */
4324 if (project_o(who
, dist
, y
, x
, dam
, typ
)) notice
= TRUE
;
4329 /* Check monsters */
4330 if (flg
& (PROJECT_KILL
))
4337 /* Start with "dist" of zero */
4340 /* Scan for monsters */
4341 for (i
= 0; i
< grids
; i
++)
4343 /* Hack -- Notice new "dist" values */
4344 if (gm
[dist
+1] == i
) dist
++;
4346 /* Get the grid location */
4350 /* Affect the monster in the grid */
4351 if (project_m(who
, dist
, y
, x
, dam
, typ
)) notice
= TRUE
;
4354 /* Player affected one monster (without "jumping") */
4355 if ((who
< 0) && (project_m_n
== 1) && !(flg
& (PROJECT_JUMP
)))
4361 /* Track if possible */
4362 if (cave_m_idx
[y
][x
] > 0)
4364 monster_type
*m_ptr
= &mon_list
[cave_m_idx
[y
][x
]];
4366 /* Hack -- auto-recall */
4367 if (m_ptr
->ml
) monster_race_track(m_ptr
->r_idx
);
4369 /* Hack - auto-track */
4370 if (m_ptr
->ml
) health_track(cave_m_idx
[y
][x
]);
4377 if (flg
& (PROJECT_KILL
))
4379 /* Start with "dist" of zero */
4382 /* Scan for player */
4383 for (i
= 0; i
< grids
; i
++)
4385 /* Hack -- Notice new "dist" values */
4386 if (gm
[dist
+1] == i
) dist
++;
4388 /* Get the grid location */
4392 /* Affect the player */
4393 if (project_p(who
, dist
, y
, x
, dam
, typ
))
4397 /* Only affect the player once */
4404 /* Return "something was noticed" */