Angband 3.0.9b.
[angband.git] / src / spells2.c
blobb9a550905d5a31c146536ce8f5424dfa8dff3b75
1 /* File: spells2.c */
3 /*
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.
9 */
11 #include "angband.h"
18 * Increase players hit points, notice effects
20 bool hp_player(int num)
22 /* Healing needed */
23 if (p_ptr->chp < p_ptr->mhp)
25 /* Gain hitpoints */
26 p_ptr->chp += num;
28 /* Enforce maximum */
29 if (p_ptr->chp >= p_ptr->mhp)
31 p_ptr->chp = p_ptr->mhp;
32 p_ptr->chp_frac = 0;
35 /* Redraw */
36 p_ptr->redraw |= (PR_HP);
38 /* Window stuff */
39 p_ptr->window |= (PW_PLAYER_0 | PW_PLAYER_1);
41 /* Heal 0-4 */
42 if (num < 5)
44 msg_print("You feel a little better.");
47 /* Heal 5-14 */
48 else if (num < 15)
50 msg_print("You feel better.");
53 /* Heal 15-34 */
54 else if (num < 35)
56 msg_print("You feel much better.");
59 /* Heal 35+ */
60 else
62 msg_print("You feel very good.");
65 /* Notice */
66 return (TRUE);
69 /* Ignore */
70 return (FALSE);
76 * Leave a "glyph of warding" which prevents monster movement
78 void warding_glyph(void)
80 object_type *o_ptr;
81 int py = p_ptr->py;
82 int px = p_ptr->px;
84 if (cave_feat[py][px] != FEAT_FLOOR)
86 msg_print("There is no clear floor on which to cast the spell.");
87 return;
90 /* Create a glyph */
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[] =
111 "strong",
112 "smart",
113 "wise",
114 "dextrous",
115 "healthy",
116 "cute"
121 * Array of stat "descriptions"
123 static cptr desc_stat_neg[] =
125 "weak",
126 "stupid",
127 "naive",
128 "clumsy",
129 "sickly",
130 "ugly"
135 * Lose a "point"
137 bool do_dec_stat(int stat)
139 bool sust = FALSE;
141 /* Get the "sustain" */
142 switch (stat)
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;
152 /* Sustain */
153 if (sust)
155 /* Message */
156 msg_format("You feel very %s for a moment, but the feeling passes.",
157 desc_stat_neg[stat]);
159 /* Notice effect */
160 return (TRUE);
163 /* Attempt to reduce the stat */
164 if (dec_stat(stat, 10, FALSE))
166 /* Message */
167 message_format(MSG_DRAIN_STAT, stat, "You feel very %s.", desc_stat_neg[stat]);
169 /* Notice effect */
170 return (TRUE);
173 /* Nothing obvious */
174 return (FALSE);
179 * Restore lost "points" in a stat
181 bool do_res_stat(int stat)
183 /* Attempt to increase */
184 if (res_stat(stat))
186 /* Message */
187 msg_format("You feel less %s.", desc_stat_neg[stat]);
189 /* Notice */
190 return (TRUE);
193 /* Nothing obvious */
194 return (FALSE);
199 * Gain a "point" in a stat
201 bool do_inc_stat(int stat)
203 bool res;
205 /* Restore strength */
206 res = res_stat(stat);
208 /* Attempt to increase */
209 if (inc_stat(stat))
211 /* Message */
212 msg_format("You feel very %s!", desc_stat_pos[stat]);
214 /* Notice */
215 return (TRUE);
218 /* Restoration worked */
219 if (res)
221 /* Message */
222 msg_format("You feel less %s.", desc_stat_neg[stat]);
224 /* Notice */
225 return (TRUE);
228 /* Nothing obvious */
229 return (FALSE);
235 * Identify everything being carried.
236 * Done by a potion of "self knowledge".
238 void identify_pack(void)
240 int i;
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;
253 /* Identify it */
254 do_ident_item(i, o_ptr);
256 /* repeat with same slot */
257 i--;
267 * Used by the "enchant" function (chance of failure)
269 static const int enchant_table[16] =
271 0, 10, 50, 100, 200,
272 300, 400, 500, 700, 950,
273 990, 992, 995, 997, 999,
274 1000
279 * Hack -- Removes curse from an object.
281 static void uncurse_object(object_type *o_ptr)
283 /* Uncurse it */
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)
306 int i, cnt = 0;
308 /* Attempt to uncurse items being worn */
309 for (i = INVEN_WIELD; i < INVEN_TOTAL; i++)
311 u32b f1, f2, f3;
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);
336 /* Window stuff */
337 p_ptr->window |= (PW_EQUIP);
339 /* Count the uncursings */
340 cnt++;
343 /* Return "something uncursed" */
344 return (cnt);
349 * Remove most curses
351 bool remove_curse(void)
353 return (remove_curse_aux(FALSE));
357 * Remove all curses
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)
374 /* Message */
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 */
381 check_experience();
383 /* Did something */
384 return (TRUE);
387 /* No effect */
388 return (FALSE);
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)
409 int i = 0, j, k;
411 u32b t1, t2, t3;
413 u32b f1 = 0L, f2 = 0L, f3 = 0L;
415 object_type *o_ptr;
417 cptr info[128];
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 */
429 if (spoil)
430 object_flags(o_ptr, &t1, &t2, &t3);
431 else
432 object_flags_known(o_ptr, &t1, &t2, &t3);
434 /* Extract flags */
435 f1 |= t1;
436 f2 |= t2;
437 f3 |= t3;
440 /* And flags from the player */
441 player_flags(&t1, &t2, &t3);
443 /* Extract flags */
444 f1 |= t1;
445 f2 |= t2;
446 f3 |= 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.";
540 if (f3 & TR3_REGEN)
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.";
693 if (f1 & (TR1_STR))
695 info[i++] = "Your strength is affected by your equipment.";
697 if (f1 & (TR1_INT))
699 info[i++] = "Your intelligence is affected by your equipment.";
701 if (f1 & (TR1_WIS))
703 info[i++] = "Your wisdom is affected by your equipment.";
705 if (f1 & (TR1_DEX))
707 info[i++] = "Your dexterity is affected by your equipment.";
709 if (f1 & (TR1_CON))
711 info[i++] = "Your constitution is affected by your equipment.";
713 if (f1 & (TR1_CHR))
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 */
756 if (o_ptr->k_idx)
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.";
835 /* Hack */
836 if (f3 & (TR3_IMPACT))
838 info[i++] = "Your weapon can induce earthquakes.";
843 /* Save screen */
844 screen_save();
847 /* Clear the screen */
848 Term_clear();
850 /* Label the information */
851 prt(" Your Attributes:", 1, 0);
853 /* Dump the info */
854 for (k = 2, j = 0; j < i; j++)
856 /* Show the info */
857 prt(info[j], k++, 0);
859 /* Page wrap */
860 if ((k == 22) && (j+1 < i))
862 prt("-- more --", k, 0);
863 inkey();
865 /* Clear the screen */
866 Term_clear();
868 /* Label the information */
869 prt(" Your Attributes:", 1, 0);
871 /* Reset */
872 k = 2;
876 /* Pause */
877 prt("[Press any key to continue]", k, 0);
878 (void)inkey();
881 /* Load screen */
882 screen_load();
888 * Set word of recall as appropriate
890 void set_recall(void)
892 /* Ironman */
893 if (adult_ironman && !p_ptr->total_winner)
895 msg_print("Nothing happens.");
896 return;
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 */
918 else
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)
932 int y, x;
934 bool detect = FALSE;
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)
947 /* Pick a trap */
948 pick_trap(y, x);
951 /* Detect traps */
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);
958 /* Redraw */
959 lite_spot(y, x);
961 /* Obvious */
962 detect = TRUE;
967 /* Describe */
968 if (detect)
970 msg_print("You sense the presence of traps!");
973 /* Result */
974 return (detect);
980 * Detect all doors on current panel
982 bool detect_doors(void)
984 int y, x;
986 bool detect = FALSE;
989 /* Scan the panel */
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)
999 /* Pick a door */
1000 place_closed_door(y, x);
1003 /* Detect doors */
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);
1012 /* Redraw */
1013 lite_spot(y, x);
1015 /* Obvious */
1016 detect = TRUE;
1021 /* Describe */
1022 if (detect)
1024 msg_print("You sense the presence of doors!");
1027 /* Result */
1028 return (detect);
1033 * Detect all stairs on current panel
1035 bool detect_stairs(void)
1037 int y, x;
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;
1049 /* Detect stairs */
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);
1056 /* Redraw */
1057 lite_spot(y, x);
1059 /* Obvious */
1060 detect = TRUE;
1065 /* Describe */
1066 if (detect)
1068 msg_print("You sense the presence of stairs!");
1071 /* Result */
1072 return (detect);
1077 * Detect any treasure on the current panel
1079 bool detect_treasure(void)
1081 int y, x;
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);
1108 /* Redraw */
1109 lite_spot(y, x);
1111 /* Detect */
1112 detect = TRUE;
1117 /* Describe */
1118 if (detect)
1120 msg_print("You sense the presence of buried treasure!");
1123 /* Result */
1124 return (detect);
1130 * Detect all "gold" objects on the current panel
1132 bool detect_objects_gold(void)
1134 int i, y, x;
1136 bool detect = FALSE;
1139 /* Scan objects */
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;
1150 /* Location */
1151 y = o_ptr->iy;
1152 x = o_ptr->ix;
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;
1163 /* Redraw */
1164 lite_spot(y, x);
1166 /* Detect */
1167 detect = TRUE;
1171 /* Describe */
1172 if (detect)
1174 msg_print("You sense the presence of treasure!");
1177 /* Result */
1178 return (detect);
1183 * Detect all "normal" objects on the current panel
1185 bool detect_objects_normal(void)
1187 int i, y, x;
1189 bool detect = FALSE;
1192 /* Scan objects */
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;
1203 /* Location */
1204 y = o_ptr->iy;
1205 x = o_ptr->ix;
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;
1216 /* Redraw */
1217 lite_spot(y, x);
1219 /* Detect */
1220 if (!squelch_hide_item(o_ptr))
1221 detect = TRUE;
1225 /* Describe */
1226 if (detect)
1228 msg_print("You sense the presence of objects!");
1231 /* Result */
1232 return (detect);
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)
1247 int i, y, x, tv;
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;
1263 /* Location */
1264 y = o_ptr->iy;
1265 x = o_ptr->ix;
1267 /* Only detect nearby objects */
1268 if (!panel_contains(y, x)) continue;
1270 /* Examine the tval */
1271 tv = o_ptr->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;
1284 /* Redraw */
1285 lite_spot(y, x);
1287 /* Detect */
1288 if (!squelch_hide_item(o_ptr))
1289 detect = TRUE;
1293 /* Describe */
1294 if (detect)
1296 msg_print("You sense the presence of magic objects!");
1299 /* Return result */
1300 return (detect);
1305 * Detect all "normal" monsters on the current panel
1307 bool detect_monsters_normal(void)
1309 int i, y, x;
1311 bool flag = FALSE;
1314 /* Scan monsters */
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;
1323 /* Location */
1324 y = m_ptr->fy;
1325 x = m_ptr->fx;
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);
1342 /* Detect */
1343 flag = TRUE;
1347 /* Describe */
1348 if (flag)
1350 /* Describe result */
1351 msg_print("You sense the presence of monsters!");
1354 /* Result */
1355 return (flag);
1360 * Detect all "invisible" monsters on current panel
1362 bool detect_monsters_invis(void)
1364 int i, y, x;
1366 bool flag = FALSE;
1369 /* Scan monsters */
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;
1379 /* Location */
1380 y = m_ptr->fy;
1381 x = m_ptr->fx;
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)
1395 /* Window stuff */
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);
1408 /* Detect */
1409 flag = TRUE;
1413 /* Describe */
1414 if (flag)
1416 /* Describe result */
1417 msg_print("You sense the presence of invisible creatures!");
1420 /* Result */
1421 return (flag);
1427 * Detect all "evil" monsters on current panel
1429 bool detect_monsters_evil(void)
1431 int i, y, x;
1433 bool flag = FALSE;
1436 /* Scan monsters */
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;
1446 /* Location */
1447 y = m_ptr->fy;
1448 x = m_ptr->fx;
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)
1462 /* Window stuff */
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);
1475 /* Detect */
1476 flag = TRUE;
1480 /* Describe */
1481 if (flag)
1483 /* Describe result */
1484 msg_print("You sense the presence of evil creatures!");
1487 /* Result */
1488 return (flag);
1494 * Detect everything
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;
1510 /* Result */
1511 return (detect);
1517 * Create stairs at the player location
1519 void stair_creation(void)
1521 int py = p_ptr->py;
1522 int px = p_ptr->px;
1524 /* XXX XXX XXX */
1525 if (!cave_valid_bold(py, px))
1527 msg_print("The object resists the spell.");
1528 return;
1531 /* XXX XXX XXX */
1532 delete_object(py, px);
1534 /* Create a staircase */
1535 if (!p_ptr->depth)
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);
1547 else
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)
1563 case TV_SWORD:
1564 case TV_HAFTED:
1565 case TV_POLEARM:
1566 case TV_DIGGING:
1567 case TV_BOW:
1568 case TV_BOLT:
1569 case TV_ARROW:
1570 case TV_SHOT:
1572 return (TRUE);
1576 return (FALSE);
1581 * Hook to specify "armour"
1583 static bool item_tester_hook_armour(const object_type *o_ptr)
1585 switch (o_ptr->tval)
1587 case TV_DRAG_ARMOR:
1588 case TV_HARD_ARMOR:
1589 case TV_SOFT_ARMOR:
1590 case TV_SHIELD:
1591 case TV_CLOAK:
1592 case TV_CROWN:
1593 case TV_HELM:
1594 case TV_BOOTS:
1595 case TV_GLOVES:
1597 return (TRUE);
1601 return (FALSE);
1605 static bool item_tester_unknown(const object_type *o_ptr)
1607 if (object_known_p(o_ptr))
1608 return FALSE;
1609 else
1610 return TRUE;
1614 static bool item_tester_unknown_star(const object_type *o_ptr)
1616 if (o_ptr->ident & IDENT_MENTAL)
1617 return FALSE;
1618 else
1619 return TRUE;
1624 * Enchant an item
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;
1642 bool res = FALSE;
1644 bool a = artifact_p(o_ptr);
1646 u32b f1, f2, f3;
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))
1660 prob = prob / 20;
1663 /* Try "n" times */
1664 for (i=0; i<n; i++)
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)))
1679 res = TRUE;
1681 /* Enchant */
1682 o_ptr->to_h++;
1684 /* Break curse */
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)))
1707 res = TRUE;
1709 /* Enchant */
1710 o_ptr->to_d++;
1712 /* Break curse */
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)))
1735 res = TRUE;
1737 /* Enchant */
1738 o_ptr->to_a++;
1740 /* Break curse */
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);
1754 /* Failure */
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);
1763 /* Window stuff */
1764 p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER_0 | PW_PLAYER_1);
1766 /* Success */
1767 return (TRUE);
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)
1779 int item;
1780 bool okay = FALSE;
1782 object_type *o_ptr;
1784 char o_name[80];
1786 cptr q, s;
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;
1795 /* Get an item */
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) */
1801 if (item >= 0)
1803 o_ptr = &inventory[item];
1806 /* Get the item (on the floor) */
1807 else
1809 o_ptr = &o_list[0 - item];
1813 /* Description */
1814 object_desc(o_name, sizeof(o_name), o_ptr, FALSE, 0);
1816 /* Describe */
1817 msg_format("%s %s glow%s brightly!",
1818 ((item >= 0) ? "Your" : "The"), o_name,
1819 ((o_ptr->number > 1) ? "" : "s"));
1821 /* Enchant */
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;
1826 /* Failure */
1827 if (!okay)
1829 /* Flush */
1830 if (flush_failure) flush();
1832 /* Message */
1833 msg_print("The enchantment failed.");
1836 /* Something happened */
1837 return (TRUE);
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)
1848 int item;
1850 object_type *o_ptr;
1852 cptr q, s;
1854 /* Only un-id'ed items */
1855 item_tester_hook = item_tester_unknown;
1857 /* Get an item */
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) */
1863 if (item >= 0)
1865 o_ptr = &inventory[item];
1868 /* Get the item (on the floor) */
1869 else
1871 o_ptr = &o_list[0 - item];
1875 /* Identify the object */
1876 do_ident_item(item, o_ptr);
1879 /* Something happened */
1880 return (TRUE);
1886 * Fully "identify" an object in the inventory
1888 * This routine returns TRUE if an item was identified.
1890 bool identify_fully(void)
1892 int item;
1894 object_type *o_ptr;
1896 cptr q, s;
1899 /* Only un-*id*'ed items */
1900 item_tester_hook = item_tester_unknown_star;
1902 /* Get an item */
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) */
1908 if (item >= 0)
1910 o_ptr = &inventory[item];
1913 /* Get the item (on the floor) */
1914 else
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);
1925 /* Handle stuff */
1926 handle_stuff();
1928 /* Describe it fully */
1929 object_info_screen(o_ptr);
1932 /* Success */
1933 return (TRUE);
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);
1950 /* Nope */
1951 return (FALSE);
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;
1973 object_type *o_ptr;
1975 cptr q, s;
1978 /* Only accept legal items */
1979 item_tester_hook = item_tester_hook_recharge;
1981 /* Get an item */
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) */
1987 if (item >= 0)
1989 o_ptr = &inventory[item];
1992 /* Get the item (on the floor) */
1993 else
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;
2005 /* Back-fire */
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 */
2022 if (item >= 0)
2024 inven_item_increase(item, -1);
2025 inven_item_describe(item);
2026 inven_item_optimize(item);
2028 /* Reduce and describe floor item */
2029 else
2031 floor_item_increase(0 - item, -1);
2032 floor_item_describe(0 - item);
2033 floor_item_optimize(0 - item);
2037 /* Recharge */
2038 else
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);
2060 /* Window stuff */
2061 p_ptr->window |= (PW_INVEN);
2063 /* Something was done */
2064 return (TRUE);
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)
2081 int i, x, y;
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;
2096 /* Location */
2097 y = m_ptr->fy;
2098 x = m_ptr->fx;
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;
2107 /* Result */
2108 return (obvious);
2113 * Speed monsters
2115 bool speed_monsters(void)
2117 return (project_los(GF_OLD_SPEED, p_ptr->lev));
2121 * Slow monsters
2123 bool slow_monsters(void)
2125 return (project_los(GF_OLD_SLOW, p_ptr->lev));
2129 * Sleep monsters
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));
2147 * Turn undead
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)
2188 int i;
2190 bool sleep = FALSE;
2191 bool speed = FALSE;
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)
2208 /* Wake up */
2209 if (m_ptr->csleep)
2211 /* Wake up */
2212 m_ptr->csleep = 0;
2213 sleep = TRUE;
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)
2223 /* Speed up */
2224 m_ptr->mspeed = r_ptr->speed + 10;
2225 speed = TRUE;
2230 /* Messages */
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)
2242 int i;
2243 unsigned dam = 0;
2245 char typ;
2248 /* Mega-Hack -- Get a monster symbol */
2249 if (!get_com("Choose a monster race (by symbol) to banish: ", &typ))
2250 return FALSE;
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 */
2271 dam += randint(4);
2274 /* Hurt the player */
2275 take_hit(dam, "the strain of casting Banishment");
2277 /* Update monster list window */
2278 p_ptr->window |= PW_MONLIST;
2280 /* Success */
2281 return TRUE;
2286 * Delete all nearby (non-unique) monsters
2288 bool mass_banishment(void)
2290 int i;
2291 unsigned dam = 0;
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 */
2315 dam += randint(3);
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;
2327 return (result);
2333 * Probe nearby monsters
2335 bool probing(void)
2337 int i;
2339 bool probe = FALSE;
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 */
2354 if (m_ptr->ml)
2356 char m_name[80];
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 */
2368 lore_do_probe(i);
2370 /* Probe worked */
2371 probe = TRUE;
2375 /* Done */
2376 if (probe)
2378 msg_print("That's all.");
2381 /* Result */
2382 return (probe);
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)
2397 int y, x, k, t;
2399 bool flag = FALSE;
2402 /* Unused parameter */
2403 (void)full;
2405 /* No effect in town */
2406 if (!p_ptr->depth)
2408 msg_print("The ground shakes for a moment.");
2409 return;
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 */
2436 flag = TRUE;
2438 /* Do not hurt this grid */
2439 continue;
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 */
2457 t = rand_int(200);
2459 /* Granite */
2460 if (t < 20)
2462 /* Create granite wall */
2463 feat = FEAT_WALL_EXTRA;
2466 /* Quartz */
2467 else if (t < 70)
2469 /* Create quartz vein */
2470 feat = FEAT_QUARTZ;
2473 /* Magma */
2474 else if (t < 100)
2476 /* Create magma vein */
2477 feat = FEAT_MAGMA;
2480 /* Change the feature */
2481 cave_set_feat(y, x, feat);
2487 /* Hack -- Affect player */
2488 if (flag)
2490 /* Message */
2491 msg_print("There is a searing blast of light!");
2493 /* Blind the player */
2494 if (!p_ptr->resist_blind && !p_ptr->resist_lite)
2496 /* Become blind */
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);
2508 /* Redraw map */
2509 p_ptr->redraw |= (PR_MAP);
2511 /* Window stuff */
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)
2533 int py = p_ptr->py;
2534 int px = p_ptr->px;
2536 int i, t, y, x, yy, xx, dy, dx;
2538 int damage = 0;
2540 int sn = 0, sy = 0, sx = 0;
2542 bool hurt = FALSE;
2544 bool map[32][32];
2546 /* No effect in town */
2547 if (!p_ptr->depth)
2549 msg_print("The ground shakes for a moment.");
2550 return;
2553 /* Paranoia -- Enforce maximum range */
2554 if (r > 12) r = 12;
2556 /* Clear the "maximal blast" area */
2557 for (y = 0; y < 32; y++)
2559 for (x = 0; x < 32; x++)
2561 map[y][x] = FALSE;
2565 /* Check around the epicenter */
2566 for (dy = -r; dy <= r; dy++)
2568 for (dx = -r; dx <= r; dx++)
2570 /* Extract the location */
2571 yy = cy + dy;
2572 xx = cx + dx;
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) */
2601 if (hurt)
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 */
2620 sy = y; sx = x;
2623 /* Random message */
2624 switch (randint(3))
2626 case 1:
2628 msg_print("The cave ceiling collapses!");
2629 break;
2631 case 2:
2633 msg_print("The cave floor twists in an unnatural way!");
2634 break;
2636 default:
2638 msg_print("The cave quakes!");
2639 msg_print("You are pummeled with debris!");
2640 break;
2644 /* Hurt the player a lot */
2645 if (!sn)
2647 /* Message and damage */
2648 msg_print("You are severely crushed!");
2649 damage = 300;
2652 /* Destroy the grid, and push the player to safety */
2653 else
2655 /* Calculate results */
2656 switch (randint(3))
2658 case 1:
2660 msg_print("You nimbly dodge the blast!");
2661 damage = 0;
2662 break;
2664 case 2:
2666 msg_print("You are bashed by rubble!");
2667 damage = damroll(10, 4);
2668 (void)inc_timed(TMD_STUN, randint(50));
2669 break;
2671 case 3:
2673 msg_print("You are crushed between the floor and ceiling!");
2674 damage = damroll(10, 4);
2675 (void)inc_timed(TMD_STUN, randint(50));
2676 break;
2680 /* Move player */
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 */
2695 yy = cy + dy;
2696 xx = cx + dx;
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)))
2711 char m_name[80];
2713 /* Assume not safe */
2714 sn = 0;
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++)
2722 /* Get the grid */
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 */
2739 sy = y;
2740 sx = x;
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 */
2754 m_ptr->csleep = 0;
2756 /* Apply damage directly */
2757 m_ptr->hp -= damage;
2759 /* Delete (not kill) "dead" monsters */
2760 if (m_ptr->hp < 0)
2762 /* Message */
2763 msg_format("%^s is embedded in the rock!", m_name);
2765 /* Delete the monster */
2766 delete_monster(yy, xx);
2768 /* No longer safe */
2769 sn = 0;
2772 /* Hack -- Escape from the rock */
2773 if (sn)
2775 /* Move the monster */
2776 monster_swap(yy, xx, sy, sx);
2784 /* XXX XXX XXX */
2786 /* New location */
2787 py = p_ptr->py;
2788 px = p_ptr->px;
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 */
2800 yy = cy + dy;
2801 xx = cx + dx;
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);
2822 /* Granite */
2823 if (t < 20)
2825 /* Create granite wall */
2826 feat = FEAT_WALL_EXTRA;
2829 /* Quartz */
2830 else if (t < 70)
2832 /* Create quartz vein */
2833 feat = FEAT_QUARTZ;
2836 /* Magma */
2837 else if (t < 100)
2839 /* Create magma vein */
2840 feat = FEAT_MAGMA;
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);
2856 /* Redraw map */
2857 p_ptr->redraw |= (PR_MAP);
2859 /* Update the health bar */
2860 p_ptr->redraw |= (PR_HEALTH);
2862 /* Window stuff */
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)
2885 int i;
2887 /* Apply flag changes */
2888 for (i = 0; i < temp_n; i++)
2890 int y = temp_y[i];
2891 int x = temp_x[i];
2893 /* No longer in the array */
2894 cave_info[y][x] &= ~(CAVE_TEMP);
2896 /* Perma-Lite */
2897 cave_info[y][x] |= (CAVE_GLOW);
2900 /* Fully update the visuals */
2901 p_ptr->update |= (PU_FORGET_VIEW | PU_UPDATE_VIEW | PU_MONSTERS);
2903 /* Update stuff */
2904 update_stuff();
2906 /* Process the grids */
2907 for (i = 0; i < temp_n; i++)
2909 int y = temp_y[i];
2910 int x = temp_x[i];
2912 /* Redraw the grid */
2913 lite_spot(y, x);
2915 /* Process affected monsters */
2916 if (cave_m_idx[y][x] > 0)
2918 int chance = 25;
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))
2932 /* Wake up! */
2933 m_ptr->csleep = 0;
2935 /* Notice the "waking up" */
2936 if (m_ptr->ml)
2938 char m_name[80];
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);
2950 /* None left */
2951 temp_n = 0;
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)
2967 int i;
2969 /* Apply flag changes */
2970 for (i = 0; i < temp_n; i++)
2972 int y = temp_y[i];
2973 int x = temp_x[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);
2992 /* Update stuff */
2993 update_stuff();
2995 /* Process the grids */
2996 for (i = 0; i < temp_n; i++)
2998 int y = temp_y[i];
2999 int x = temp_x[i];
3001 /* Redraw the grid */
3002 lite_spot(y, x);
3005 /* None left */
3006 temp_n = 0;
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 */
3030 temp_y[temp_n] = y;
3031 temp_x[temp_n] = x;
3032 temp_n++;
3039 * Illuminate any room containing the given location.
3041 void lite_room(int y1, int x1)
3043 int i, x, y;
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)
3079 int i, x, y;
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)
3117 int py = p_ptr->py;
3118 int px = p_ptr->px;
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 */
3132 lite_room(py, px);
3134 /* Assume seen */
3135 return (TRUE);
3140 * Hack -- call darkness around the player
3141 * Affect all monsters in the projection radius
3143 bool unlite_area(int dam, int rad)
3145 int py = p_ptr->py;
3146 int px = p_ptr->px;
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);
3162 /* Assume seen */
3163 return (TRUE);
3169 * Cast a ball spell
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)
3176 int py = p_ptr->py;
3177 int px = p_ptr->px;
3179 int ty, tx;
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;
3211 int py = p_ptr->py;
3212 int px = p_ptr->px;
3214 int ty, tx;
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;
3229 while (num--)
3231 /* Analyze the "dir" and the "target". Hurt items on floor. */
3232 if (project(-1, rad, ty, tx, dam, typ, flg)) noticed = TRUE;
3235 return noticed;
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)
3244 int py = p_ptr->py;
3245 int px = p_ptr->px;
3247 int ty, tx;
3249 /* Pass through the target if needed */
3250 flg |= (PROJECT_THRU);
3252 /* Use the given direction */
3253 ty = py + ddy[dir];
3254 tx = px + ddx[dir];
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));
3269 * Cast a bolt spell
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));
3280 * Cast a beam spell
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));
3299 else
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)
3408 int py = p_ptr->py;
3409 int px = p_ptr->px;
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)
3417 int py = p_ptr->py;
3418 int px = p_ptr->px;
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)
3426 int py = p_ptr->py;
3427 int px = p_ptr->px;
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)
3435 int py = p_ptr->py;
3436 int px = p_ptr->px;
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)
3448 object_type *o_ptr;
3450 char o_name[80];
3453 /* Curse the body armor */
3454 o_ptr = &inventory[INVEN_BODY];
3456 /* Nothing to curse */
3457 if (!o_ptr->k_idx) return (FALSE);
3460 /* Describe */
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))
3466 /* Cool */
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... */
3472 else
3474 /* Oops */
3475 msg_format("A terrible black aura blasts your %s!", o_name);
3477 /* Blast the armor */
3478 o_ptr->name1 = 0;
3479 o_ptr->name2 = EGO_BLASTED;
3480 o_ptr->to_a = 0 - randint(5) - randint(5);
3481 o_ptr->to_h = 0;
3482 o_ptr->to_d = 0;
3483 o_ptr->ac = 0;
3484 o_ptr->dd = 0;
3485 o_ptr->ds = 0;
3487 /* Curse it */
3488 o_ptr->ident |= (IDENT_CURSED);
3490 /* Break it */
3491 o_ptr->ident |= (IDENT_BROKEN);
3493 /* Recalculate bonuses */
3494 p_ptr->update |= (PU_BONUS);
3496 /* Recalculate mana */
3497 p_ptr->update |= (PU_MANA);
3499 /* Window stuff */
3500 p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER_0 | PW_PLAYER_1);
3503 return (TRUE);
3508 * Curse the players weapon
3510 bool curse_weapon(void)
3512 object_type *o_ptr;
3514 char o_name[80];
3517 /* Curse the weapon */
3518 o_ptr = &inventory[INVEN_WIELD];
3520 /* Nothing to curse */
3521 if (!o_ptr->k_idx) return (FALSE);
3524 /* Describe */
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))
3530 /* Cool */
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... */
3536 else
3538 /* Oops */
3539 msg_format("A terrible black aura blasts your %s!", o_name);
3541 /* Shatter the weapon */
3542 o_ptr->name1 = 0;
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);
3546 o_ptr->to_a = 0;
3547 o_ptr->ac = 0;
3548 o_ptr->dd = 0;
3549 o_ptr->ds = 0;
3551 /* Curse it */
3552 o_ptr->ident |= (IDENT_CURSED);
3554 /* Break it */
3555 o_ptr->ident |= (IDENT_BROKEN);
3557 /* Recalculate bonuses */
3558 p_ptr->update |= (PU_BONUS);
3560 /* Recalculate mana */
3561 p_ptr->update |= (PU_MANA);
3563 /* Window stuff */
3564 p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER_0 | PW_PLAYER_1);
3567 /* Notice */
3568 return (TRUE);
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";
3586 char o_name[80];
3588 object_desc(o_name, sizeof(o_name), o_ptr, FALSE, 0);
3590 switch (brand_type)
3592 case EGO_BRAND_FIRE:
3593 case EGO_FLAME:
3594 act = "fiery";
3595 break;
3596 case EGO_BRAND_COLD:
3597 case EGO_FROST:
3598 act = "frosty";
3599 break;
3600 case EGO_BRAND_POIS:
3601 case EGO_AMMO_VENOM:
3602 act = "sickly";
3603 break;
3606 /* Describe */
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);
3615 /* Window stuff */
3616 p_ptr->window |= (PW_INVEN | PW_EQUIP);
3618 /* Enchant */
3619 enchant(o_ptr, rand_int(3) + 4, ENCH_TOHIT | ENCH_TODAM);
3621 else
3623 if (flush_failure) flush();
3624 msg_print("The Branding failed.");
3630 * Brand the current weapon
3632 void brand_weapon(void)
3634 object_type *o_ptr;
3635 byte brand_type;
3637 o_ptr = &inventory[INVEN_WIELD];
3639 /* Select a brand */
3640 if (rand_int(100) < 25)
3641 brand_type = EGO_BRAND_FIRE;
3642 else
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)
3657 case TV_BOLT:
3658 case TV_ARROW:
3659 case TV_SHOT:
3661 return (TRUE);
3665 return (FALSE);
3670 * Brand some (non-magical) ammo
3672 bool brand_ammo(void)
3674 int item;
3675 object_type *o_ptr;
3676 cptr q, s;
3677 int r;
3678 byte brand_type;
3680 /* Only accept ammo */
3681 item_tester_hook = item_tester_hook_ammo;
3683 /* Get an item */
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) */
3689 if (item >= 0)
3691 o_ptr = &inventory[item];
3694 /* Get the item (on the floor) */
3695 else
3697 o_ptr = &o_list[0 - item];
3700 r = rand_int(100);
3702 /* Select the brand */
3703 if (r < 33)
3704 brand_type = EGO_FLAME;
3705 else if (r < 67)
3706 brand_type = EGO_FROST;
3707 else
3708 brand_type = EGO_AMMO_VENOM;
3710 /* Brand the ammo */
3711 brand_object(o_ptr, brand_type);
3713 /* Done */
3714 return (TRUE);
3719 * Enchant some (non-magical) bolts
3721 bool brand_bolts(void)
3723 int item;
3724 object_type *o_ptr;
3725 cptr q, s;
3728 /* Restrict choices to bolts */
3729 item_tester_tval = TV_BOLT;
3731 /* Get an item */
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) */
3737 if (item >= 0)
3739 o_ptr = &inventory[item];
3742 /* Get the item (on the floor) */
3743 else
3745 o_ptr = &o_list[0 - item];
3748 /* Brand the bolts */
3749 brand_object(o_ptr, EGO_FLAME);
3751 /* Done */
3752 return (TRUE);
3757 * Hack -- activate the ring of power
3759 void ring_of_power(int dir)
3761 /* Pick a random effect */
3762 switch (randint(10))
3764 case 1:
3765 case 2:
3767 /* Message */
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);
3781 check_experience();
3783 break;
3786 case 3:
3788 /* Message */
3789 msg_print("You are surrounded by a powerful aura.");
3791 /* Dispel monsters */
3792 dispel_monsters(1000);
3794 break;
3797 case 4:
3798 case 5:
3799 case 6:
3801 /* Mana Ball */
3802 fire_ball(GF_MANA, dir, 300, 3);
3804 break;
3807 case 7:
3808 case 8:
3809 case 9:
3810 case 10:
3812 /* Mana Bolt */
3813 fire_bolt(GF_MANA, dir, 250);
3815 break;
3822 * Identify an item.
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
3826 * on the floor.
3828 void do_ident_item(int item, object_type *o_ptr)
3830 char o_name[80];
3832 /* Identify it */
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);
3848 /* Window stuff */
3849 p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER_0 | PW_PLAYER_1);
3851 /* Description */
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);
3871 /* Describe */
3872 if (item >= INVEN_WIELD)
3874 msg_format("%^s: %s (%c).",
3875 describe_use(item), o_name, index_to_label(item));
3877 else if (item >= 0)
3879 msg_format("In your pack: %s (%c).",
3880 o_name, index_to_label(item));
3882 else
3884 msg_format("On the ground: %s.", o_name);