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.
18 * Increase players hit points, notice effects
20 bool hp_player(int num
)
23 if (p_ptr
->chp
< p_ptr
->mhp
)
29 if (p_ptr
->chp
>= p_ptr
->mhp
)
31 p_ptr
->chp
= p_ptr
->mhp
;
36 p_ptr
->redraw
|= (PR_HP
);
39 p_ptr
->window
|= (PW_PLAYER_0
| PW_PLAYER_1
);
44 msg_print("You feel a little better.");
50 msg_print("You feel better.");
56 msg_print("You feel much better.");
62 msg_print("You feel very good.");
76 * Leave a "glyph of warding" which prevents monster movement
78 void warding_glyph(void)
84 if (cave_feat
[py
][px
] != FEAT_FLOOR
)
86 msg_print("There is no clear floor on which to cast the spell.");
91 cave_set_feat(py
, px
, FEAT_GLYPH
);
93 /* Shift any objects to further away */
94 for (o_ptr
= get_first_object(py
, px
); o_ptr
; o_ptr
= get_next_object(o_ptr
))
96 drop_near(o_ptr
, 0, py
, px
);
99 /* Delete the "moved" objects from their original position */
100 delete_object(py
, px
);
107 * Array of stat "descriptions"
109 static cptr desc_stat_pos
[] =
121 * Array of stat "descriptions"
123 static cptr desc_stat_neg
[] =
137 bool do_dec_stat(int stat
)
141 /* Get the "sustain" */
144 case A_STR
: if (p_ptr
->sustain_str
) sust
= TRUE
; break;
145 case A_INT
: if (p_ptr
->sustain_int
) sust
= TRUE
; break;
146 case A_WIS
: if (p_ptr
->sustain_wis
) sust
= TRUE
; break;
147 case A_DEX
: if (p_ptr
->sustain_dex
) sust
= TRUE
; break;
148 case A_CON
: if (p_ptr
->sustain_con
) sust
= TRUE
; break;
149 case A_CHR
: if (p_ptr
->sustain_chr
) sust
= TRUE
; break;
156 msg_format("You feel very %s for a moment, but the feeling passes.",
157 desc_stat_neg
[stat
]);
163 /* Attempt to reduce the stat */
164 if (dec_stat(stat
, 10, FALSE
))
167 message_format(MSG_DRAIN_STAT
, stat
, "You feel very %s.", desc_stat_neg
[stat
]);
173 /* Nothing obvious */
179 * Restore lost "points" in a stat
181 bool do_res_stat(int stat
)
183 /* Attempt to increase */
187 msg_format("You feel less %s.", desc_stat_neg
[stat
]);
193 /* Nothing obvious */
199 * Gain a "point" in a stat
201 bool do_inc_stat(int stat
)
205 /* Restore strength */
206 res
= res_stat(stat
);
208 /* Attempt to increase */
212 msg_format("You feel very %s!", desc_stat_pos
[stat
]);
218 /* Restoration worked */
222 msg_format("You feel less %s.", desc_stat_neg
[stat
]);
228 /* Nothing obvious */
235 * Identify everything being carried.
236 * Done by a potion of "self knowledge".
238 void identify_pack(void)
242 /* Simply identify and know every item */
243 for (i
= 0; i
< INVEN_TOTAL
; i
++)
245 object_type
*o_ptr
= &inventory
[i
];
247 /* Skip non-objects */
248 if (!o_ptr
->k_idx
) continue;
250 /* Aware and Known */
251 if (object_known_p(o_ptr
)) continue;
254 do_ident_item(i
, o_ptr
);
256 /* repeat with same slot */
267 * Used by the "enchant" function (chance of failure)
269 static const int enchant_table
[16] =
272 300, 400, 500, 700, 950,
273 990, 992, 995, 997, 999,
279 * Hack -- Removes curse from an object.
281 static void uncurse_object(object_type
*o_ptr
)
284 o_ptr
->ident
&= ~(IDENT_CURSED
);
286 /* Mark as uncursed */
287 o_ptr
->pseudo
= INSCRIP_UNCURSED
;
289 /* The object has been "sensed" */
290 o_ptr
->ident
|= (IDENT_SENSE
);
295 * Removes curses from items in inventory.
297 * Note that Items which are "Perma-Cursed" (The One Ring,
298 * The Crown of Morgoth) can NEVER be uncursed.
300 * Note that if "all" is FALSE, then Items which are
301 * "Heavy-Cursed" (Mormegil, Calris, and Weapons of Morgul)
302 * will not be uncursed.
304 static int remove_curse_aux(int all
)
308 /* Attempt to uncurse items being worn */
309 for (i
= INVEN_WIELD
; i
< INVEN_TOTAL
; i
++)
313 object_type
*o_ptr
= &inventory
[i
];
315 /* Skip non-objects */
316 if (!o_ptr
->k_idx
) continue;
318 /* Uncursed already */
319 if (!cursed_p(o_ptr
)) continue;
321 /* Extract the flags */
322 object_flags(o_ptr
, &f1
, &f2
, &f3
);
324 /* Heavily Cursed Items need a special spell */
325 if (!all
&& (f3
& (TR3_HEAVY_CURSE
))) continue;
327 /* Perma-Cursed Items can NEVER be uncursed */
328 if (f3
& (TR3_PERMA_CURSE
)) continue;
330 /* Uncurse the object */
331 uncurse_object(o_ptr
);
333 /* Recalculate the bonuses */
334 p_ptr
->update
|= (PU_BONUS
);
337 p_ptr
->window
|= (PW_EQUIP
);
339 /* Count the uncursings */
343 /* Return "something uncursed" */
351 bool remove_curse(void)
353 return (remove_curse_aux(FALSE
));
359 bool remove_all_curse(void)
361 return (remove_curse_aux(TRUE
));
367 * Restores any drained experience
369 bool restore_level(void)
371 /* Restore experience */
372 if (p_ptr
->exp
< p_ptr
->max_exp
)
375 msg_print("You feel your life energies returning.");
377 /* Restore the experience */
378 p_ptr
->exp
= p_ptr
->max_exp
;
380 /* Check the experience */
393 * Hack -- acquire self knowledge
395 * List various information about the player and/or his current equipment.
396 * See also "identify_fully()".
398 * This tests the flags of the equipment being carried and the innate player
399 * flags, so any changes made in calc_bonuses need to be shadowed here.
401 * Use the "roff()" routines, perhaps. XXX XXX XXX
403 * Use the "show_file()" method, perhaps. XXX XXX XXX
405 * This function cannot display more than 20 lines. XXX XXX XXX
407 void self_knowledge(bool spoil
)
413 u32b f1
= 0L, f2
= 0L, f3
= 0L;
420 /* Get item flags from equipment */
421 for (k
= INVEN_WIELD
; k
< INVEN_TOTAL
; k
++)
423 o_ptr
= &inventory
[k
];
425 /* Skip non-objects */
426 if (!o_ptr
->k_idx
) continue;
428 /* Extract the flags */
430 object_flags(o_ptr
, &t1
, &t2
, &t3
);
432 object_flags_known(o_ptr
, &t1
, &t2
, &t3
);
440 /* And flags from the player */
441 player_flags(&t1
, &t2
, &t3
);
449 if (p_ptr
->timed
[TMD_BLIND
])
451 info
[i
++] = "You cannot see.";
453 if (p_ptr
->timed
[TMD_CONFUSED
])
455 info
[i
++] = "You are confused.";
457 if (p_ptr
->timed
[TMD_AFRAID
])
459 info
[i
++] = "You are terrified.";
461 if (p_ptr
->timed
[TMD_CUT
])
463 info
[i
++] = "You are bleeding.";
465 if (p_ptr
->timed
[TMD_STUN
])
467 info
[i
++] = "You are stunned.";
469 if (p_ptr
->timed
[TMD_POISONED
])
471 info
[i
++] = "You are poisoned.";
473 if (p_ptr
->timed
[TMD_IMAGE
])
475 info
[i
++] = "You are hallucinating.";
478 if (f3
& TR3_AGGRAVATE
)
480 info
[i
++] = "You aggravate monsters.";
482 if (f3
& TR3_TELEPORT
)
484 info
[i
++] = "Your position is very uncertain.";
487 if (p_ptr
->timed
[TMD_BLESSED
])
489 info
[i
++] = "You feel righteous.";
491 if (p_ptr
->timed
[TMD_HERO
])
493 info
[i
++] = "You feel heroic.";
495 if (p_ptr
->timed
[TMD_SHERO
])
497 info
[i
++] = "You are in a battle rage.";
499 if (p_ptr
->timed
[TMD_PROTEVIL
])
501 info
[i
++] = "You are protected from evil.";
503 if (p_ptr
->timed
[TMD_SHIELD
])
505 info
[i
++] = "You are protected by a mystic shield.";
507 if (p_ptr
->timed
[TMD_INVULN
])
509 info
[i
++] = "You are temporarily invulnerable.";
511 if (p_ptr
->confusing
)
513 info
[i
++] = "Your hands are glowing dull red.";
515 if (p_ptr
->searching
)
517 info
[i
++] = "You are looking around very carefully.";
519 if (p_ptr
->new_spells
)
521 info
[i
++] = "You can learn some spells/prayers.";
523 if (p_ptr
->word_recall
)
525 info
[i
++] = "You will soon be recalled.";
527 if (rp_ptr
->infra
|| f1
& TR1_INFRA
)
529 info
[i
++] = "Your eyes are sensitive to infrared light.";
532 if (f3
& TR3_SLOW_DIGEST
)
534 info
[i
++] = "Your appetite is small.";
536 if (f3
& TR3_FEATHER
)
538 info
[i
++] = "You land gently.";
542 info
[i
++] = "You regenerate quickly.";
544 if (f3
& TR3_TELEPATHY
)
546 info
[i
++] = "You have ESP.";
548 if (f3
& TR3_SEE_INVIS
)
550 info
[i
++] = "You can see invisible creatures.";
552 if (f3
& TR3_FREE_ACT
)
554 info
[i
++] = "You have free action.";
556 if (f3
& TR3_HOLD_LIFE
)
558 info
[i
++] = "You have a firm hold on your life force.";
561 if (f2
& TR2_IM_ACID
)
563 info
[i
++] = "You are completely immune to acid.";
565 else if ((f2
& TR2_RES_ACID
) && (p_ptr
->timed
[TMD_OPP_ACID
]))
567 info
[i
++] = "You resist acid exceptionally well.";
569 else if ((f2
& TR2_RES_ACID
) || (p_ptr
->timed
[TMD_OPP_ACID
]))
571 info
[i
++] = "You are resistant to acid.";
574 if (f2
& TR2_IM_ELEC
)
576 info
[i
++] = "You are completely immune to lightning.";
578 else if ((f2
& TR2_RES_ELEC
) && (p_ptr
->timed
[TMD_OPP_ELEC
]))
580 info
[i
++] = "You resist lightning exceptionally well.";
582 else if ((f2
& TR2_RES_ELEC
) || (p_ptr
->timed
[TMD_OPP_ELEC
]))
584 info
[i
++] = "You are resistant to lightning.";
587 if (f2
& TR2_IM_FIRE
)
589 info
[i
++] = "You are completely immune to fire.";
591 else if ((f2
& TR2_RES_FIRE
) && (p_ptr
->timed
[TMD_OPP_FIRE
]))
593 info
[i
++] = "You resist fire exceptionally well.";
595 else if ((f2
& TR2_RES_FIRE
) || (p_ptr
->timed
[TMD_OPP_FIRE
]))
597 info
[i
++] = "You are resistant to fire.";
600 if (f2
& TR2_IM_COLD
)
602 info
[i
++] = "You are completely immune to cold.";
604 else if ((f2
& TR2_RES_COLD
) && (p_ptr
->timed
[TMD_OPP_COLD
]))
606 info
[i
++] = "You resist cold exceptionally well.";
608 else if ((f2
& TR2_RES_COLD
) || (p_ptr
->timed
[TMD_OPP_COLD
]))
610 info
[i
++] = "You are resistant to cold.";
613 if ((f2
& TR2_RES_POIS
) && (p_ptr
->timed
[TMD_OPP_POIS
]))
615 info
[i
++] = "You resist poison exceptionally well.";
617 else if ((f2
& TR2_RES_POIS
) || (p_ptr
->timed
[TMD_OPP_POIS
]))
619 info
[i
++] = "You are resistant to poison.";
622 if (f2
& TR2_RES_FEAR
)
624 info
[i
++] = "You are completely fearless.";
627 if (f2
& TR2_RES_LITE
)
629 info
[i
++] = "You are resistant to bright light.";
631 if (f2
& TR2_RES_DARK
)
633 info
[i
++] = "You are resistant to darkness.";
635 if (f2
& TR2_RES_BLIND
)
637 info
[i
++] = "Your eyes are resistant to blindness.";
639 if (f2
& TR2_RES_CONFU
)
641 info
[i
++] = "You are resistant to confusion.";
643 if (f2
& TR2_RES_SOUND
)
645 info
[i
++] = "You are resistant to sonic attacks.";
647 if (f2
& TR2_RES_SHARD
)
649 info
[i
++] = "You are resistant to blasts of shards.";
651 if (f2
& TR2_RES_NEXUS
)
653 info
[i
++] = "You are resistant to nexus attacks.";
655 if (f2
& TR2_RES_NETHR
)
657 info
[i
++] = "You are resistant to nether forces.";
659 if (f2
& TR2_RES_CHAOS
)
661 info
[i
++] = "You are resistant to chaos.";
663 if (f2
& TR2_RES_DISEN
)
665 info
[i
++] = "You are resistant to disenchantment.";
668 if (f2
& TR2_SUST_STR
)
670 info
[i
++] = "Your strength is sustained.";
672 if (f2
& TR2_SUST_INT
)
674 info
[i
++] = "Your intelligence is sustained.";
676 if (f2
& TR2_SUST_WIS
)
678 info
[i
++] = "Your wisdom is sustained.";
680 if (f2
& TR2_SUST_DEX
)
682 info
[i
++] = "Your dexterity is sustained.";
684 if (f2
& TR2_SUST_CON
)
686 info
[i
++] = "Your constitution is sustained.";
688 if (f2
& TR2_SUST_CHR
)
690 info
[i
++] = "Your charisma is sustained.";
695 info
[i
++] = "Your strength is affected by your equipment.";
699 info
[i
++] = "Your intelligence is affected by your equipment.";
703 info
[i
++] = "Your wisdom is affected by your equipment.";
707 info
[i
++] = "Your dexterity is affected by your equipment.";
711 info
[i
++] = "Your constitution is affected by your equipment.";
715 info
[i
++] = "Your charisma is affected by your equipment.";
718 if (f1
& (TR1_STEALTH
))
720 info
[i
++] = "Your stealth is affected by your equipment.";
722 if (f1
& (TR1_SEARCH
))
724 info
[i
++] = "Your searching ability is affected by your equipment.";
726 if (f1
& (TR1_INFRA
))
728 info
[i
++] = "Your infravision is affected by your equipment.";
730 if (f1
& (TR1_TUNNEL
))
732 info
[i
++] = "Your digging ability is affected by your equipment.";
734 if (f1
& (TR1_SPEED
))
736 info
[i
++] = "Your speed is affected by your equipment.";
738 if (f1
& (TR1_BLOWS
))
740 info
[i
++] = "Your attack speed is affected by your equipment.";
742 if (f1
& (TR1_SHOTS
))
744 info
[i
++] = "Your shooting speed is affected by your equipment.";
746 if (f1
& (TR1_MIGHT
))
748 info
[i
++] = "Your shooting might is affected by your equipment.";
752 /* Get the current weapon */
753 o_ptr
= &inventory
[INVEN_WIELD
];
755 /* Analyze the weapon */
758 /* Special "Attack Bonuses" */
759 if (f1
& (TR1_BRAND_ACID
))
761 info
[i
++] = "Your weapon melts your foes.";
763 if (f1
& (TR1_BRAND_ELEC
))
765 info
[i
++] = "Your weapon shocks your foes.";
767 if (f1
& (TR1_BRAND_FIRE
))
769 info
[i
++] = "Your weapon burns your foes.";
771 if (f1
& (TR1_BRAND_COLD
))
773 info
[i
++] = "Your weapon freezes your foes.";
775 if (f1
& (TR1_BRAND_POIS
))
777 info
[i
++] = "Your weapon poisons your foes.";
780 /* Special "slay" flags */
781 if (f1
& (TR1_SLAY_ANIMAL
))
783 info
[i
++] = "Your weapon strikes at animals with extra force.";
785 if (f1
& (TR1_SLAY_EVIL
))
787 info
[i
++] = "Your weapon strikes at evil with extra force.";
789 if (f1
& (TR1_SLAY_UNDEAD
))
791 info
[i
++] = "Your weapon strikes at undead with holy wrath.";
793 if (f1
& (TR1_SLAY_DEMON
))
795 info
[i
++] = "Your weapon strikes at demons with holy wrath.";
797 if (f1
& (TR1_SLAY_ORC
))
799 info
[i
++] = "Your weapon is especially deadly against orcs.";
801 if (f1
& (TR1_SLAY_TROLL
))
803 info
[i
++] = "Your weapon is especially deadly against trolls.";
805 if (f1
& (TR1_SLAY_GIANT
))
807 info
[i
++] = "Your weapon is especially deadly against giants.";
809 if (f1
& (TR1_SLAY_DRAGON
))
811 info
[i
++] = "Your weapon is especially deadly against dragons.";
814 /* Special "kill" flags */
815 if (f1
& (TR1_KILL_DRAGON
))
817 info
[i
++] = "Your weapon is a great bane of dragons.";
819 if (f1
& (TR1_KILL_DEMON
))
821 info
[i
++] = "Your weapon is a great bane of demons.";
823 if (f1
& (TR1_KILL_UNDEAD
))
825 info
[i
++] = "Your weapon is a great bane of undead.";
829 /* Indicate Blessing */
830 if (f3
& (TR3_BLESSED
))
832 info
[i
++] = "Your weapon has been blessed by the gods.";
836 if (f3
& (TR3_IMPACT
))
838 info
[i
++] = "Your weapon can induce earthquakes.";
847 /* Clear the screen */
850 /* Label the information */
851 prt(" Your Attributes:", 1, 0);
854 for (k
= 2, j
= 0; j
< i
; j
++)
857 prt(info
[j
], k
++, 0);
860 if ((k
== 22) && (j
+1 < i
))
862 prt("-- more --", k
, 0);
865 /* Clear the screen */
868 /* Label the information */
869 prt(" Your Attributes:", 1, 0);
877 prt("[Press any key to continue]", k
, 0);
888 * Set word of recall as appropriate
890 void set_recall(void)
893 if (adult_ironman
&& !p_ptr
->total_winner
)
895 msg_print("Nothing happens.");
899 /* Activate recall */
900 if (!p_ptr
->word_recall
)
902 /* Reset recall depth */
903 if ((p_ptr
->depth
> 0) && (p_ptr
->depth
!= p_ptr
->max_depth
))
906 * ToDo: Add a new player_type field "recall_depth"
907 * ToDo: Poll: Always reset recall depth?
909 if (get_check("Reset recall depth? "))
910 p_ptr
->max_depth
= p_ptr
->depth
;
913 p_ptr
->word_recall
= rand_int(20) + 15;
914 msg_print("The air about you becomes charged...");
917 /* Deactivate recall */
920 p_ptr
->word_recall
= 0;
921 msg_print("A tension leaves the air around you...");
928 * Detect all traps on current panel
930 bool detect_traps(void)
937 /* Scan the current panel */
938 for (y
= Term
->offset_y
; y
< Term
->offset_y
+ SCREEN_HGT
; y
++)
940 for (x
= Term
->offset_x
; x
< Term
->offset_x
+ SCREEN_WID
; x
++)
942 if (!in_bounds_fully(y
, x
)) continue;
944 /* Detect invisible traps */
945 if (cave_feat
[y
][x
] == FEAT_INVIS
)
952 if ((cave_feat
[y
][x
] >= FEAT_TRAP_HEAD
) &&
953 (cave_feat
[y
][x
] <= FEAT_TRAP_TAIL
))
955 /* Hack -- Memorize */
956 cave_info
[y
][x
] |= (CAVE_MARK
);
970 msg_print("You sense the presence of traps!");
980 * Detect all doors on current panel
982 bool detect_doors(void)
990 for (y
= Term
->offset_y
; y
< Term
->offset_y
+ SCREEN_HGT
; y
++)
992 for (x
= Term
->offset_x
; x
< Term
->offset_x
+ SCREEN_WID
; x
++)
994 if (!in_bounds_fully(y
, x
)) continue;
996 /* Detect secret doors */
997 if (cave_feat
[y
][x
] == FEAT_SECRET
)
1000 place_closed_door(y
, x
);
1004 if (((cave_feat
[y
][x
] >= FEAT_DOOR_HEAD
) &&
1005 (cave_feat
[y
][x
] <= FEAT_DOOR_TAIL
)) ||
1006 ((cave_feat
[y
][x
] == FEAT_OPEN
) ||
1007 (cave_feat
[y
][x
] == FEAT_BROKEN
)))
1009 /* Hack -- Memorize */
1010 cave_info
[y
][x
] |= (CAVE_MARK
);
1024 msg_print("You sense the presence of doors!");
1033 * Detect all stairs on current panel
1035 bool detect_stairs(void)
1039 bool detect
= FALSE
;
1042 /* Scan the panel */
1043 for (y
= Term
->offset_y
; y
< Term
->offset_y
+ SCREEN_HGT
; y
++)
1045 for (x
= Term
->offset_x
; x
< Term
->offset_x
+ SCREEN_WID
; x
++)
1047 if (!in_bounds_fully(y
, x
)) continue;
1050 if ((cave_feat
[y
][x
] == FEAT_LESS
) ||
1051 (cave_feat
[y
][x
] == FEAT_MORE
))
1053 /* Hack -- Memorize */
1054 cave_info
[y
][x
] |= (CAVE_MARK
);
1068 msg_print("You sense the presence of stairs!");
1077 * Detect any treasure on the current panel
1079 bool detect_treasure(void)
1083 bool detect
= FALSE
;
1086 /* Scan the current panel */
1087 for (y
= Term
->offset_y
; y
< Term
->offset_y
+ SCREEN_HGT
; y
++)
1089 for (x
= Term
->offset_x
; x
< Term
->offset_x
+ SCREEN_WID
; x
++)
1091 if (!in_bounds_fully(y
, x
)) continue;
1093 /* Notice embedded gold */
1094 if ((cave_feat
[y
][x
] == FEAT_MAGMA_H
) ||
1095 (cave_feat
[y
][x
] == FEAT_QUARTZ_H
))
1097 /* Expose the gold */
1098 cave_feat
[y
][x
] += 0x02;
1101 /* Magma/Quartz + Known Gold */
1102 if ((cave_feat
[y
][x
] == FEAT_MAGMA_K
) ||
1103 (cave_feat
[y
][x
] == FEAT_QUARTZ_K
))
1105 /* Hack -- Memorize */
1106 cave_info
[y
][x
] |= (CAVE_MARK
);
1120 msg_print("You sense the presence of buried treasure!");
1130 * Detect all "gold" objects on the current panel
1132 bool detect_objects_gold(void)
1136 bool detect
= FALSE
;
1140 for (i
= 1; i
< o_max
; i
++)
1142 object_type
*o_ptr
= &o_list
[i
];
1144 /* Skip dead objects */
1145 if (!o_ptr
->k_idx
) continue;
1147 /* Skip held objects */
1148 if (o_ptr
->held_m_idx
) continue;
1154 /* Only detect nearby objects */
1155 if (!panel_contains(y
, x
)) continue;
1157 /* Detect "gold" objects */
1158 if (o_ptr
->tval
== TV_GOLD
)
1160 /* Hack -- memorize it */
1161 o_ptr
->marked
= TRUE
;
1174 msg_print("You sense the presence of treasure!");
1183 * Detect all "normal" objects on the current panel
1185 bool detect_objects_normal(void)
1189 bool detect
= FALSE
;
1193 for (i
= 1; i
< o_max
; i
++)
1195 object_type
*o_ptr
= &o_list
[i
];
1197 /* Skip dead objects */
1198 if (!o_ptr
->k_idx
) continue;
1200 /* Skip held objects */
1201 if (o_ptr
->held_m_idx
) continue;
1207 /* Only detect nearby objects */
1208 if (!panel_contains(y
, x
)) continue;
1210 /* Detect "real" objects */
1211 if (o_ptr
->tval
!= TV_GOLD
)
1213 /* Hack -- memorize it */
1214 o_ptr
->marked
= TRUE
;
1220 if (!squelch_hide_item(o_ptr
))
1228 msg_print("You sense the presence of objects!");
1237 * Detect all "magic" objects on the current panel.
1239 * This will light up all spaces with "magic" items, including artifacts,
1240 * ego-items, potions, scrolls, books, rods, wands, staves, amulets, rings,
1241 * and "enchanted" items of the "good" variety.
1243 * It can probably be argued that this function is now too powerful.
1245 bool detect_objects_magic(void)
1249 bool detect
= FALSE
;
1252 /* Scan all objects */
1253 for (i
= 1; i
< o_max
; i
++)
1255 object_type
*o_ptr
= &o_list
[i
];
1257 /* Skip dead objects */
1258 if (!o_ptr
->k_idx
) continue;
1260 /* Skip held objects */
1261 if (o_ptr
->held_m_idx
) continue;
1267 /* Only detect nearby objects */
1268 if (!panel_contains(y
, x
)) continue;
1270 /* Examine the tval */
1273 /* Artifacts, misc magic items, or enchanted wearables */
1274 if (artifact_p(o_ptr
) || ego_item_p(o_ptr
) ||
1275 (tv
== TV_AMULET
) || (tv
== TV_RING
) ||
1276 (tv
== TV_STAFF
) || (tv
== TV_WAND
) || (tv
== TV_ROD
) ||
1277 (tv
== TV_SCROLL
) || (tv
== TV_POTION
) ||
1278 (tv
== TV_MAGIC_BOOK
) || (tv
== TV_PRAYER_BOOK
) ||
1279 ((o_ptr
->to_a
> 0) || (o_ptr
->to_h
+ o_ptr
->to_d
> 0)))
1281 /* Memorize the item */
1282 o_ptr
->marked
= TRUE
;
1288 if (!squelch_hide_item(o_ptr
))
1296 msg_print("You sense the presence of magic objects!");
1305 * Detect all "normal" monsters on the current panel
1307 bool detect_monsters_normal(void)
1315 for (i
= 1; i
< mon_max
; i
++)
1317 monster_type
*m_ptr
= &mon_list
[i
];
1318 monster_race
*r_ptr
= &r_info
[m_ptr
->r_idx
];
1320 /* Skip dead monsters */
1321 if (!m_ptr
->r_idx
) continue;
1327 /* Only detect nearby monsters */
1328 if (!panel_contains(y
, x
)) continue;
1330 /* Detect all non-invisible monsters */
1331 if (!(r_ptr
->flags2
& (RF2_INVISIBLE
)))
1333 /* Optimize -- Repair flags */
1334 repair_mflag_mark
= repair_mflag_show
= TRUE
;
1336 /* Hack -- Detect the monster */
1337 m_ptr
->mflag
|= (MFLAG_MARK
| MFLAG_SHOW
);
1339 /* Update the monster */
1340 update_mon(i
, FALSE
);
1350 /* Describe result */
1351 msg_print("You sense the presence of monsters!");
1360 * Detect all "invisible" monsters on current panel
1362 bool detect_monsters_invis(void)
1370 for (i
= 1; i
< mon_max
; i
++)
1372 monster_type
*m_ptr
= &mon_list
[i
];
1373 monster_race
*r_ptr
= &r_info
[m_ptr
->r_idx
];
1374 monster_lore
*l_ptr
= &l_list
[m_ptr
->r_idx
];
1376 /* Skip dead monsters */
1377 if (!m_ptr
->r_idx
) continue;
1383 /* Only detect nearby monsters */
1384 if (!panel_contains(y
, x
)) continue;
1386 /* Detect invisible monsters */
1387 if (r_ptr
->flags2
& (RF2_INVISIBLE
))
1389 /* Take note that they are invisible */
1390 l_ptr
->flags2
|= (RF2_INVISIBLE
);
1392 /* Update monster recall window */
1393 if (p_ptr
->monster_race_idx
== m_ptr
->r_idx
)
1396 p_ptr
->window
|= (PW_MONSTER
);
1399 /* Optimize -- Repair flags */
1400 repair_mflag_mark
= repair_mflag_show
= TRUE
;
1402 /* Hack -- Detect the monster */
1403 m_ptr
->mflag
|= (MFLAG_MARK
| MFLAG_SHOW
);
1405 /* Update the monster */
1406 update_mon(i
, FALSE
);
1416 /* Describe result */
1417 msg_print("You sense the presence of invisible creatures!");
1427 * Detect all "evil" monsters on current panel
1429 bool detect_monsters_evil(void)
1437 for (i
= 1; i
< mon_max
; i
++)
1439 monster_type
*m_ptr
= &mon_list
[i
];
1440 monster_race
*r_ptr
= &r_info
[m_ptr
->r_idx
];
1441 monster_lore
*l_ptr
= &l_list
[m_ptr
->r_idx
];
1443 /* Skip dead monsters */
1444 if (!m_ptr
->r_idx
) continue;
1450 /* Only detect nearby monsters */
1451 if (!panel_contains(y
, x
)) continue;
1453 /* Detect evil monsters */
1454 if (r_ptr
->flags3
& (RF3_EVIL
))
1456 /* Take note that they are evil */
1457 l_ptr
->flags3
|= (RF3_EVIL
);
1459 /* Update monster recall window */
1460 if (p_ptr
->monster_race_idx
== m_ptr
->r_idx
)
1463 p_ptr
->window
|= (PW_MONSTER
);
1466 /* Optimize -- Repair flags */
1467 repair_mflag_mark
= repair_mflag_show
= TRUE
;
1469 /* Detect the monster */
1470 m_ptr
->mflag
|= (MFLAG_MARK
| MFLAG_SHOW
);
1472 /* Update the monster */
1473 update_mon(i
, FALSE
);
1483 /* Describe result */
1484 msg_print("You sense the presence of evil creatures!");
1496 bool detect_all(void)
1498 bool detect
= FALSE
;
1500 /* Detect everything */
1501 if (detect_traps()) detect
= TRUE
;
1502 if (detect_doors()) detect
= TRUE
;
1503 if (detect_stairs()) detect
= TRUE
;
1504 if (detect_treasure()) detect
= TRUE
;
1505 if (detect_objects_gold()) detect
= TRUE
;
1506 if (detect_objects_normal()) detect
= TRUE
;
1507 if (detect_monsters_invis()) detect
= TRUE
;
1508 if (detect_monsters_normal()) detect
= TRUE
;
1517 * Create stairs at the player location
1519 void stair_creation(void)
1525 if (!cave_valid_bold(py
, px
))
1527 msg_print("The object resists the spell.");
1532 delete_object(py
, px
);
1534 /* Create a staircase */
1537 cave_set_feat(py
, px
, FEAT_MORE
);
1539 else if (is_quest(p_ptr
->depth
) || (p_ptr
->depth
>= MAX_DEPTH
-1))
1541 cave_set_feat(py
, px
, FEAT_LESS
);
1543 else if (rand_int(100) < 50)
1545 cave_set_feat(py
, px
, FEAT_MORE
);
1549 cave_set_feat(py
, px
, FEAT_LESS
);
1557 * Hook to specify "weapon"
1559 static bool item_tester_hook_weapon(const object_type
*o_ptr
)
1561 switch (o_ptr
->tval
)
1581 * Hook to specify "armour"
1583 static bool item_tester_hook_armour(const object_type
*o_ptr
)
1585 switch (o_ptr
->tval
)
1605 static bool item_tester_unknown(const object_type
*o_ptr
)
1607 if (object_known_p(o_ptr
))
1614 static bool item_tester_unknown_star(const object_type
*o_ptr
)
1616 if (o_ptr
->ident
& IDENT_MENTAL
)
1626 * Revamped! Now takes item pointer, number of times to try enchanting,
1627 * and a flag of what to try enchanting. Artifacts resist enchantment
1628 * some of the time, and successful enchantment to at least +0 might
1629 * break a curse on the item. -CFT
1631 * Note that an item can technically be enchanted all the way to +15 if
1632 * you wait a very, very, long time. Going from +9 to +10 only works
1633 * about 5% of the time, and from +10 to +11 only about 1% of the time.
1635 * Note that this function can now be used on "piles" of items, and
1636 * the larger the pile, the lower the chance of success.
1638 bool enchant(object_type
*o_ptr
, int n
, int eflag
)
1640 int i
, chance
, prob
;
1644 bool a
= artifact_p(o_ptr
);
1648 /* Extract the flags */
1649 object_flags(o_ptr
, &f1
, &f2
, &f3
);
1652 /* Large piles resist enchantment */
1653 prob
= o_ptr
->number
* 100;
1655 /* Missiles are easy to enchant */
1656 if ((o_ptr
->tval
== TV_BOLT
) ||
1657 (o_ptr
->tval
== TV_ARROW
) ||
1658 (o_ptr
->tval
== TV_SHOT
))
1666 /* Hack -- Roll for pile resistance */
1667 if ((prob
> 100) && (rand_int(prob
) >= 100)) continue;
1669 /* Enchant to hit */
1670 if (eflag
& (ENCH_TOHIT
))
1672 if (o_ptr
->to_h
< 0) chance
= 0;
1673 else if (o_ptr
->to_h
> 15) chance
= 1000;
1674 else chance
= enchant_table
[o_ptr
->to_h
];
1676 /* Attempt to enchant */
1677 if ((randint(1000) > chance
) && (!a
|| (rand_int(100) < 50)))
1685 if (cursed_p(o_ptr
) &&
1686 (!(f3
& (TR3_PERMA_CURSE
))) &&
1687 (o_ptr
->to_h
>= 0) && (rand_int(100) < 25))
1689 msg_print("The curse is broken!");
1691 /* Uncurse the object */
1692 uncurse_object(o_ptr
);
1697 /* Enchant to damage */
1698 if (eflag
& (ENCH_TODAM
))
1700 if (o_ptr
->to_d
< 0) chance
= 0;
1701 else if (o_ptr
->to_d
> 15) chance
= 1000;
1702 else chance
= enchant_table
[o_ptr
->to_d
];
1704 /* Attempt to enchant */
1705 if ((randint(1000) > chance
) && (!a
|| (rand_int(100) < 50)))
1713 if (cursed_p(o_ptr
) &&
1714 (!(f3
& (TR3_PERMA_CURSE
))) &&
1715 (o_ptr
->to_d
>= 0) && (rand_int(100) < 25))
1717 msg_print("The curse is broken!");
1719 /* Uncurse the object */
1720 uncurse_object(o_ptr
);
1725 /* Enchant to armor class */
1726 if (eflag
& (ENCH_TOAC
))
1728 if (o_ptr
->to_a
< 0) chance
= 0;
1729 else if (o_ptr
->to_a
> 15) chance
= 1000;
1730 else chance
= enchant_table
[o_ptr
->to_a
];
1732 /* Attempt to enchant */
1733 if ((randint(1000) > chance
) && (!a
|| (rand_int(100) < 50)))
1741 if (cursed_p(o_ptr
) &&
1742 (!(f3
& (TR3_PERMA_CURSE
))) &&
1743 (o_ptr
->to_a
>= 0) && (rand_int(100) < 25))
1745 msg_print("The curse is broken!");
1747 /* Uncurse the object */
1748 uncurse_object(o_ptr
);
1755 if (!res
) return (FALSE
);
1757 /* Recalculate bonuses */
1758 p_ptr
->update
|= (PU_BONUS
);
1760 /* Combine / Reorder the pack (later) */
1761 p_ptr
->notice
|= (PN_COMBINE
| PN_REORDER
);
1764 p_ptr
->window
|= (PW_INVEN
| PW_EQUIP
| PW_PLAYER_0
| PW_PLAYER_1
);
1773 * Enchant an item (in the inventory or on the floor)
1774 * Note that "num_ac" requires armour, else weapon
1775 * Returns TRUE if attempted, FALSE if cancelled
1777 bool enchant_spell(int num_hit
, int num_dam
, int num_ac
)
1789 /* Assume enchant weapon */
1790 item_tester_hook
= item_tester_hook_weapon
;
1792 /* Enchant armor if requested */
1793 if (num_ac
) item_tester_hook
= item_tester_hook_armour
;
1796 q
= "Enchant which item? ";
1797 s
= "You have nothing to enchant.";
1798 if (!get_item(&item
, q
, s
, (USE_EQUIP
| USE_INVEN
| USE_FLOOR
))) return (FALSE
);
1800 /* Get the item (in the pack) */
1803 o_ptr
= &inventory
[item
];
1806 /* Get the item (on the floor) */
1809 o_ptr
= &o_list
[0 - item
];
1814 object_desc(o_name
, sizeof(o_name
), o_ptr
, FALSE
, 0);
1817 msg_format("%s %s glow%s brightly!",
1818 ((item
>= 0) ? "Your" : "The"), o_name
,
1819 ((o_ptr
->number
> 1) ? "" : "s"));
1822 if (enchant(o_ptr
, num_hit
, ENCH_TOHIT
)) okay
= TRUE
;
1823 if (enchant(o_ptr
, num_dam
, ENCH_TODAM
)) okay
= TRUE
;
1824 if (enchant(o_ptr
, num_ac
, ENCH_TOAC
)) okay
= TRUE
;
1830 if (flush_failure
) flush();
1833 msg_print("The enchantment failed.");
1836 /* Something happened */
1842 * Identify an object in the inventory (or on the floor)
1843 * This routine does *not* automatically combine objects.
1844 * Returns TRUE if something was identified, else FALSE.
1846 bool ident_spell(void)
1854 /* Only un-id'ed items */
1855 item_tester_hook
= item_tester_unknown
;
1858 q
= "Identify which item? ";
1859 s
= "You have nothing to identify.";
1860 if (!get_item(&item
, q
, s
, (USE_EQUIP
| USE_INVEN
| USE_FLOOR
))) return (FALSE
);
1862 /* Get the item (in the pack) */
1865 o_ptr
= &inventory
[item
];
1868 /* Get the item (on the floor) */
1871 o_ptr
= &o_list
[0 - item
];
1875 /* Identify the object */
1876 do_ident_item(item
, o_ptr
);
1879 /* Something happened */
1886 * Fully "identify" an object in the inventory
1888 * This routine returns TRUE if an item was identified.
1890 bool identify_fully(void)
1899 /* Only un-*id*'ed items */
1900 item_tester_hook
= item_tester_unknown_star
;
1903 q
= "Identify which item? ";
1904 s
= "You have nothing to identify.";
1905 if (!get_item(&item
, q
, s
, (USE_EQUIP
| USE_INVEN
| USE_FLOOR
))) return (FALSE
);
1907 /* Get the item (in the pack) */
1910 o_ptr
= &inventory
[item
];
1913 /* Get the item (on the floor) */
1916 o_ptr
= &o_list
[0 - item
];
1919 /* Identify the object */
1920 do_ident_item(item
, o_ptr
);
1922 /* Mark the item as fully known */
1923 o_ptr
->ident
|= (IDENT_MENTAL
);
1928 /* Describe it fully */
1929 object_info_screen(o_ptr
);
1940 * Hook for "get_item()". Determine if something is rechargable.
1942 static bool item_tester_hook_recharge(const object_type
*o_ptr
)
1944 /* Recharge staves */
1945 if (o_ptr
->tval
== TV_STAFF
) return (TRUE
);
1947 /* Recharge wands */
1948 if (o_ptr
->tval
== TV_WAND
) return (TRUE
);
1956 * Recharge a wand or staff from the pack or on the floor.
1958 * It is harder to recharge high level, and highly charged wands.
1960 * XXX XXX XXX Beware of "sliding index errors".
1962 * Should probably not "destroy" over-charged items, unless we
1963 * "replace" them by, say, a broken stick or some such. The only
1964 * reason this is okay is because "scrolls of recharging" appear
1965 * BEFORE all staves/wands in the inventory. Note that the
1966 * new "auto_sort_pack" option would correctly handle replacing
1967 * the "broken" wand with any other item (i.e. a broken stick).
1969 bool recharge(int num
)
1971 int i
, t
, item
, lev
;
1978 /* Only accept legal items */
1979 item_tester_hook
= item_tester_hook_recharge
;
1982 q
= "Recharge which item? ";
1983 s
= "You have nothing to recharge.";
1984 if (!get_item(&item
, q
, s
, (USE_INVEN
| USE_FLOOR
))) return (FALSE
);
1986 /* Get the item (in the pack) */
1989 o_ptr
= &inventory
[item
];
1992 /* Get the item (on the floor) */
1995 o_ptr
= &o_list
[0 - item
];
1999 /* Extract the object "level" */
2000 lev
= k_info
[o_ptr
->k_idx
].level
;
2002 /* Recharge power */
2003 i
= (num
+ 100 - lev
- (10 * (o_ptr
->pval
/ o_ptr
->number
))) / 15;
2006 if ((i
<= 1) || (rand_int(i
) == 0))
2008 msg_print("The recharge backfires!");
2009 msg_print("There is a bright flash of light.");
2011 /* Reduce the charges of rods/wands/staves */
2012 reduce_charges(o_ptr
, 1);
2014 /* *Identified* items keep the knowledge about the charges */
2015 if (!(o_ptr
->ident
& IDENT_MENTAL
))
2017 /* We no longer "know" the item */
2018 o_ptr
->ident
&= ~(IDENT_KNOWN
);
2021 /* Reduce and describe inventory */
2024 inven_item_increase(item
, -1);
2025 inven_item_describe(item
);
2026 inven_item_optimize(item
);
2028 /* Reduce and describe floor item */
2031 floor_item_increase(0 - item
, -1);
2032 floor_item_describe(0 - item
);
2033 floor_item_optimize(0 - item
);
2040 /* Extract a "power" */
2041 t
= (num
/ (lev
+ 2)) + 1;
2043 /* Recharge based on the power */
2044 if (t
> 0) o_ptr
->pval
+= 2 + randint(t
);
2046 /* *Identified* items keep the knowledge about the charges */
2047 if (!(o_ptr
->ident
& IDENT_MENTAL
))
2049 /* We no longer "know" the item */
2050 o_ptr
->ident
&= ~(IDENT_KNOWN
);
2053 /* We no longer think the item is empty */
2054 o_ptr
->ident
&= ~(IDENT_EMPTY
);
2057 /* Combine / Reorder the pack (later) */
2058 p_ptr
->notice
|= (PN_COMBINE
| PN_REORDER
);
2061 p_ptr
->window
|= (PW_INVEN
);
2063 /* Something was done */
2075 * Apply a "project()" directly to all viewable monsters
2077 * Note that affected monsters are NOT auto-tracked by this usage.
2079 bool project_los(int typ
, int dam
)
2083 int flg
= PROJECT_JUMP
| PROJECT_KILL
| PROJECT_HIDE
;
2085 bool obvious
= FALSE
;
2088 /* Affect all (nearby) monsters */
2089 for (i
= 1; i
< mon_max
; i
++)
2091 monster_type
*m_ptr
= &mon_list
[i
];
2093 /* Paranoia -- Skip dead monsters */
2094 if (!m_ptr
->r_idx
) continue;
2100 /* Require line of sight */
2101 if (!player_has_los_bold(y
, x
)) continue;
2103 /* Jump directly to the target monster */
2104 if (project(-1, 0, y
, x
, dam
, typ
, flg
)) obvious
= TRUE
;
2115 bool speed_monsters(void)
2117 return (project_los(GF_OLD_SPEED
, p_ptr
->lev
));
2123 bool slow_monsters(void)
2125 return (project_los(GF_OLD_SLOW
, p_ptr
->lev
));
2131 bool sleep_monsters(void)
2133 return (project_los(GF_OLD_SLEEP
, p_ptr
->lev
));
2138 * Banish evil monsters
2140 bool banish_evil(int dist
)
2142 return (project_los(GF_AWAY_EVIL
, dist
));
2149 bool turn_undead(void)
2151 return (project_los(GF_TURN_UNDEAD
, p_ptr
->lev
));
2156 * Dispel undead monsters
2158 bool dispel_undead(int dam
)
2160 return (project_los(GF_DISP_UNDEAD
, dam
));
2164 * Dispel evil monsters
2166 bool dispel_evil(int dam
)
2168 return (project_los(GF_DISP_EVIL
, dam
));
2172 * Dispel all monsters
2174 bool dispel_monsters(int dam
)
2176 return (project_los(GF_DISP_ALL
, dam
));
2184 * Wake up all monsters, and speed up "los" monsters.
2186 void aggravate_monsters(int who
)
2193 /* Aggravate everyone nearby */
2194 for (i
= 1; i
< mon_max
; i
++)
2196 monster_type
*m_ptr
= &mon_list
[i
];
2197 monster_race
*r_ptr
= &r_info
[m_ptr
->r_idx
];
2199 /* Paranoia -- Skip dead monsters */
2200 if (!m_ptr
->r_idx
) continue;
2202 /* Skip aggravating monster (or player) */
2203 if (i
== who
) continue;
2205 /* Wake up nearby sleeping monsters */
2206 if (m_ptr
->cdis
< MAX_SIGHT
* 2)
2217 /* Speed up monsters in line of sight */
2218 if (player_has_los_bold(m_ptr
->fy
, m_ptr
->fx
))
2220 /* Speed up (instantly) to racial base + 10 */
2221 if (m_ptr
->mspeed
< r_ptr
->speed
+ 10)
2224 m_ptr
->mspeed
= r_ptr
->speed
+ 10;
2231 if (speed
) msg_print("You feel a sudden stirring nearby!");
2232 else if (sleep
) msg_print("You hear a sudden stirring in the distance!");
2238 * Delete all non-unique monsters of a given "type" from the level
2240 bool banishment(void)
2248 /* Mega-Hack -- Get a monster symbol */
2249 if (!get_com("Choose a monster race (by symbol) to banish: ", &typ
))
2252 /* Delete the monsters of that "type" */
2253 for (i
= 1; i
< mon_max
; i
++)
2255 monster_type
*m_ptr
= &mon_list
[i
];
2256 monster_race
*r_ptr
= &r_info
[m_ptr
->r_idx
];
2258 /* Paranoia -- Skip dead monsters */
2259 if (!m_ptr
->r_idx
) continue;
2261 /* Hack -- Skip Unique Monsters */
2262 if (r_ptr
->flags1
& (RF1_UNIQUE
)) continue;
2264 /* Skip "wrong" monsters */
2265 if (r_ptr
->d_char
!= typ
) continue;
2267 /* Delete the monster */
2268 delete_monster_idx(i
);
2270 /* Take some damage */
2274 /* Hurt the player */
2275 take_hit(dam
, "the strain of casting Banishment");
2277 /* Update monster list window */
2278 p_ptr
->window
|= PW_MONLIST
;
2286 * Delete all nearby (non-unique) monsters
2288 bool mass_banishment(void)
2293 bool result
= FALSE
;
2296 /* Delete the (nearby) monsters */
2297 for (i
= 1; i
< mon_max
; i
++)
2299 monster_type
*m_ptr
= &mon_list
[i
];
2300 monster_race
*r_ptr
= &r_info
[m_ptr
->r_idx
];
2302 /* Paranoia -- Skip dead monsters */
2303 if (!m_ptr
->r_idx
) continue;
2305 /* Hack -- Skip unique monsters */
2306 if (r_ptr
->flags1
& (RF1_UNIQUE
)) continue;
2308 /* Skip distant monsters */
2309 if (m_ptr
->cdis
> MAX_SIGHT
) continue;
2311 /* Delete the monster */
2312 delete_monster_idx(i
);
2314 /* Take some damage */
2318 /* Hurt the player */
2319 take_hit(dam
, "the strain of casting Mass Banishment");
2321 /* Calculate result */
2322 result
= (dam
> 0) ? TRUE
: FALSE
;
2324 /* Update monster list window */
2325 if (result
) p_ptr
->window
|= PW_MONLIST
;
2333 * Probe nearby monsters
2342 /* Probe all (nearby) monsters */
2343 for (i
= 1; i
< mon_max
; i
++)
2345 monster_type
*m_ptr
= &mon_list
[i
];
2347 /* Paranoia -- Skip dead monsters */
2348 if (!m_ptr
->r_idx
) continue;
2350 /* Require line of sight */
2351 if (!player_has_los_bold(m_ptr
->fy
, m_ptr
->fx
)) continue;
2353 /* Probe visible monsters */
2358 /* Start the message */
2359 if (!probe
) msg_print("Probing...");
2361 /* Get "the monster" or "something" */
2362 monster_desc(m_name
, sizeof(m_name
), m_ptr
, 0x04);
2364 /* Describe the monster */
2365 msg_format("%^s has %d hit points.", m_name
, m_ptr
->hp
);
2367 /* Learn all of the non-spell, non-treasure flags */
2378 msg_print("That's all.");
2388 * The spell of destruction
2390 * This spell "deletes" monsters (instead of "killing" them).
2392 * Later we may use one function for both "destruction" and
2393 * "earthquake" by using the "full" to select "destruction".
2395 void destroy_area(int y1
, int x1
, int r
, bool full
)
2402 /* Unused parameter */
2405 /* No effect in town */
2408 msg_print("The ground shakes for a moment.");
2412 /* Big area of affect */
2413 for (y
= (y1
- r
); y
<= (y1
+ r
); y
++)
2415 for (x
= (x1
- r
); x
<= (x1
+ r
); x
++)
2417 /* Skip illegal grids */
2418 if (!in_bounds_fully(y
, x
)) continue;
2420 /* Extract the distance */
2421 k
= distance(y1
, x1
, y
, x
);
2423 /* Stay in the circle of death */
2424 if (k
> r
) continue;
2426 /* Lose room and vault */
2427 cave_info
[y
][x
] &= ~(CAVE_ROOM
| CAVE_ICKY
);
2429 /* Lose light and knowledge */
2430 cave_info
[y
][x
] &= ~(CAVE_GLOW
| CAVE_MARK
);
2432 /* Hack -- Notice player affect */
2433 if (cave_m_idx
[y
][x
] < 0)
2435 /* Hurt the player later */
2438 /* Do not hurt this grid */
2442 /* Hack -- Skip the epicenter */
2443 if ((y
== y1
) && (x
== x1
)) continue;
2445 /* Delete the monster (if any) */
2446 delete_monster(y
, x
);
2448 /* Destroy "valid" grids */
2449 if (cave_valid_bold(y
, x
))
2451 int feat
= FEAT_FLOOR
;
2453 /* Delete objects */
2454 delete_object(y
, x
);
2456 /* Wall (or floor) type */
2462 /* Create granite wall */
2463 feat
= FEAT_WALL_EXTRA
;
2469 /* Create quartz vein */
2476 /* Create magma vein */
2480 /* Change the feature */
2481 cave_set_feat(y
, x
, feat
);
2487 /* Hack -- Affect player */
2491 msg_print("There is a searing blast of light!");
2493 /* Blind the player */
2494 if (!p_ptr
->resist_blind
&& !p_ptr
->resist_lite
)
2497 (void)inc_timed(TMD_BLIND
, 10 + randint(10));
2502 /* Fully update the visuals */
2503 p_ptr
->update
|= (PU_FORGET_VIEW
| PU_UPDATE_VIEW
| PU_MONSTERS
);
2505 /* Fully update the flow */
2506 p_ptr
->update
|= (PU_FORGET_FLOW
| PU_UPDATE_FLOW
);
2509 p_ptr
->redraw
|= (PR_MAP
);
2512 p_ptr
->window
|= (PW_OVERHEAD
| PW_MAP
| PW_MONLIST
);
2517 * Induce an "earthquake" of the given radius at the given location.
2519 * This will turn some walls into floors and some floors into walls.
2521 * The player will take damage and "jump" into a safe grid if possible,
2522 * otherwise, he will "tunnel" through the rubble instantaneously.
2524 * Monsters will take damage, and "jump" into a safe grid if possible,
2525 * otherwise they will be "buried" in the rubble, disappearing from
2526 * the level in the same way that they do when banished.
2528 * Note that players and monsters (except eaters of walls and passers
2529 * through walls) will never occupy the same grid as a wall (or door).
2531 void earthquake(int cy
, int cx
, int r
)
2536 int i
, t
, y
, x
, yy
, xx
, dy
, dx
;
2540 int sn
= 0, sy
= 0, sx
= 0;
2546 /* No effect in town */
2549 msg_print("The ground shakes for a moment.");
2553 /* Paranoia -- Enforce maximum range */
2556 /* Clear the "maximal blast" area */
2557 for (y
= 0; y
< 32; y
++)
2559 for (x
= 0; x
< 32; x
++)
2565 /* Check around the epicenter */
2566 for (dy
= -r
; dy
<= r
; dy
++)
2568 for (dx
= -r
; dx
<= r
; dx
++)
2570 /* Extract the location */
2574 /* Skip illegal grids */
2575 if (!in_bounds_fully(yy
, xx
)) continue;
2577 /* Skip distant grids */
2578 if (distance(cy
, cx
, yy
, xx
) > r
) continue;
2580 /* Lose room and vault */
2581 cave_info
[yy
][xx
] &= ~(CAVE_ROOM
| CAVE_ICKY
);
2583 /* Lose light and knowledge */
2584 cave_info
[yy
][xx
] &= ~(CAVE_GLOW
| CAVE_MARK
);
2586 /* Skip the epicenter */
2587 if (!dx
&& !dy
) continue;
2589 /* Skip most grids */
2590 if (rand_int(100) < 85) continue;
2592 /* Damage this grid */
2593 map
[16+yy
-cy
][16+xx
-cx
] = TRUE
;
2595 /* Hack -- Take note of player damage */
2596 if ((yy
== py
) && (xx
== px
)) hurt
= TRUE
;
2600 /* First, affect the player (if necessary) */
2603 /* Check around the player */
2604 for (i
= 0; i
< 8; i
++)
2606 /* Get the location */
2607 y
= py
+ ddy_ddd
[i
];
2608 x
= px
+ ddx_ddd
[i
];
2610 /* Skip non-empty grids */
2611 if (!cave_empty_bold(y
, x
)) continue;
2613 /* Important -- Skip "quake" grids */
2614 if (map
[16+y
-cy
][16+x
-cx
]) continue;
2616 /* Count "safe" grids, apply the randomizer */
2617 if ((++sn
> 1) && (rand_int(sn
) != 0)) continue;
2619 /* Save the safe location */
2623 /* Random message */
2628 msg_print("The cave ceiling collapses!");
2633 msg_print("The cave floor twists in an unnatural way!");
2638 msg_print("The cave quakes!");
2639 msg_print("You are pummeled with debris!");
2644 /* Hurt the player a lot */
2647 /* Message and damage */
2648 msg_print("You are severely crushed!");
2652 /* Destroy the grid, and push the player to safety */
2655 /* Calculate results */
2660 msg_print("You nimbly dodge the blast!");
2666 msg_print("You are bashed by rubble!");
2667 damage
= damroll(10, 4);
2668 (void)inc_timed(TMD_STUN
, randint(50));
2673 msg_print("You are crushed between the floor and ceiling!");
2674 damage
= damroll(10, 4);
2675 (void)inc_timed(TMD_STUN
, randint(50));
2681 monster_swap(py
, px
, sy
, sx
);
2684 /* Take some damage */
2685 if (damage
) take_hit(damage
, "an earthquake");
2689 /* Examine the quaked region */
2690 for (dy
= -r
; dy
<= r
; dy
++)
2692 for (dx
= -r
; dx
<= r
; dx
++)
2694 /* Extract the location */
2698 /* Skip unaffected grids */
2699 if (!map
[16+yy
-cy
][16+xx
-cx
]) continue;
2701 /* Process monsters */
2702 if (cave_m_idx
[yy
][xx
] > 0)
2704 monster_type
*m_ptr
= &mon_list
[cave_m_idx
[yy
][xx
]];
2705 monster_race
*r_ptr
= &r_info
[m_ptr
->r_idx
];
2707 /* Most monsters cannot co-exist with rock */
2708 if (!(r_ptr
->flags2
& (RF2_KILL_WALL
)) &&
2709 !(r_ptr
->flags2
& (RF2_PASS_WALL
)))
2713 /* Assume not safe */
2716 /* Monster can move to escape the wall */
2717 if (!(r_ptr
->flags1
& (RF1_NEVER_MOVE
)))
2719 /* Look for safety */
2720 for (i
= 0; i
< 8; i
++)
2723 y
= yy
+ ddy_ddd
[i
];
2724 x
= xx
+ ddx_ddd
[i
];
2726 /* Skip non-empty grids */
2727 if (!cave_empty_bold(y
, x
)) continue;
2729 /* Hack -- no safety on glyph of warding */
2730 if (cave_feat
[y
][x
] == FEAT_GLYPH
) continue;
2732 /* Important -- Skip "quake" grids */
2733 if (map
[16+y
-cy
][16+x
-cx
]) continue;
2735 /* Count "safe" grids, apply the randomizer */
2736 if ((++sn
> 1) && (rand_int(sn
) != 0)) continue;
2738 /* Save the safe grid */
2744 /* Describe the monster */
2745 monster_desc(m_name
, sizeof(m_name
), m_ptr
, 0);
2747 /* Scream in pain */
2748 msg_format("%^s wails out in pain!", m_name
);
2750 /* Take damage from the quake */
2751 damage
= (sn
? damroll(4, 8) : (m_ptr
->hp
+ 1));
2753 /* Monster is certainly awake */
2756 /* Apply damage directly */
2757 m_ptr
->hp
-= damage
;
2759 /* Delete (not kill) "dead" monsters */
2763 msg_format("%^s is embedded in the rock!", m_name
);
2765 /* Delete the monster */
2766 delete_monster(yy
, xx
);
2768 /* No longer safe */
2772 /* Hack -- Escape from the rock */
2775 /* Move the monster */
2776 monster_swap(yy
, xx
, sy
, sx
);
2790 /* Important -- no wall on player */
2791 map
[16+py
-cy
][16+px
-cx
] = FALSE
;
2794 /* Examine the quaked region */
2795 for (dy
= -r
; dy
<= r
; dy
++)
2797 for (dx
= -r
; dx
<= r
; dx
++)
2799 /* Extract the location */
2803 /* Skip unaffected grids */
2804 if (!map
[16+yy
-cy
][16+xx
-cx
]) continue;
2806 /* Paranoia -- never affect player */
2807 if ((yy
== py
) && (xx
== px
)) continue;
2809 /* Destroy location (if valid) */
2810 if (cave_valid_bold(yy
, xx
))
2812 int feat
= FEAT_FLOOR
;
2814 bool floor
= cave_floor_bold(yy
, xx
);
2816 /* Delete objects */
2817 delete_object(yy
, xx
);
2819 /* Wall (or floor) type */
2820 t
= (floor
? rand_int(100) : 200);
2825 /* Create granite wall */
2826 feat
= FEAT_WALL_EXTRA
;
2832 /* Create quartz vein */
2839 /* Create magma vein */
2843 /* Change the feature */
2844 cave_set_feat(yy
, xx
, feat
);
2850 /* Fully update the visuals */
2851 p_ptr
->update
|= (PU_FORGET_VIEW
| PU_UPDATE_VIEW
| PU_MONSTERS
);
2853 /* Fully update the flow */
2854 p_ptr
->update
|= (PU_FORGET_FLOW
| PU_UPDATE_FLOW
);
2857 p_ptr
->redraw
|= (PR_MAP
);
2859 /* Update the health bar */
2860 p_ptr
->redraw
|= (PR_HEALTH
);
2863 p_ptr
->window
|= (PW_OVERHEAD
| PW_MAP
| PW_MONLIST
);
2869 * This routine clears the entire "temp" set.
2871 * This routine will Perma-Lite all "temp" grids.
2873 * This routine is used (only) by "lite_room()"
2875 * Dark grids are illuminated.
2877 * Also, process all affected monsters.
2879 * SMART monsters always wake up when illuminated
2880 * NORMAL monsters wake up 1/4 the time when illuminated
2881 * STUPID monsters wake up 1/10 the time when illuminated
2883 static void cave_temp_room_lite(void)
2887 /* Apply flag changes */
2888 for (i
= 0; i
< temp_n
; i
++)
2893 /* No longer in the array */
2894 cave_info
[y
][x
] &= ~(CAVE_TEMP
);
2897 cave_info
[y
][x
] |= (CAVE_GLOW
);
2900 /* Fully update the visuals */
2901 p_ptr
->update
|= (PU_FORGET_VIEW
| PU_UPDATE_VIEW
| PU_MONSTERS
);
2906 /* Process the grids */
2907 for (i
= 0; i
< temp_n
; i
++)
2912 /* Redraw the grid */
2915 /* Process affected monsters */
2916 if (cave_m_idx
[y
][x
] > 0)
2920 monster_type
*m_ptr
= &mon_list
[cave_m_idx
[y
][x
]];
2921 monster_race
*r_ptr
= &r_info
[m_ptr
->r_idx
];
2923 /* Stupid monsters rarely wake up */
2924 if (r_ptr
->flags2
& (RF2_STUPID
)) chance
= 10;
2926 /* Smart monsters always wake up */
2927 if (r_ptr
->flags2
& (RF2_SMART
)) chance
= 100;
2929 /* Sometimes monsters wake up */
2930 if (m_ptr
->csleep
&& (rand_int(100) < chance
))
2935 /* Notice the "waking up" */
2940 /* Get the monster name */
2941 monster_desc(m_name
, sizeof(m_name
), m_ptr
, 0);
2943 /* Dump a message */
2944 msg_format("%^s wakes up.", m_name
);
2957 * This routine clears the entire "temp" set.
2959 * This routine will "darken" all "temp" grids.
2961 * In addition, some of these grids will be "unmarked".
2963 * This routine is used (only) by "unlite_room()"
2965 static void cave_temp_room_unlite(void)
2969 /* Apply flag changes */
2970 for (i
= 0; i
< temp_n
; i
++)
2975 /* No longer in the array */
2976 cave_info
[y
][x
] &= ~(CAVE_TEMP
);
2978 /* Darken the grid */
2979 cave_info
[y
][x
] &= ~(CAVE_GLOW
);
2981 /* Hack -- Forget "boring" grids */
2982 if (cave_feat
[y
][x
] <= FEAT_INVIS
)
2984 /* Forget the grid */
2985 cave_info
[y
][x
] &= ~(CAVE_MARK
);
2989 /* Fully update the visuals */
2990 p_ptr
->update
|= (PU_FORGET_VIEW
| PU_UPDATE_VIEW
| PU_MONSTERS
);
2995 /* Process the grids */
2996 for (i
= 0; i
< temp_n
; i
++)
3001 /* Redraw the grid */
3013 * Aux function -- see below
3015 static void cave_temp_room_aux(int y
, int x
)
3017 /* Avoid infinite recursion */
3018 if (cave_info
[y
][x
] & (CAVE_TEMP
)) return;
3020 /* Do not "leave" the current room */
3021 if (!(cave_info
[y
][x
] & (CAVE_ROOM
))) return;
3023 /* Paranoia -- verify space */
3024 if (temp_n
== TEMP_MAX
) return;
3026 /* Mark the grid as "seen" */
3027 cave_info
[y
][x
] |= (CAVE_TEMP
);
3029 /* Add it to the "seen" set */
3039 * Illuminate any room containing the given location.
3041 void lite_room(int y1
, int x1
)
3045 /* Add the initial grid */
3046 cave_temp_room_aux(y1
, x1
);
3048 /* While grids are in the queue, add their neighbors */
3049 for (i
= 0; i
< temp_n
; i
++)
3051 x
= temp_x
[i
], y
= temp_y
[i
];
3053 /* Walls get lit, but stop light */
3054 if (!cave_floor_bold(y
, x
)) continue;
3056 /* Spread adjacent */
3057 cave_temp_room_aux(y
+ 1, x
);
3058 cave_temp_room_aux(y
- 1, x
);
3059 cave_temp_room_aux(y
, x
+ 1);
3060 cave_temp_room_aux(y
, x
- 1);
3062 /* Spread diagonal */
3063 cave_temp_room_aux(y
+ 1, x
+ 1);
3064 cave_temp_room_aux(y
- 1, x
- 1);
3065 cave_temp_room_aux(y
- 1, x
+ 1);
3066 cave_temp_room_aux(y
+ 1, x
- 1);
3069 /* Now, lite them all up at once */
3070 cave_temp_room_lite();
3075 * Darken all rooms containing the given location
3077 void unlite_room(int y1
, int x1
)
3081 /* Add the initial grid */
3082 cave_temp_room_aux(y1
, x1
);
3084 /* Spread, breadth first */
3085 for (i
= 0; i
< temp_n
; i
++)
3087 x
= temp_x
[i
], y
= temp_y
[i
];
3089 /* Walls get dark, but stop darkness */
3090 if (!cave_floor_bold(y
, x
)) continue;
3092 /* Spread adjacent */
3093 cave_temp_room_aux(y
+ 1, x
);
3094 cave_temp_room_aux(y
- 1, x
);
3095 cave_temp_room_aux(y
, x
+ 1);
3096 cave_temp_room_aux(y
, x
- 1);
3098 /* Spread diagonal */
3099 cave_temp_room_aux(y
+ 1, x
+ 1);
3100 cave_temp_room_aux(y
- 1, x
- 1);
3101 cave_temp_room_aux(y
- 1, x
+ 1);
3102 cave_temp_room_aux(y
+ 1, x
- 1);
3105 /* Now, darken them all at once */
3106 cave_temp_room_unlite();
3112 * Hack -- call light around the player
3113 * Affect all monsters in the projection radius
3115 bool lite_area(int dam
, int rad
)
3120 int flg
= PROJECT_GRID
| PROJECT_KILL
;
3122 /* Hack -- Message */
3123 if (!p_ptr
->timed
[TMD_BLIND
])
3125 msg_print("You are surrounded by a white light.");
3128 /* Hook into the "project()" function */
3129 (void)project(-1, rad
, py
, px
, dam
, GF_LITE_WEAK
, flg
);
3131 /* Lite up the room */
3140 * Hack -- call darkness around the player
3141 * Affect all monsters in the projection radius
3143 bool unlite_area(int dam
, int rad
)
3148 int flg
= PROJECT_GRID
| PROJECT_KILL
;
3150 /* Hack -- Message */
3151 if (!p_ptr
->timed
[TMD_BLIND
])
3153 msg_print("Darkness surrounds you.");
3156 /* Hook into the "project()" function */
3157 (void)project(-1, rad
, py
, px
, dam
, GF_DARK_WEAK
, flg
);
3159 /* Lite up the room */
3160 unlite_room(py
, px
);
3170 * Stop if we hit a monster, act as a "ball"
3171 * Allow "target" mode to pass over monsters
3172 * Affect grids, objects, and monsters
3174 bool fire_ball(int typ
, int dir
, int dam
, int rad
)
3181 int flg
= PROJECT_STOP
| PROJECT_GRID
| PROJECT_ITEM
| PROJECT_KILL
;
3183 /* Use the given direction */
3184 ty
= py
+ 99 * ddy
[dir
];
3185 tx
= px
+ 99 * ddx
[dir
];
3187 /* Hack -- Use an actual "target" */
3188 if ((dir
== 5) && target_okay())
3190 flg
&= ~(PROJECT_STOP
);
3192 ty
= p_ptr
->target_row
;
3193 tx
= p_ptr
->target_col
;
3196 /* Analyze the "dir" and the "target". Hurt items on floor. */
3197 return (project(-1, rad
, ty
, tx
, dam
, typ
, flg
));
3202 * Cast multiple non-jumping ball spells at the same target.
3204 * Targets absolute coordinates instead of a specific monster, so that
3205 * the death of the monster doesn't change the target's location.
3207 bool fire_swarm(int num
, int typ
, int dir
, int dam
, int rad
)
3209 bool noticed
= FALSE
;
3216 int flg
= PROJECT_STOP
| PROJECT_GRID
| PROJECT_ITEM
| PROJECT_KILL
;
3218 /* Use the given direction */
3219 ty
= py
+ 99 * ddy
[dir
];
3220 tx
= px
+ 99 * ddx
[dir
];
3222 /* Hack -- Use an actual "target" (early detonation) */
3223 if ((dir
== 5) && target_okay())
3225 ty
= p_ptr
->target_row
;
3226 tx
= p_ptr
->target_col
;
3231 /* Analyze the "dir" and the "target". Hurt items on floor. */
3232 if (project(-1, rad
, ty
, tx
, dam
, typ
, flg
)) noticed
= TRUE
;
3240 * Hack -- apply a "projection()" in a direction (or at the target)
3242 static bool project_hook(int typ
, int dir
, int dam
, int flg
)
3249 /* Pass through the target if needed */
3250 flg
|= (PROJECT_THRU
);
3252 /* Use the given direction */
3256 /* Hack -- Use an actual "target" */
3257 if ((dir
== 5) && target_okay())
3259 ty
= p_ptr
->target_row
;
3260 tx
= p_ptr
->target_col
;
3263 /* Analyze the "dir" and the "target", do NOT explode */
3264 return (project(-1, 0, ty
, tx
, dam
, typ
, flg
));
3270 * Stop if we hit a monster, as a "bolt"
3271 * Affect monsters (not grids or objects)
3273 bool fire_bolt(int typ
, int dir
, int dam
)
3275 int flg
= PROJECT_STOP
| PROJECT_KILL
;
3276 return (project_hook(typ
, dir
, dam
, flg
));
3281 * Pass through monsters, as a "beam"
3282 * Affect monsters (not grids or objects)
3284 bool fire_beam(int typ
, int dir
, int dam
)
3286 int flg
= PROJECT_BEAM
| PROJECT_KILL
;
3287 return (project_hook(typ
, dir
, dam
, flg
));
3291 * Cast a bolt spell, or rarely, a beam spell
3293 bool fire_bolt_or_beam(int prob
, int typ
, int dir
, int dam
)
3295 if (rand_int(100) < prob
)
3297 return (fire_beam(typ
, dir
, dam
));
3301 return (fire_bolt(typ
, dir
, dam
));
3307 * Some of the old functions
3310 bool lite_line(int dir
)
3312 int flg
= PROJECT_BEAM
| PROJECT_GRID
| PROJECT_KILL
;
3313 return (project_hook(GF_LITE_WEAK
, dir
, damroll(6, 8), flg
));
3316 bool strong_lite_line(int dir
)
3318 int flg
= PROJECT_BEAM
| PROJECT_GRID
| PROJECT_KILL
;
3319 return (project_hook(GF_LITE
, dir
, damroll(10, 8), flg
));
3322 bool drain_life(int dir
, int dam
)
3324 int flg
= PROJECT_STOP
| PROJECT_KILL
;
3325 return (project_hook(GF_OLD_DRAIN
, dir
, dam
, flg
));
3328 bool wall_to_mud(int dir
)
3330 int flg
= PROJECT_BEAM
| PROJECT_GRID
| PROJECT_ITEM
| PROJECT_KILL
;
3331 return (project_hook(GF_KILL_WALL
, dir
, 20 + randint(30), flg
));
3334 bool destroy_door(int dir
)
3336 int flg
= PROJECT_BEAM
| PROJECT_GRID
| PROJECT_ITEM
;
3337 return (project_hook(GF_KILL_DOOR
, dir
, 0, flg
));
3340 bool disarm_trap(int dir
)
3342 int flg
= PROJECT_BEAM
| PROJECT_GRID
| PROJECT_ITEM
;
3343 return (project_hook(GF_KILL_TRAP
, dir
, 0, flg
));
3346 bool heal_monster(int dir
)
3348 int flg
= PROJECT_STOP
| PROJECT_KILL
;
3349 return (project_hook(GF_OLD_HEAL
, dir
, damroll(4, 6), flg
));
3352 bool speed_monster(int dir
)
3354 int flg
= PROJECT_STOP
| PROJECT_KILL
;
3355 return (project_hook(GF_OLD_SPEED
, dir
, p_ptr
->lev
, flg
));
3358 bool slow_monster(int dir
)
3360 int flg
= PROJECT_STOP
| PROJECT_KILL
;
3361 return (project_hook(GF_OLD_SLOW
, dir
, p_ptr
->lev
, flg
));
3364 bool sleep_monster(int dir
)
3366 int flg
= PROJECT_STOP
| PROJECT_KILL
;
3367 return (project_hook(GF_OLD_SLEEP
, dir
, p_ptr
->lev
, flg
));
3370 bool confuse_monster(int dir
, int plev
)
3372 int flg
= PROJECT_STOP
| PROJECT_KILL
;
3373 return (project_hook(GF_OLD_CONF
, dir
, plev
, flg
));
3376 bool poly_monster(int dir
)
3378 int flg
= PROJECT_STOP
| PROJECT_KILL
;
3379 return (project_hook(GF_OLD_POLY
, dir
, p_ptr
->lev
, flg
));
3382 bool clone_monster(int dir
)
3384 int flg
= PROJECT_STOP
| PROJECT_KILL
;
3385 return (project_hook(GF_OLD_CLONE
, dir
, 0, flg
));
3388 bool fear_monster(int dir
, int plev
)
3390 int flg
= PROJECT_STOP
| PROJECT_KILL
;
3391 return (project_hook(GF_TURN_ALL
, dir
, plev
, flg
));
3394 bool teleport_monster(int dir
)
3396 int flg
= PROJECT_BEAM
| PROJECT_KILL
;
3397 return (project_hook(GF_AWAY_ALL
, dir
, MAX_SIGHT
* 5, flg
));
3403 * Hooks -- affect adjacent grids (radius 1 ball attack)
3406 bool door_creation(void)
3411 int flg
= PROJECT_GRID
| PROJECT_ITEM
| PROJECT_HIDE
;
3412 return (project(-1, 1, py
, px
, 0, GF_MAKE_DOOR
, flg
));
3415 bool trap_creation(void)
3420 int flg
= PROJECT_GRID
| PROJECT_ITEM
| PROJECT_HIDE
;
3421 return (project(-1, 1, py
, px
, 0, GF_MAKE_TRAP
, flg
));
3424 bool destroy_doors_touch(void)
3429 int flg
= PROJECT_GRID
| PROJECT_ITEM
| PROJECT_HIDE
;
3430 return (project(-1, 1, py
, px
, 0, GF_KILL_DOOR
, flg
));
3433 bool sleep_monsters_touch(void)
3438 int flg
= PROJECT_KILL
| PROJECT_HIDE
;
3439 return (project(-1, 1, py
, px
, p_ptr
->lev
, GF_OLD_SLEEP
, flg
));
3444 * Curse the players armor
3446 bool curse_armor(void)
3453 /* Curse the body armor */
3454 o_ptr
= &inventory
[INVEN_BODY
];
3456 /* Nothing to curse */
3457 if (!o_ptr
->k_idx
) return (FALSE
);
3461 object_desc(o_name
, sizeof(o_name
), o_ptr
, FALSE
, 3);
3463 /* Attempt a saving throw for artifacts */
3464 if (artifact_p(o_ptr
) && (rand_int(100) < 50))
3467 msg_format("A %s tries to %s, but your %s resists the effects!",
3468 "terrible black aura", "surround your armor", o_name
);
3471 /* not artifact or failed save... */
3475 msg_format("A terrible black aura blasts your %s!", o_name
);
3477 /* Blast the armor */
3479 o_ptr
->name2
= EGO_BLASTED
;
3480 o_ptr
->to_a
= 0 - randint(5) - randint(5);
3488 o_ptr
->ident
|= (IDENT_CURSED
);
3491 o_ptr
->ident
|= (IDENT_BROKEN
);
3493 /* Recalculate bonuses */
3494 p_ptr
->update
|= (PU_BONUS
);
3496 /* Recalculate mana */
3497 p_ptr
->update
|= (PU_MANA
);
3500 p_ptr
->window
|= (PW_INVEN
| PW_EQUIP
| PW_PLAYER_0
| PW_PLAYER_1
);
3508 * Curse the players weapon
3510 bool curse_weapon(void)
3517 /* Curse the weapon */
3518 o_ptr
= &inventory
[INVEN_WIELD
];
3520 /* Nothing to curse */
3521 if (!o_ptr
->k_idx
) return (FALSE
);
3525 object_desc(o_name
, sizeof(o_name
), o_ptr
, FALSE
, 3);
3527 /* Attempt a saving throw */
3528 if (artifact_p(o_ptr
) && (rand_int(100) < 50))
3531 msg_format("A %s tries to %s, but your %s resists the effects!",
3532 "terrible black aura", "surround your weapon", o_name
);
3535 /* not artifact or failed save... */
3539 msg_format("A terrible black aura blasts your %s!", o_name
);
3541 /* Shatter the weapon */
3543 o_ptr
->name2
= EGO_SHATTERED
;
3544 o_ptr
->to_h
= 0 - randint(5) - randint(5);
3545 o_ptr
->to_d
= 0 - randint(5) - randint(5);
3552 o_ptr
->ident
|= (IDENT_CURSED
);
3555 o_ptr
->ident
|= (IDENT_BROKEN
);
3557 /* Recalculate bonuses */
3558 p_ptr
->update
|= (PU_BONUS
);
3560 /* Recalculate mana */
3561 p_ptr
->update
|= (PU_MANA
);
3564 p_ptr
->window
|= (PW_INVEN
| PW_EQUIP
| PW_PLAYER_0
| PW_PLAYER_1
);
3573 * Brand weapons (or ammo)
3575 * Turns the (non-magical) object into an ego-item of 'brand_type'.
3577 void brand_object(object_type
*o_ptr
, byte brand_type
)
3579 /* you can never modify artifacts / ego-items */
3580 /* you can never modify broken / cursed items */
3581 if ((o_ptr
->k_idx
) &&
3582 (!artifact_p(o_ptr
)) && (!ego_item_p(o_ptr
)) &&
3583 (!broken_p(o_ptr
)) && (!cursed_p(o_ptr
)))
3585 cptr act
= "magical";
3588 object_desc(o_name
, sizeof(o_name
), o_ptr
, FALSE
, 0);
3592 case EGO_BRAND_FIRE
:
3596 case EGO_BRAND_COLD
:
3600 case EGO_BRAND_POIS
:
3601 case EGO_AMMO_VENOM
:
3607 msg_format("A %s aura surrounds the %s.", act
, o_name
);
3609 /* Brand the object */
3610 o_ptr
->name2
= brand_type
;
3612 /* Combine / Reorder the pack (later) */
3613 p_ptr
->notice
|= (PN_COMBINE
| PN_REORDER
);
3616 p_ptr
->window
|= (PW_INVEN
| PW_EQUIP
);
3619 enchant(o_ptr
, rand_int(3) + 4, ENCH_TOHIT
| ENCH_TODAM
);
3623 if (flush_failure
) flush();
3624 msg_print("The Branding failed.");
3630 * Brand the current weapon
3632 void brand_weapon(void)
3637 o_ptr
= &inventory
[INVEN_WIELD
];
3639 /* Select a brand */
3640 if (rand_int(100) < 25)
3641 brand_type
= EGO_BRAND_FIRE
;
3643 brand_type
= EGO_BRAND_COLD
;
3645 /* Brand the weapon */
3646 brand_object(o_ptr
, brand_type
);
3651 * Hook to specify "ammo"
3653 static bool item_tester_hook_ammo(const object_type
*o_ptr
)
3655 switch (o_ptr
->tval
)
3670 * Brand some (non-magical) ammo
3672 bool brand_ammo(void)
3680 /* Only accept ammo */
3681 item_tester_hook
= item_tester_hook_ammo
;
3684 q
= "Brand which kind of ammunition? ";
3685 s
= "You have nothing to brand.";
3686 if (!get_item(&item
, q
, s
, (USE_EQUIP
| USE_INVEN
| USE_FLOOR
))) return (FALSE
);
3688 /* Get the item (in the pack) */
3691 o_ptr
= &inventory
[item
];
3694 /* Get the item (on the floor) */
3697 o_ptr
= &o_list
[0 - item
];
3702 /* Select the brand */
3704 brand_type
= EGO_FLAME
;
3706 brand_type
= EGO_FROST
;
3708 brand_type
= EGO_AMMO_VENOM
;
3710 /* Brand the ammo */
3711 brand_object(o_ptr
, brand_type
);
3719 * Enchant some (non-magical) bolts
3721 bool brand_bolts(void)
3728 /* Restrict choices to bolts */
3729 item_tester_tval
= TV_BOLT
;
3732 q
= "Brand which bolts? ";
3733 s
= "You have no bolts to brand.";
3734 if (!get_item(&item
, q
, s
, (USE_INVEN
| USE_FLOOR
))) return (FALSE
);
3736 /* Get the item (in the pack) */
3739 o_ptr
= &inventory
[item
];
3742 /* Get the item (on the floor) */
3745 o_ptr
= &o_list
[0 - item
];
3748 /* Brand the bolts */
3749 brand_object(o_ptr
, EGO_FLAME
);
3757 * Hack -- activate the ring of power
3759 void ring_of_power(int dir
)
3761 /* Pick a random effect */
3762 switch (randint(10))
3768 msg_print("You are surrounded by a malignant aura.");
3770 /* Decrease all stats (permanently) */
3771 (void)dec_stat(A_STR
, 50, TRUE
);
3772 (void)dec_stat(A_INT
, 50, TRUE
);
3773 (void)dec_stat(A_WIS
, 50, TRUE
);
3774 (void)dec_stat(A_DEX
, 50, TRUE
);
3775 (void)dec_stat(A_CON
, 50, TRUE
);
3776 (void)dec_stat(A_CHR
, 50, TRUE
);
3778 /* Lose some experience (permanently) */
3779 p_ptr
->exp
-= (p_ptr
->exp
/ 4);
3780 p_ptr
->max_exp
-= (p_ptr
->max_exp
/ 4);
3789 msg_print("You are surrounded by a powerful aura.");
3791 /* Dispel monsters */
3792 dispel_monsters(1000);
3802 fire_ball(GF_MANA
, dir
, 300, 3);
3813 fire_bolt(GF_MANA
, dir
, 250);
3824 * `item` is used to print the slot occupied by an object in equip/inven.
3825 * Any negative value assigned to "item" can be used for specifying an object
3828 void do_ident_item(int item
, object_type
*o_ptr
)
3833 object_aware(o_ptr
);
3834 object_known(o_ptr
);
3836 /* Apply an autoinscription, if necessary */
3837 apply_autoinscription(o_ptr
);
3839 /* Set squelch flag */
3840 p_ptr
->notice
|= PN_SQUELCH
;
3842 /* Recalculate bonuses */
3843 p_ptr
->update
|= (PU_BONUS
);
3845 /* Combine / Reorder the pack (later) */
3846 p_ptr
->notice
|= (PN_COMBINE
| PN_REORDER
);
3849 p_ptr
->window
|= (PW_INVEN
| PW_EQUIP
| PW_PLAYER_0
| PW_PLAYER_1
);
3852 object_desc(o_name
, sizeof(o_name
), o_ptr
, TRUE
, 3);
3854 /* Possibly play a sound depending on object quality. */
3855 if (o_ptr
->pval
< 0)
3857 /* This is a bad item. */
3858 sound(MSG_IDENT_BAD
);
3860 else if (o_ptr
->name1
!= 0)
3862 /* We have a good artifact. */
3863 sound(MSG_IDENT_ART
);
3865 else if (o_ptr
->name2
!= 0)
3867 /* We have a good ego item. */
3868 sound(MSG_IDENT_EGO
);
3872 if (item
>= INVEN_WIELD
)
3874 msg_format("%^s: %s (%c).",
3875 describe_use(item
), o_name
, index_to_label(item
));
3879 msg_format("In your pack: %s (%c).",
3880 o_name
, index_to_label(item
));
3884 msg_format("On the ground: %s.", o_name
);