1 /* SCCS Id: @(#)spell.c 3.4 2003/01/17 */
2 /* Copyright (c) M. Stephenson 1988 */
3 /* NetHack may be freely redistributed. See license for details. */
7 static NEARDATA schar delay; /* moves left for this spell */
8 static NEARDATA struct obj *book; /* last/current book being xscribed */
10 /* spellmenu arguments; 0 thru n-1 used as spl_book[] index when swapping */
11 #define SPELLMENU_CAST (-2)
12 #define SPELLMENU_VIEW (-1)
15 #define MAX_SPELL_STUDY 3
16 #define incrnknow(spell) spl_book[spell].sp_know = KEEN
18 #define spellev(spell) spl_book[spell].sp_lev
19 #define spellname(spell) OBJ_NAME(objects[spellid(spell)])
20 #define spellet(spell) \
21 ((char)((spell < 26) ? ('a' + spell) : ('A' + spell - 26)))
23 STATIC_DCL int FDECL(spell_let_to_idx, (CHAR_P));
24 STATIC_DCL boolean FDECL(cursed_book, (struct obj *bp));
25 STATIC_DCL boolean FDECL(confused_book, (struct obj *));
26 STATIC_DCL void FDECL(deadbook, (struct obj *));
27 STATIC_PTR int NDECL(learn);
28 STATIC_DCL boolean FDECL(getspell, (int *));
29 STATIC_DCL boolean FDECL(dospellmenu, (const char *,int,int *));
30 STATIC_DCL int FDECL(percent_success, (int));
31 STATIC_DCL int NDECL(throwspell);
32 STATIC_DCL void NDECL(cast_protection);
33 STATIC_DCL void FDECL(spell_backfire, (int));
34 STATIC_DCL const char *FDECL(spelltypemnemonic, (int));
35 STATIC_DCL int FDECL(isqrt, (int));
37 /* The roles[] table lists the role-specific values for tuning
42 * Arc are aware of magic through historical research
43 * Bar abhor magic (Conan finds it "interferes with his animal instincts")
44 * Cav are ignorant to magic
45 * Hea are very aware of healing magic through medical research
46 * Kni are moderately aware of healing from Paladin training
47 * Mon use magic to attack and defend in lieu of weapons and armor
48 * Pri are very aware of healing magic through theological research
49 * Ran avoid magic, preferring to fight unseen and unheard
50 * Rog are moderately aware of magic through trickery
51 * Sam have limited magical awareness, prefering meditation to conjuring
52 * Tou are aware of magic from all the great films they have seen
53 * Val have limited magical awareness, prefering fighting
54 * Wiz are trained mages
56 * The arms penalty is lessened for trained fighters Bar, Kni, Ran,
58 * the penalty is its metal interference, not encumbrance.
59 * The `spelspec' is a single spell which is fundamentally easier
60 * for that role to cast.
63 * Arc map masters (SPE_MAGIC_MAPPING)
64 * Bar fugue/berserker (SPE_HASTE_SELF)
65 * Cav born to dig (SPE_DIG)
66 * Hea to heal (SPE_CURE_SICKNESS)
67 * Kni to turn back evil (SPE_TURN_UNDEAD)
68 * Mon to preserve their abilities (SPE_RESTORE_ABILITY)
69 * Pri to bless (SPE_REMOVE_CURSE)
70 * Ran to hide (SPE_INVISIBILITY)
71 * Rog to find loot (SPE_DETECT_TREASURE)
72 * Sam to be At One (SPE_CLAIRVOYANCE)
73 * Tou to smile (SPE_CHARM_MONSTER)
74 * Val control the cold (SPE_CONE_OF_COLD)
75 * Wiz all really, but SPE_MAGIC_MISSILE is their party trick
77 * See percent_success() below for more comments.
79 * uarmbon, uarmsbon, uarmhbon, uarmgbon, uarmfbon:
80 * Fighters find body armour & shield a little less limiting.
81 * Headgear, Gauntlets and Footwear are not role-specific (but
82 * still have an effect, except helm of brilliance, which is designed
83 * to permit magic-use).
86 #define uarmhbon 4 /* Metal helmets interfere with the mind */
87 #define uarmgbon 6 /* Casting channels through the hands */
88 #define uarmfbon 2 /* All metal interferes to some degree */
90 /* since the spellbook itself doesn't blow up, don't say just "explodes" */
91 static const char explodes[] = "radiates explosive energy";
93 /* convert a letter into a number in the range 0..51, or -1 if not a letter */
95 spell_let_to_idx(ilet)
101 if (indx >= 0 && indx < 26) return indx;
103 if (indx >= 0 && indx < 26) return indx + 26;
107 /* TRUE: book should be destroyed by caller */
112 int lev = objects[bp->otyp].oc_level;
116 You_feel("a wrenching sensation.");
117 tele(); /* teleport him */
120 You_feel("threatened.");
124 make_blinded(Blinded + rn1(100,250),TRUE);
130 pline("These runes were just too much to comprehend.");
131 make_confused(HConfusion + rn1(7,16),FALSE);
134 pline_The("book was coated with contact poison!");
136 if (uarmg->oerodeproof || !is_corrodeable(uarmg)) {
137 Your("gloves seem unaffected.");
138 } else if (uarmg->oeroded2 < MAX_ERODE) {
139 if (uarmg->greased) {
140 grease_protect(uarmg, "gloves", &youmonst);
142 Your("gloves corrode%s!",
143 uarmg->oeroded2+1 == MAX_ERODE ?
144 " completely" : uarmg->oeroded2 ?
149 Your("gloves %s completely corroded.",
150 Blind ? "feel" : "look");
153 /* temp disable in_use; death should not destroy the book */
155 losestr(Poison_resistance ? rn1(2,1) : rn1(4,3));
156 losehp(rnd(Poison_resistance ? 6 : 10),
157 "contact-poisoned spellbook", KILLED_BY_AN);
162 shieldeff(u.ux, u.uy);
163 pline_The("book %s, but you are unharmed!", explodes);
165 pline("As you read the book, it %s in your %s!",
166 explodes, body_part(FACE));
167 losehp(2*rnd(10)+5, "exploding rune", KILLED_BY_AN);
177 /* study while confused: returns TRUE if the book is destroyed */
179 confused_book(spellbook)
180 struct obj *spellbook;
182 boolean gone = FALSE;
184 if (!rn2(3) && spellbook->otyp != SPE_BOOK_OF_THE_DEAD) {
185 spellbook->in_use = TRUE; /* in case called from learn */
187 "Being confused you have difficulties in controlling your actions.");
188 display_nhwindow(WIN_MESSAGE, FALSE);
189 You("accidentally tear the spellbook to pieces.");
190 if (!objects[spellbook->otyp].oc_name_known &&
191 !objects[spellbook->otyp].oc_uname)
196 You("find yourself reading the %s line over and over again.",
197 spellbook == book ? "next" : "first");
202 /* special effects for The Book of the Dead */
207 struct monst *mtmp, *mtmp2;
210 You("turn the pages of the Book of the Dead...");
211 makeknown(SPE_BOOK_OF_THE_DEAD);
212 /* KMH -- Need ->known to avoid "_a_ Book of the Dead" */
214 if(invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) {
215 register struct obj *otmp;
216 register boolean arti1_primed = FALSE, arti2_primed = FALSE,
220 pline_The("runes appear scrambled. You can't read them!");
224 if(!u.uhave.bell || !u.uhave.menorah) {
225 pline("A chill runs down your %s.", body_part(SPINE));
226 if(!u.uhave.bell) You_hear("a faint chime...");
227 if(!u.uhave.menorah) pline("Vlad's doppelganger is amused.");
231 for(otmp = invent; otmp; otmp = otmp->nobj) {
232 if(otmp->otyp == CANDELABRUM_OF_INVOCATION &&
233 otmp->spe == 7 && otmp->lamplit) {
234 if(!otmp->cursed) arti1_primed = TRUE;
235 else arti_cursed = TRUE;
237 if(otmp->otyp == BELL_OF_OPENING &&
238 (moves - otmp->age) < 5L) { /* you rang it recently */
239 if(!otmp->cursed) arti2_primed = TRUE;
240 else arti_cursed = TRUE;
245 pline_The("invocation fails!");
246 pline("At least one of your artifacts is cursed...");
247 } else if(arti1_primed && arti2_primed) {
248 unsigned soon = (unsigned) d(2,6); /* time til next intervene() */
250 /* successful invocation */
252 u.uevent.invoked = 1;
253 /* in case you haven't killed the Wizard yet, behave as if
255 u.uevent.udemigod = 1; /* wizdead() */
256 if (!u.udg_cnt || u.udg_cnt > soon) u.udg_cnt = soon;
257 } else { /* at least one artifact not prepared properly */
258 You("have a feeling that %s is amiss...", something);
264 /* when not an invocation situation */
268 You("raised the dead!");
269 /* first maybe place a dangerous adversary */
270 if (!rn2(3) && ((mtmp = makemon(&mons[PM_MASTER_LICH],
271 u.ux, u.uy, NO_MINVENT)) != 0 ||
272 (mtmp = makemon(&mons[PM_NALFESHNEE],
273 u.ux, u.uy, NO_MINVENT)) != 0)) {
277 /* next handle the affect on things you're carrying */
278 (void) unturn_dead(&youmonst);
279 /* last place some monsters around you */
282 mkundead(&mm, TRUE, NO_MINVENT);
283 } else if(book2->blessed) {
284 for(mtmp = fmon; mtmp; mtmp = mtmp2) {
285 mtmp2 = mtmp->nmon; /* tamedog() changes chain */
286 if (DEADMONSTER(mtmp)) continue;
288 if (is_undead(mtmp->data) && cansee(mtmp->mx, mtmp->my)) {
289 mtmp->mpeaceful = TRUE;
290 if(sgn(mtmp->data->maligntyp) == sgn(u.ualign.type)
291 && distu(mtmp->mx, mtmp->my) < 4)
293 if (mtmp->mtame < 20)
296 (void) tamedog(mtmp, (struct obj *)0);
297 else monflee(mtmp, 0, FALSE, TRUE);
303 Your("ancestors are annoyed with you!");
306 pline_The("headstones in the cemetery begin to move!");
309 pline("Oh my! Your name appears in the book!");
321 boolean costly = TRUE;
323 /* JDS: lenses give 50% faster reading; 33% smaller read time */
324 if (delay && ublindf && ublindf->otyp == LENSES && rn2(2)) delay++;
325 if (Confusion) { /* became confused while learning */
326 (void) confused_book(book);
327 book = 0; /* no longer studying */
328 nomul(delay); /* remaining delay is uninterrupted */
332 if (delay) { /* not if (delay++), so at end delay == 0 */
334 return(1); /* still busy */
336 exercise(A_WIS, TRUE); /* you're studying. */
337 booktype = book->otyp;
338 if(booktype == SPE_BOOK_OF_THE_DEAD) {
343 Sprintf(splname, objects[booktype].oc_name_known ?
344 "\"%s\"" : "the \"%s\" spell",
345 OBJ_NAME(objects[booktype]));
346 for (i = 0; i < MAXSPELL; i++) {
347 if (spellid(i) == booktype) {
348 if (book->spestudied > MAX_SPELL_STUDY) {
349 pline("This spellbook is too faint to be read any more.");
350 book->otyp = booktype = SPE_BLANK_PAPER;
351 } else if (spellknow(i) <= 1000) {
352 Your("knowledge of %s is keener.", splname);
355 exercise(A_WIS,TRUE); /* extra study */
356 } else { /* 1000 < spellknow(i) <= MAX_SPELL_STUDY */
357 You("know %s quite well already.", splname);
360 /* make book become known even when spell is already
361 known, in case amnesia made you forget the book */
362 makeknown((int)booktype);
364 } else if (spellid(i) == NO_SPELL) {
365 spl_book[i].sp_id = booktype;
366 spl_book[i].sp_lev = objects[booktype].oc_level;
369 You(i > 0 ? "add %s to your repertoire." : "learn %s.",
371 makeknown((int)booktype);
375 if (i == MAXSPELL) impossible("Too many spells memorized!");
377 if (book->cursed) { /* maybe a demon cursed it */
378 if (cursed_book(book)) {
384 if (costly) check_unpaid(book);
390 study_book(spellbook)
391 register struct obj *spellbook;
393 register int booktype = spellbook->otyp;
394 register boolean confused = (Confusion != 0);
395 boolean too_hard = FALSE;
397 if (delay && !confused && spellbook == book &&
398 /* handle the sequence: start reading, get interrupted,
399 have book become erased somehow, resume reading it */
400 booktype != SPE_BLANK_PAPER) {
401 You("continue your efforts to memorize the spell.");
403 /* KMH -- Simplified this code */
404 if (booktype == SPE_BLANK_PAPER) {
405 pline("This spellbook is all blank.");
409 switch (objects[booktype].oc_level) {
412 delay = -objects[booktype].oc_delay;
416 delay = -(objects[booktype].oc_level - 1) *
417 objects[booktype].oc_delay;
421 delay = -objects[booktype].oc_level *
422 objects[booktype].oc_delay;
425 delay = -8 * objects[booktype].oc_delay;
428 impossible("Unknown spellbook level %d, book %d;",
429 objects[booktype].oc_level, booktype);
433 /* Books are often wiser than their readers (Rus.) */
434 spellbook->in_use = TRUE;
435 if (!spellbook->blessed &&
436 spellbook->otyp != SPE_BOOK_OF_THE_DEAD) {
437 if (spellbook->cursed) {
440 /* uncursed - chance to fail */
441 int read_ability = ACURR(A_INT) + 4 + u.ulevel/2
442 - 2*objects[booktype].oc_level
443 + ((ublindf && ublindf->otyp == LENSES) ? 2 : 0);
444 /* only wizards know if a spell is too difficult */
445 if (Role_if(PM_WIZARD) && read_ability < 20 &&
449 "This spellbook is %sdifficult to comprehend. Continue?",
450 (read_ability < 12 ? "very " : ""));
451 if (yn(qbuf) != 'y') {
452 spellbook->in_use = FALSE;
456 /* its up to random luck now */
457 if (rnd(20) > read_ability) {
464 boolean gone = cursed_book(spellbook);
466 nomul(delay); /* study time */
468 if(gone || !rn2(3)) {
469 if (!gone) pline_The("spellbook crumbles to dust!");
470 if (!objects[spellbook->otyp].oc_name_known &&
471 !objects[spellbook->otyp].oc_uname)
475 spellbook->in_use = FALSE;
477 } else if (confused) {
478 if (!confused_book(spellbook)) {
479 spellbook->in_use = FALSE;
485 spellbook->in_use = FALSE;
487 You("begin to %s the runes.",
488 spellbook->otyp == SPE_BOOK_OF_THE_DEAD ? "recite" :
493 set_occupation(learn, "studying", 0);
497 /* a spellbook has been destroyed or the character has changed levels;
498 the stored address for the current book is no longer valid */
503 if (obj == book) book = (struct obj *)0;
506 /* renaming an object usually results in it having a different address;
507 so the sequence start reading, get interrupted, name the book, resume
508 reading would read the "new" book from scratch */
510 book_substitution(old_obj, new_obj)
511 struct obj *old_obj, *new_obj;
513 if (old_obj == book) book = new_obj;
516 /* called from moveloop() */
522 * The time relative to the hero (a pass through move
523 * loop) causes all spell knowledge to be decremented.
524 * The hero's speed, rest status, conscious status etc.
525 * does not alter the loss of memory.
527 for (i = 0; i < MAXSPELL && spellid(i) != NO_SPELL; i++)
534 * Return TRUE if a spell was picked, with the spell index in the return
535 * parameter. Otherwise return FALSE.
542 char ilet, lets[BUFSZ], qbuf[QBUFSZ];
544 if (spellid(0) == NO_SPELL) {
545 You("don't know any spells right now.");
548 if (flags.menu_style == MENU_TRADITIONAL) {
549 /* we know there is at least 1 known spell */
550 for (nspells = 1; nspells < MAXSPELL
551 && spellid(nspells) != NO_SPELL; nspells++)
554 if (nspells == 1) Strcpy(lets, "a");
555 else if (nspells < 27) Sprintf(lets, "a-%c", 'a' + nspells - 1);
556 else if (nspells == 27) Sprintf(lets, "a-zA");
557 else Sprintf(lets, "a-zA-%c", 'A' + nspells - 27);
560 Sprintf(qbuf, "Cast which spell? [%s ?]", lets);
561 if ((ilet = yn_function(qbuf, (char *)0, '\0')) == '?')
564 if (index(quitchars, ilet))
567 idx = spell_let_to_idx(ilet);
568 if (idx >= 0 && idx < nspells) {
572 You("don't know that spell.");
575 return dospellmenu("Choose which spell to cast",
576 SPELLMENU_CAST, spell_no);
579 /* the 'Z' command -- cast a spell */
585 if (getspell(&spell_no))
586 return spelleffects(spell_no, FALSE);
590 STATIC_OVL const char *
591 spelltypemnemonic(skill)
597 case P_HEALING_SPELL:
599 case P_DIVINATION_SPELL:
601 case P_ENCHANTMENT_SPELL:
602 return "enchantment";
610 impossible("Unknown spell skill, %d;", skill);
616 spell_skilltype(booktype)
619 return (objects[booktype].oc_skill);
627 int natac = u.uac - u.uspellprot;
630 /* loglev=log2(u.ulevel)+1 (1..5) */
636 /* The more u.uspellprot you already have, the less you get,
637 * and the better your natural ac, the less you get.
639 * LEVEL AC SPELLPROT from sucessive SPE_PROTECTION casts
643 * 2-3 10 0, 2, 4, 5, 6, 7, 8
644 * 2-3 0 0, 2, 4, 5, 6
646 * 4-7 10 0, 3, 6, 8, 9, 10, 11, 12
647 * 4-7 0 0, 3, 5, 7, 8, 9
649 * 7-15 -10 0, 3, 5, 6
650 * 8-15 10 0, 4, 7, 10, 12, 13, 14, 15, 16
651 * 8-15 0 0, 4, 7, 9, 10, 11, 12
652 * 8-15 -10 0, 4, 6, 7, 8
653 * 16-30 10 0, 5, 9, 12, 14, 16, 17, 18, 19, 20
654 * 16-30 0 0, 5, 9, 11, 13, 14, 15
655 * 16-30 -10 0, 5, 8, 9, 10
657 gain = loglev - (int)u.uspellprot / (4 - min(3,(10 - natac)/10));
661 const char *hgolden = hcolor(NH_GOLDEN);
664 pline_The("%s haze around you becomes more dense.",
667 pline_The("%s around you begins to shimmer with %s haze.",
668 /*[ what about being inside solid rock while polyd? ]*/
669 (Underwater || Is_waterlevel(&u.uz)) ? "water" : "air",
672 u.uspellprot += gain;
674 P_SKILL(spell_skilltype(SPE_PROTECTION)) == P_EXPERT ? 20 : 10;
676 u.usptime = u.uspmtime;
679 Your("skin feels warm for a moment.");
683 /* attempting to cast a forgotten spell will cause disorientation */
685 spell_backfire(spell)
688 long duration = (long)((spellev(spell) + 1) * 3); /* 6..24 */
690 /* prior to 3.4.1, the only effect was confusion; it still predominates */
695 case 3: make_confused(duration, FALSE); /* 40% */
699 case 6: make_confused(2L * duration / 3L, FALSE); /* 30% */
700 make_stunned(duration / 3L, FALSE);
703 case 8: make_stunned(2L * duration / 3L, FALSE); /* 20% */
704 make_confused(duration / 3L, FALSE);
706 case 9: make_stunned(duration, FALSE); /* 10% */
713 spelleffects(spell, atme)
717 int energy, damage, chance, n, intell;
718 int skill, role_skill;
719 boolean confused = (Confusion != 0);
724 * Spell casting no longer affects knowledge of the spell. A
725 * decrement of spell knowledge is done every turn.
727 if (spellknow(spell) <= 0) {
728 Your("knowledge of this spell is twisted.");
729 pline("It invokes nightmarish images in your mind...");
730 spell_backfire(spell);
732 } else if (spellknow(spell) <= 100) {
733 You("strain to recall the spell.");
734 } else if (spellknow(spell) <= 1000) {
735 Your("knowledge of this spell is growing faint.");
737 energy = (spellev(spell) * 5); /* 5 <= energy <= 35 */
739 if (u.uhunger <= 10 && spellid(spell) != SPE_DETECT_FOOD) {
740 You("are too hungry to cast that spell.");
742 } else if (ACURR(A_STR) < 4) {
743 You("lack the strength to cast spells.");
745 } else if(check_capacity(
746 "Your concentration falters while carrying so much stuff.")) {
748 } else if (!freehand()) {
749 Your("arms are not free to cast!");
753 if (u.uhave.amulet) {
754 You_feel("the amulet draining your energy away.");
755 energy += rnd(2*energy);
758 You("don't have enough energy to cast that spell.");
761 if (spellid(spell) != SPE_DETECT_FOOD) {
762 int hungr = energy * 2;
764 /* If hero is a wizard, their current intelligence
765 * (bonuses + temporary + current)
766 * affects hunger reduction in casting a spell.
767 * 1. int = 17-18 no reduction
768 * 2. int = 16 1/4 hungr
769 * 3. int = 15 1/2 hungr
770 * 4. int = 1-14 normal reduction
771 * The reason for this is:
772 * a) Intelligence affects the amount of exertion
774 * b) Wizards have spent their life at magic and
775 * understand quite well how to cast spells.
777 intell = acurr(A_INT);
778 if (!Role_if(PM_WIZARD)) intell = 10;
780 case 25: case 24: case 23: case 22:
781 case 21: case 20: case 19: case 18:
782 case 17: hungr = 0; break;
783 case 16: hungr /= 4; break;
784 case 15: hungr /= 2; break;
786 /* don't put player (quite) into fainting from
787 * casting a spell, particularly since they might
788 * not even be hungry at the beginning; however,
789 * this is low enough that they must eat before
790 * casting anything else except detect food
792 if (hungr > u.uhunger-3)
798 chance = percent_success(spell);
799 if (confused || (rnd(100) > chance)) {
800 You("fail to cast the spell correctly.");
808 exercise(A_WIS, TRUE);
809 /* pseudo is a temporary "false" object containing the spell stats */
810 pseudo = mksobj(spellid(spell), FALSE, FALSE);
811 pseudo->blessed = pseudo->cursed = 0;
812 pseudo->quan = 20L; /* do not let useup get it */
814 * Find the skill the hero has in a spell type category.
815 * See spell_skilltype for categories.
817 skill = spell_skilltype(pseudo->otyp);
818 role_skill = P_SKILL(skill);
820 switch(pseudo->otyp) {
822 * At first spells act as expected. As the hero increases in skill
823 * with the appropriate spell type, some spells increase in their
824 * effects, e.g. more damage, further distance, and so on, without
825 * additional cost to the spellcaster.
827 case SPE_CONE_OF_COLD:
829 if (role_skill >= P_SKILLED) {
834 if(!u.dx && !u.dy && !u.dz) {
835 if ((damage = zapyourself(pseudo, TRUE)) != 0) {
837 Sprintf(buf, "zapped %sself with a spell", uhim());
838 losehp(damage, buf, NO_KILLER_PREFIX);
842 pseudo->otyp - SPE_MAGIC_MISSILE + 10,
843 u.ulevel/2 + 1 + spell_damage_bonus(), 0,
844 (pseudo->otyp == SPE_CONE_OF_COLD) ?
845 EXPL_FROSTY : EXPL_FIERY);
847 u.dx = cc.x+rnd(3)-2; u.dy = cc.y+rnd(3)-2;
848 if (!isok(u.dx,u.dy) || !cansee(u.dx,u.dy) ||
849 IS_STWALL(levl[u.dx][u.dy].typ) || u.uswallow) {
850 /* Spell is reflected back to center */
857 } /* else fall through... */
859 /* these spells are all duplicates of wand effects */
862 case SPE_MAGIC_MISSILE:
864 case SPE_SLOW_MONSTER:
865 case SPE_WIZARD_LOCK:
867 case SPE_TURN_UNDEAD:
869 case SPE_TELEPORT_AWAY:
870 case SPE_CANCELLATION:
871 case SPE_FINGER_OF_DEATH:
873 case SPE_DETECT_UNSEEN:
875 case SPE_EXTRA_HEALING:
877 case SPE_STONE_TO_FLESH:
878 if (!(objects[pseudo->otyp].oc_dir == NODIR)) {
879 if (atme) u.dx = u.dy = u.dz = 0;
880 else if (!getdir((char *)0)) {
881 /* getdir cancelled, re-use previous direction */
882 pline_The("magical energy is released!");
884 if(!u.dx && !u.dy && !u.dz) {
885 if ((damage = zapyourself(pseudo, TRUE)) != 0) {
887 Sprintf(buf, "zapped %sself with a spell", uhim());
888 losehp(damage, buf, NO_KILLER_PREFIX);
890 } else weffects(pseudo);
891 } else weffects(pseudo);
892 update_inventory(); /* spell may modify inventory */
895 /* these are all duplicates of scroll effects */
896 case SPE_REMOVE_CURSE:
897 case SPE_CONFUSE_MONSTER:
898 case SPE_DETECT_FOOD:
900 /* high skill yields effect equivalent to blessed scroll */
901 if (role_skill >= P_SKILLED) pseudo->blessed = 1;
903 case SPE_CHARM_MONSTER:
904 case SPE_MAGIC_MAPPING:
905 case SPE_CREATE_MONSTER:
907 (void) seffects(pseudo);
910 /* these are all duplicates of potion effects */
912 case SPE_DETECT_TREASURE:
913 case SPE_DETECT_MONSTERS:
915 case SPE_RESTORE_ABILITY:
916 /* high skill yields effect equivalent to blessed potion */
917 if (role_skill >= P_SKILLED) pseudo->blessed = 1;
919 case SPE_INVISIBILITY:
920 (void) peffects(pseudo);
923 case SPE_CURE_BLINDNESS:
924 healup(0, 0, FALSE, TRUE);
926 case SPE_CURE_SICKNESS:
927 if (Sick) You("are no longer ill.");
929 pline_The("slime disappears!");
931 /* flags.botl = 1; -- healup() handles this */
933 healup(0, 0, TRUE, FALSE);
935 case SPE_CREATE_FAMILIAR:
936 (void) make_familiar((struct obj *)0, u.ux, u.uy, FALSE);
938 case SPE_CLAIRVOYANCE:
941 /* at present, only one thing blocks clairvoyance */
942 else if (uarmh && uarmh->otyp == CORNUTHAUM)
943 You("sense a pointy hat on top of your %s.",
950 if (!jump(max(role_skill,1)))
951 pline(nothing_happens);
954 impossible("Unknown spell %d attempted.", spell);
955 obfree(pseudo, (struct obj *)0);
959 /* gain skill for successful cast */
960 use_skill(skill, spellev(spell));
962 obfree(pseudo, (struct obj *)0); /* now, get rid of it */
966 /* Choose location where spell takes effect. */
973 pline("You're joking! In this weather?"); return 0;
974 } else if (Is_waterlevel(&u.uz)) {
975 You("had better wait for the sun to come out."); return 0;
978 pline("Where do you want to cast the spell?");
981 if (getpos(&cc, TRUE, "the desired position") < 0)
982 return 0; /* user pressed ESC */
983 /* The number of moves from hero to where the spell drops.*/
984 if (distmin(u.ux, u.uy, cc.x, cc.y) > 10) {
985 pline_The("spell dissipates over the distance!");
987 } else if (u.uswallow) {
988 pline_The("spell is cut short!");
989 exercise(A_WIS, FALSE); /* What were you THINKING! */
993 } else if (!cansee(cc.x, cc.y) || IS_STWALL(levl[cc.x][cc.y].typ)) {
994 Your("mind fails to lock onto that location!");
1006 boolean confused = (Confusion != 0);
1010 for (n = 0; n < MAXSPELL && spellid(n) != NO_SPELL; n++)
1013 nzap = rnd(n) + confused ? 1 : 0;
1014 if (nzap > n) nzap = n;
1015 for (i = n - nzap; i < n; i++) {
1016 spellid(i) = NO_SPELL;
1017 exercise(A_WIS, FALSE); /* ouch! */
1022 /* the '+' command -- view known spells */
1028 struct spell spl_tmp;
1030 if (spellid(0) == NO_SPELL)
1031 You("don't know any spells right now.");
1033 while (dospellmenu("Currently known spells",
1034 SPELLMENU_VIEW, &splnum)) {
1035 Sprintf(qbuf, "Reordering spells; swap '%c' with",
1037 if (!dospellmenu(qbuf, splnum, &othnum)) break;
1039 spl_tmp = spl_book[splnum];
1040 spl_book[splnum] = spl_book[othnum];
1041 spl_book[othnum] = spl_tmp;
1048 dospellmenu(prompt, splaction, spell_no)
1050 int splaction; /* SPELLMENU_CAST, SPELLMENU_VIEW, or spl_book[] index */
1056 menu_item *selected;
1059 tmpwin = create_nhwindow(NHW_MENU);
1061 any.a_void = 0; /* zero out all bits */
1064 * The correct spacing of the columns depends on the
1065 * following that (1) the font is monospaced and (2)
1066 * that selection letters are pre-pended to the given
1067 * string and are of the form "a - ".
1069 * To do it right would require that we implement columns
1070 * in the window-ports (say via a tab character).
1072 if (!iflags.menu_tab_sep)
1073 Sprintf(buf, "%-20s Level %-12s Fail", " Name", "Category");
1075 Sprintf(buf, "Name\tLevel\tCategory\tFail");
1076 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_BOLD, buf, MENU_UNSELECTED);
1077 for (i = 0; i < MAXSPELL && spellid(i) != NO_SPELL; i++) {
1078 Sprintf(buf, iflags.menu_tab_sep ?
1079 "%s\t%-d%s\t%s\t%-d%%" : "%-20s %2d%s %-12s %3d%%",
1080 spellname(i), spellev(i),
1081 spellknow(i) ? " " : "*",
1082 spelltypemnemonic(spell_skilltype(spellid(i))),
1083 100 - percent_success(i));
1085 any.a_int = i+1; /* must be non-zero */
1086 add_menu(tmpwin, NO_GLYPH, &any,
1087 spellet(i), 0, ATR_NONE, buf,
1088 (i == splaction) ? MENU_SELECTED : MENU_UNSELECTED);
1090 end_menu(tmpwin, prompt);
1093 if (splaction == SPELLMENU_VIEW && spellid(1) == NO_SPELL)
1094 how = PICK_NONE; /* only one spell => nothing to swap with */
1095 n = select_menu(tmpwin, how, &selected);
1096 destroy_nhwindow(tmpwin);
1098 *spell_no = selected[0].item.a_int - 1;
1099 /* menu selection for `PICK_ONE' does not
1100 de-select any preselected entry */
1101 if (n > 1 && *spell_no == splaction)
1102 *spell_no = selected[1].item.a_int - 1;
1103 free((genericptr_t)selected);
1104 /* default selection of preselected spell means that
1105 user chose not to swap it with anything */
1106 if (*spell_no == splaction) return FALSE;
1108 } else if (splaction >= 0) {
1109 /* explicit de-selection of preselected spell means that
1110 user is still swapping but not for the current spell */
1111 *spell_no = splaction;
1117 /* Integer square root function without using floating point. */
1133 percent_success(spell)
1136 /* Intrinsic and learned ability are combined to calculate
1137 * the probability of player's success at cast a given spell.
1139 int chance, splcaster, special, statused;
1143 /* Calculate intrinsic ability (splcaster) */
1145 splcaster = urole.spelbase;
1146 special = urole.spelheal;
1147 statused = ACURR(urole.spelstat);
1149 if (uarm && is_metallic(uarm))
1150 splcaster += (uarmc && uarmc->otyp == ROBE) ?
1151 urole.spelarmr/2 : urole.spelarmr;
1152 else if (uarmc && uarmc->otyp == ROBE)
1153 splcaster -= urole.spelarmr;
1154 if (uarms) splcaster += urole.spelshld;
1156 if (uarmh && is_metallic(uarmh) && uarmh->otyp != HELM_OF_BRILLIANCE)
1157 splcaster += uarmhbon;
1158 if (uarmg && is_metallic(uarmg)) splcaster += uarmgbon;
1159 if (uarmf && is_metallic(uarmf)) splcaster += uarmfbon;
1161 if (spellid(spell) == urole.spelspec)
1162 splcaster += urole.spelsbon;
1165 /* `healing spell' bonus */
1166 if (spellid(spell) == SPE_HEALING ||
1167 spellid(spell) == SPE_EXTRA_HEALING ||
1168 spellid(spell) == SPE_CURE_BLINDNESS ||
1169 spellid(spell) == SPE_CURE_SICKNESS ||
1170 spellid(spell) == SPE_RESTORE_ABILITY ||
1171 spellid(spell) == SPE_REMOVE_CURSE) splcaster += special;
1173 if (splcaster > 20) splcaster = 20;
1175 /* Calculate learned ability */
1177 /* Players basic likelihood of being able to cast any spell
1178 * is based of their `magic' statistic. (Int or Wis)
1180 chance = 11 * statused / 2;
1183 * High level spells are harder. Easier for higher level casters.
1184 * The difficulty is based on the hero's level and their skill level
1185 * in that spell type.
1187 skill = P_SKILL(spell_skilltype(spellid(spell)));
1188 skill = max(skill,P_UNSKILLED) - 1; /* unskilled => 0 */
1189 difficulty= (spellev(spell)-1) * 4 - ((skill * 6) + (u.ulevel/3) + 1);
1191 if (difficulty > 0) {
1192 /* Player is too low level or unskilled. */
1193 chance -= isqrt(900 * difficulty + 2000);
1195 /* Player is above level. Learning continues, but the
1196 * law of diminishing returns sets in quickly for
1197 * low-level spells. That is, a player quickly gains
1198 * no advantage for raising level.
1200 int learning = 15 * -difficulty / spellev(spell);
1201 chance += learning > 20 ? 20 : learning;
1204 /* Clamp the chance: >18 stat and advanced learning only help
1205 * to a limit, while chances below "hopeless" only raise the
1206 * specter of overflowing 16-bit ints (and permit wearing a
1207 * shield to raise the chances :-).
1209 if (chance < 0) chance = 0;
1210 if (chance > 120) chance = 120;
1212 /* Wearing anything but a light shield makes it very awkward
1213 * to cast a spell. The penalty is not quite so bad for the
1214 * player's role-specific spell.
1216 if (uarms && weight(uarms) > (int) objects[SMALL_SHIELD].oc_weight) {
1217 if (spellid(spell) == urole.spelspec) {
1224 /* Finally, chance (based on player intell/wisdom and level) is
1225 * combined with ability (based on player intrinsics and
1226 * encumbrances). No matter how intelligent/wise and advanced
1227 * a player is, intrinsics and encumbrance can prevent casting;
1228 * and no matter how able, learning is always required.
1230 chance = chance * (20-splcaster) / 15 - splcaster;
1232 /* Clamp to percentile */
1233 if (chance > 100) chance = 100;
1234 if (chance < 0) chance = 0;
1240 /* Learn a spell during creation of the initial inventory */
1247 for (i = 0; i < MAXSPELL; i++) {
1248 if (spellid(i) == obj->otyp) {
1249 pline("Error: Spell %s already known.",
1250 OBJ_NAME(objects[obj->otyp]));
1253 if (spellid(i) == NO_SPELL) {
1254 spl_book[i].sp_id = obj->otyp;
1255 spl_book[i].sp_lev = objects[obj->otyp].oc_level;
1260 impossible("Too many spells memorized!");