Source:NetHack 3.3.0/spell.c
Jump to navigation
Jump to search
Below is the full text to spell.c from the source code of NetHack 3.3.0. To link to a particular line, write [[NetHack 3.3.0/spell.c#line123]], for example.
Warning! This is the source code from an old release. For the latest release, see Source code
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
1. /* SCCS Id: @(#)spell.c 3.3 1999/11/01 */ 2. /* Copyright (c) M. Stephenson 1988 */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. #include "hack.h" 6. 7. static NEARDATA schar delay; /* moves left for this spell */ 8. static NEARDATA struct obj *book; /* last/current book being xscribed */ 9. 10. /* spellmenu arguments; 0 thru n-1 used as spl_book[] index when swapping */ 11. #define SPELLMENU_CAST (-2) 12. #define SPELLMENU_VIEW (-1) 13. 14. #define KEEN 20000 15. #define MAX_SPELL_STUDY 3 16. #define incrnknow(spell) spl_book[spell].sp_know = KEEN 17. 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))) 22. 23. static int FDECL(spell_let_to_idx, (CHAR_P)); 24. static void FDECL(cursed_book, (int)); 25. static void FDECL(deadbook, (struct obj *)); 26. STATIC_PTR int NDECL(learn); 27. static boolean FDECL(getspell, (int *)); 28. static boolean FDECL(dospellmenu, (const char *,int,int *)); 29. static int FDECL(percent_success, (int)); 30. static int NDECL(throwspell); 31. static void NDECL(cast_protection); 32. static const char *FDECL(spelltypemnemonic, (int)); 33. static int FDECL(isqrt, (int)); 34. 35. /* The roles[] table lists the role-specific values for tuning 36. * percent_success(). 37. * 38. * Reasoning: 39. * spelbase, spelheal: 40. * Arc are aware of magic through historical research 41. * Bar abhor magic (Conan finds it "interferes with his animal instincts") 42. * Cav are ignorant to magic 43. * Hea are very aware of healing magic through medical research 44. * Kni are moderately aware of healing from Paladin training 45. * Mon use magic to attack and defend in lieu of weapons and armor 46. * Pri are very aware of healing magic through theological research 47. * Ran avoid magic, preferring to fight unseen and unheard 48. * Rog are moderately aware of magic through trickery 49. * Sam have limited magical awareness, prefering meditation to conjuring 50. * Tou are aware of magic from all the great films they have seen 51. * Val have limited magical awareness, prefering fighting 52. * Wiz are trained mages 53. * 54. * The arms penalty is lessened for trained fighters Bar, Kni, Ran, 55. * Sam, Val - 56. * the penalty is its metal interference, not encumberance. 57. * The `spelspec' is a single spell which is fundamentally easier 58. * for that role to cast. 59. * 60. * spelspec, spelsbon: 61. * Arc map masters (SPE_MAGIC_MAPPING) 62. * Bar fugue/berserker (SPE_HASTE_SELF) 63. * Cav born to dig (SPE_DIG) 64. * Hea to heal (SPE_CURE_SICKNESS) 65. * Kni to turn back evil (SPE_TURN_UNDEAD) 66. * Mon to preserve their abilities (SPE_RESTORE_ABILITY) 67. * Pri to bless (SPE_REMOVE_CURSE) 68. * Ran to hide (SPE_INVISIBILITY) 69. * Rog to find loot (SPE_DETECT_TREASURE) 70. * Sam to be At One (SPE_CLAIRVOYANCE) 71. * Tou to smile (SPE_CHARM_MONSTER) 72. * Val control the cold (SPE_CONE_OF_COLD) 73. * Wiz all really, but SPE_MAGIC_MISSILE is their party trick 74. * 75. * See percent_success() below for more comments. 76. * 77. * uarmbon, uarmsbon, uarmhbon, uarmgbon, uarmfbon: 78. * Fighters find body armour & shield a little less limiting. 79. * Headgear, Gauntlets and Footwear are not role-specific (but 80. * still have an effect, except helm of brilliance, which is designed 81. * to permit magic-use). 82. */ 83. 84. #define uarmhbon 4 /* Metal helmets interfere with the mind */ 85. #define uarmgbon 6 /* Casting channels through the hands */ 86. #define uarmfbon 2 /* All metal interferes to some degree */ 87. 88. /* since the spellbook itself doesn't blow up, don't say just "explodes" */ 89. static const char explodes[] = "radiates explosive energy"; 90. 91. /* convert a letter into a number in the range 0..51, or -1 if not a letter */ 92. static int 93. spell_let_to_idx(ilet) 94. char ilet; 95. { 96. int indx; 97. 98. indx = ilet - 'a'; 99. if (indx >= 0 && indx < 26) return indx; 100. indx = ilet - 'A'; 101. if (indx >= 0 && indx < 26) return indx + 26; 102. return -1; 103. } 104. 105. static void 106. cursed_book(lev) 107. register int lev; 108. { 109. switch(rn2(lev)) { 110. case 0: 111. You_feel("a wrenching sensation."); 112. tele(); /* teleport him */ 113. break; 114. case 1: 115. You_feel("threatened."); 116. aggravate(); 117. break; 118. case 2: 119. make_blinded(Blinded + rn1(100,250),TRUE); 120. break; 121. case 3: 122. take_gold(); 123. break; 124. case 4: 125. pline("These runes were just too much to comprehend."); 126. make_confused(HConfusion + rn1(7,16),FALSE); 127. break; 128. case 5: 129. pline_The("book was coated with contact poison!"); 130. if (uarmg) { 131. if (uarmg->oerodeproof || !is_corrodeable(uarmg)) { 132. Your("gloves seem unaffected."); 133. } else if (uarmg->oeroded2 < MAX_ERODE) { 134. Your("gloves corrode%s!", 135. uarmg->oeroded2+1 == MAX_ERODE ? " completely" : 136. uarmg->oeroded2 ? " further" : ""); 137. uarmg->oeroded2++; 138. } else 139. Your("gloves %s completely corroded.", 140. Blind ? "feel" : "look"); 141. break; 142. } 143. losestr(Poison_resistance ? rn1(2,1) : rn1(4,3)); 144. losehp(rnd(Poison_resistance ? 6 : 10), 145. "contact-poisoned spellbook", KILLED_BY_AN); 146. break; 147. case 6: 148. if(Antimagic) { 149. shieldeff(u.ux, u.uy); 150. pline_The("book %s, but you are unharmed!", explodes); 151. } else { 152. pline("As you read the book, it %s in your %s!", 153. explodes, body_part(FACE)); 154. losehp (2*rnd(10)+5, "exploding rune", KILLED_BY_AN); 155. } 156. break; 157. default: 158. rndcurse(); 159. break; 160. } 161. return; 162. } 163. 164. /* special effects for The Book of the Dead */ 165. static void 166. deadbook(book2) 167. struct obj *book2; 168. { 169. struct monst *mtmp, *mtmp2; 170. coord mm; 171. 172. You("turn the pages of the Book of the Dead..."); 173. makeknown(SPE_BOOK_OF_THE_DEAD); 174. /* KMH -- Need ->known to avoid "_a_ Book of the Dead" */ 175. book2->known = 1; 176. if(invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) { 177. register struct obj *otmp; 178. register boolean arti1_primed = FALSE, arti2_primed = FALSE, 179. arti_cursed = FALSE; 180. 181. if(book2->cursed) { 182. pline_The("runes appear scrambled. You can't read them!"); 183. return; 184. } 185. 186. if(!u.uhave.bell || !u.uhave.menorah) { 187. pline("A chill runs down your %s.", body_part(SPINE)); 188. if(!u.uhave.bell) You_hear("a faint chime..."); 189. if(!u.uhave.menorah) pline("Vlad's doppelganger is amused."); 190. return; 191. } 192. 193. for(otmp = invent; otmp; otmp = otmp->nobj) { 194. if(otmp->otyp == CANDELABRUM_OF_INVOCATION && 195. otmp->spe == 7 && otmp->lamplit) { 196. if(!otmp->cursed) arti1_primed = TRUE; 197. else arti_cursed = TRUE; 198. } 199. if(otmp->otyp == BELL_OF_OPENING && 200. (moves - otmp->age) < 5L) { /* you rang it recently */ 201. if(!otmp->cursed) arti2_primed = TRUE; 202. else arti_cursed = TRUE; 203. } 204. } 205. 206. if(arti_cursed) { 207. pline_The("invocation fails!"); 208. pline("At least one of your artifacts is cursed..."); 209. } else if(arti1_primed && arti2_primed) { 210. mkinvokearea(); 211. u.uevent.invoked = 1; 212. } else { /* at least one artifact not prepared properly */ 213. You("have a feeling that %s is amiss...", something); 214. goto raise_dead; 215. } 216. return; 217. } 218. 219. /* when not an invocation situation */ 220. if (book2->cursed) { 221. raise_dead: 222. 223. You("raised the dead!"); 224. /* first maybe place a dangerous adversary */ 225. if (!rn2(3) && ((mtmp = makemon(&mons[PM_MASTER_LICH], 226. u.ux, u.uy, NO_MINVENT)) != 0 || 227. (mtmp = makemon(&mons[PM_NALFESHNEE], 228. u.ux, u.uy, NO_MINVENT)) != 0)) { 229. mtmp->mpeaceful = 0; 230. set_malign(mtmp); 231. } 232. /* next handle the affect on things you're carrying */ 233. (void) unturn_dead(&youmonst); 234. /* last place some monsters around you */ 235. mm.x = u.ux; 236. mm.y = u.uy; 237. mkundead(&mm, TRUE, NO_MINVENT); 238. } else if(book2->blessed) { 239. for(mtmp = fmon; mtmp; mtmp = mtmp2) { 240. mtmp2 = mtmp->nmon; /* tamedog() changes chain */ 241. if(is_undead(mtmp->data) && cansee(mtmp->mx, mtmp->my)) { 242. mtmp->mpeaceful = TRUE; 243. if(sgn(mtmp->data->maligntyp) == sgn(u.ualign.type) 244. && distu(mtmp->mx, mtmp->my) < 4) 245. if (mtmp->mtame) { 246. if (mtmp->mtame < 20) 247. mtmp->mtame++; 248. } else 249. (void) tamedog(mtmp, (struct obj *)0); 250. else mtmp->mflee = TRUE; 251. } 252. } 253. } else { 254. switch(rn2(3)) { 255. case 0: 256. Your("ancestors are annoyed with you!"); 257. break; 258. case 1: 259. pline_The("headstones in the cemetery begin to move!"); 260. break; 261. default: 262. pline("Oh my! Your name appears in the book!"); 263. } 264. } 265. return; 266. } 267. 268. STATIC_PTR int 269. learn() 270. { 271. int i; 272. short booktype; 273. char splname[BUFSZ]; 274. boolean costly = TRUE; 275. 276. if (delay) { /* not if (delay++), so at end delay == 0 */ 277. delay++; 278. return(1); /* still busy */ 279. } 280. exercise(A_WIS, TRUE); /* you're studying. */ 281. booktype = book->otyp; 282. if(booktype == SPE_BOOK_OF_THE_DEAD) { 283. deadbook(book); 284. return(0); 285. } 286. 287. Sprintf(splname, objects[booktype].oc_name_known ? 288. "\"%s\"" : "the \"%s\" spell", 289. OBJ_NAME(objects[booktype])); 290. for (i = 0; i < MAXSPELL; i++) { 291. if (spellid(i) == booktype) { 292. if (book->spestudied > MAX_SPELL_STUDY) { 293. pline("This spellbook is too faint to be read any more."); 294. book->otyp = booktype = SPE_BLANK_PAPER; 295. } else if (spellknow(i) <= 1000) { 296. Your("knowledge of %s is keener.", splname); 297. incrnknow(i); 298. book->spestudied++; 299. exercise(A_WIS,TRUE); /* extra study */ 300. } else { /* 1000 < spellknow(i) <= MAX_SPELL_STUDY */ 301. You("know %s quite well already.", splname); 302. costly = FALSE; 303. } 304. /* make book become known even when spell is already 305. known, in case amnesia made you forget the book */ 306. makeknown((int)booktype); 307. break; 308. } else if (spellid(i) == NO_SPELL) { 309. spl_book[i].sp_id = booktype; 310. spl_book[i].sp_lev = objects[booktype].oc_level; 311. incrnknow(i); 312. book->spestudied++; 313. You(i > 0 ? "add %s to your repertoire." : "learn %s.", 314. splname); 315. makeknown((int)booktype); 316. break; 317. } 318. } 319. if (i == MAXSPELL) impossible("Too many spells memorized!"); 320. 321. if (book->cursed) { /* maybe a demon cursed it */ 322. cursed_book(objects[booktype].oc_level); 323. } 324. if (costly) check_unpaid(book); 325. book = 0; 326. return(0); 327. } 328. 329. int 330. study_book(spellbook) 331. register struct obj *spellbook; 332. { 333. register int booktype = spellbook->otyp; 334. register boolean confused = (Confusion != 0); 335. boolean too_hard = FALSE; 336. 337. if (delay && spellbook == book && 338. /* handle the sequence: start reading, get interrupted, 339. have book become erased somehow, resume reading it */ 340. booktype != SPE_BLANK_PAPER) { 341. You("continue your efforts to memorize the spell."); 342. } else { 343. /* KMH -- Simplified this code */ 344. if (booktype == SPE_BLANK_PAPER) { 345. pline("This spellbook is all blank."); 346. makeknown(booktype); 347. return(1); 348. } 349. switch (objects[booktype].oc_level) { 350. case 1: 351. case 2: 352. delay = -objects[booktype].oc_delay; 353. break; 354. case 3: 355. case 4: 356. delay = -(objects[booktype].oc_level - 1) * 357. objects[booktype].oc_delay; 358. break; 359. case 5: 360. case 6: 361. delay = -objects[booktype].oc_level * 362. objects[booktype].oc_delay; 363. break; 364. case 7: 365. delay = -8 * objects[booktype].oc_delay; 366. break; 367. default: 368. impossible("Unknown spellbook level %d, book %d;", 369. objects[booktype].oc_level, booktype); 370. return 0; 371. } 372. 373. /* Books are often wiser than their readers (Rus.) */ 374. spellbook->in_use = TRUE; 375. if (!spellbook->blessed && spellbook->otyp != SPE_BOOK_OF_THE_DEAD) { 376. if (spellbook->cursed) { 377. too_hard = TRUE; 378. } else { 379. /* uncursed - chance to fail */ 380. int read_ability = ACURR(A_INT) + 4 + u.ulevel/2 381. - 2*objects[booktype].oc_level; 382. /* only wizards know if a spell is too difficult */ 383. if (Role_if(PM_WIZARD) && read_ability < 20) { 384. char qbuf[QBUFSZ]; 385. Sprintf(qbuf, 386. "This spellbook is %sdifficult to comprehend. Continue?", 387. (read_ability < 12 ? "very " : "")); 388. if (ynq(qbuf) != 'y') return(1); 389. } 390. /* its up to random luck now */ 391. if (rnd(20) > read_ability) { 392. too_hard = TRUE; 393. } 394. } 395. } 396. 397. if (too_hard) { 398. cursed_book(objects[booktype].oc_level); 399. nomul(delay); /* study time */ 400. delay = 0; 401. if(!rn2(3)) { 402. pline_The("spellbook crumbles to dust!"); 403. if (!objects[spellbook->otyp].oc_name_known && 404. !objects[spellbook->otyp].oc_uname) 405. docall(spellbook); 406. useup(spellbook); 407. } else 408. spellbook->in_use = FALSE; 409. return(1); 410. } else if (confused) { 411. if (!rn2(3) && 412. spellbook->otyp != SPE_BOOK_OF_THE_DEAD) { 413. pline( 414. "Being confused you have difficulties in controlling your actions."); 415. display_nhwindow(WIN_MESSAGE, FALSE); 416. You("accidentally tear the spellbook to pieces."); 417. if (!objects[spellbook->otyp].oc_name_known && 418. !objects[spellbook->otyp].oc_uname) 419. docall(spellbook); 420. useup(spellbook); 421. } else { 422. You( 423. "find yourself reading the first line over and over again."); 424. spellbook->in_use = FALSE; 425. } 426. nomul(delay); 427. delay = 0; 428. return(1); 429. } 430. spellbook->in_use = FALSE; 431. 432. You("begin to %s the runes.", 433. spellbook->otyp == SPE_BOOK_OF_THE_DEAD ? "recite" : 434. "memorize"); 435. } 436. 437. book = spellbook; 438. set_occupation(learn, "studying", 0); 439. return(1); 440. } 441. 442. /* renaming an object usually results in it having a different address; 443. so the sequence start reading, get interrupted, name the book, resume 444. reading would read the "new" book from scratch */ 445. void 446. book_substitution(old_obj, new_obj) 447. struct obj *old_obj, *new_obj; 448. { 449. if (old_obj == book) book = new_obj; 450. } 451. 452. /* called from moveloop() */ 453. void 454. age_spells() 455. { 456. int i; 457. /* 458. * The time relative to the hero (a pass through move 459. * loop) causes all spell knowledge to be decremented. 460. * The hero's speed, rest status, conscious status etc. 461. * does not alter the loss of memory. 462. */ 463. for (i = 0; i < MAXSPELL && spellid(i) != NO_SPELL; i++) 464. if (spellknow(i)) 465. decrnknow(i); 466. return; 467. } 468. 469. /* 470. * Return TRUE if a spell was picked, with the spell index in the return 471. * parameter. Otherwise return FALSE. 472. */ 473. static boolean 474. getspell(spell_no) 475. int *spell_no; 476. { 477. int nspells, idx; 478. char ilet, lets[BUFSZ], qbuf[QBUFSZ]; 479. 480. if (spellid(0) == NO_SPELL) { 481. You("don't know any spells right now."); 482. return FALSE; 483. } 484. if (flags.menu_style == MENU_TRADITIONAL) { 485. /* we know there is at least 1 known spell */ 486. for (nspells = 1; nspells < MAXSPELL 487. && spellid(nspells) != NO_SPELL; nspells++) 488. continue; 489. 490. if (nspells == 1) Strcpy(lets, "a"); 491. else if (nspells < 27) Sprintf(lets, "a-%c", 'a' + nspells - 1); 492. else if (nspells == 27) Sprintf(lets, "a-zA"); 493. else Sprintf(lets, "a-zA-%c", 'A' + nspells - 27); 494. 495. for(;;) { 496. Sprintf(qbuf, "Cast which spell? [%s ?]", lets); 497. if ((ilet = yn_function(qbuf, (char *)0, '\0')) == '?') 498. break; 499. 500. if (index(quitchars, ilet)) 501. return FALSE; 502. 503. idx = spell_let_to_idx(ilet); 504. if (idx >= 0 && idx < nspells) { 505. *spell_no = idx; 506. return TRUE; 507. } else 508. You("don't know that spell."); 509. } 510. } 511. return dospellmenu("Choose which spell to cast", 512. SPELLMENU_CAST, spell_no); 513. } 514. 515. /* the 'Z' command -- cast a spell */ 516. int 517. docast() 518. { 519. int spell_no; 520. 521. if (getspell(&spell_no)) 522. return spelleffects(spell_no, FALSE); 523. return 0; 524. } 525. 526. static const char * 527. spelltypemnemonic(skill) 528. int skill; 529. { 530. switch (skill) { 531. case P_ATTACK_SPELL: 532. return "attack"; 533. case P_HEALING_SPELL: 534. return "healing"; 535. case P_DIVINATION_SPELL: 536. return "divination"; 537. case P_ENCHANTMENT_SPELL: 538. return "enchantment"; 539. case P_CLERIC_SPELL: 540. return "clerical"; 541. case P_ESCAPE_SPELL: 542. return "escape"; 543. case P_MATTER_SPELL: 544. return "matter"; 545. default: 546. impossible("Unknown spell skill, %d;", skill); 547. return ""; 548. } 549. } 550. 551. int 552. spell_skilltype(booktype) 553. int booktype; 554. { 555. return (objects[booktype].oc_skill); 556. } 557. 558. static void 559. cast_protection() 560. { 561. int loglev = 0; 562. int l = u.ulevel; 563. int natac = u.uac - u.uspellprot; 564. int gain; 565. 566. /* loglev=log2(u.ulevel)+1 (1..5) */ 567. while (l) { 568. loglev++; 569. l /= 2; 570. } 571. 572. /* The more u.uspellprot you already have, the less you get, 573. * and the better your natural ac, the less you get. 574. * 575. * LEVEL AC SPELLPROT from sucessive SPE_PROTECTION casts 576. * 1 10 0, 1, 2, 3, 4 577. * 1 0 0, 1, 2, 3 578. * 1 -10 0, 1, 2 579. * 2-3 10 0, 2, 4, 5, 6, 7, 8 580. * 2-3 0 0, 2, 4, 5, 6 581. * 2-3 -10 0, 2, 3, 4 582. * 4-7 10 0, 3, 6, 8, 9, 10, 11, 12 583. * 4-7 0 0, 3, 5, 7, 8, 9 584. * 4-7 -10 0, 3, 5, 6 585. * 7-15 -10 0, 3, 5, 6 586. * 8-15 10 0, 4, 7, 10, 12, 13, 14, 15, 16 587. * 8-15 0 0, 4, 7, 9, 10, 11, 12 588. * 8-15 -10 0, 4, 6, 7, 8 589. * 16-30 10 0, 5, 9, 12, 14, 16, 17, 18, 19, 20 590. * 16-30 0 0, 5, 9, 11, 13, 14, 15 591. * 16-30 -10 0, 5, 8, 9, 10 592. */ 593. gain = loglev - (int)u.uspellprot / (4 - min(3,(10 - natac)/10)); 594. 595. if (gain > 0) { 596. if (!Blind) { 597. const char *hgolden = hcolor(golden); 598. 599. if (u.uspellprot) 600. pline_The("%s haze around you becomes more dense.", 601. hgolden); 602. else 603. pline_The("%s around you begins to shimmer with %s haze.", 604. /*[ what about being inside solid rock while polyd? ]*/ 605. (Underwater || Is_waterlevel(&u.uz)) ? "water" : "air", 606. an(hgolden)); 607. } 608. u.uspellprot += gain; 609. u.uspmtime = 610. P_SKILL(spell_skilltype(SPE_PROTECTION)) == P_EXPERT ? 20 : 10; 611. if (!u.usptime) 612. u.usptime = u.uspmtime; 613. find_ac(); 614. } else { 615. Your("skin feels warm for a moment."); 616. } 617. } 618. 619. int 620. spelleffects(spell, atme) 621. int spell; 622. boolean atme; 623. { 624. int energy, damage, chance, n, intell; 625. int skill, role_skill; 626. boolean confused = (Confusion != 0); 627. struct obj *pseudo; 628. coord cc; 629. 630. /* 631. * Spell casting no longer affects knowledge of the spell. A 632. * decrement of spell knowledge is done every turn. 633. */ 634. if (spellknow(spell) <= 0) { 635. Your("knowledge of this spell is twisted."); 636. pline("It invokes nightmarish images in your mind..."); 637. make_confused((long)spellev(spell) * 3, FALSE); 638. return(0); 639. } else if (spellknow(spell) <= 100) { 640. You("strain to recall the spell."); 641. } else if (spellknow(spell) <= 1000) { 642. Your("knowledge of this spell is growing faint."); 643. } 644. energy = (spellev(spell) * 5); /* 5 <= energy <= 35 */ 645. 646. if (u.uhunger <= 10 && spellid(spell) != SPE_DETECT_FOOD) { 647. You("are too hungry to cast that spell."); 648. return(0); 649. } else if (ACURR(A_STR) < 4) { 650. You("lack the strength to cast spells."); 651. return(0); 652. } else if(check_capacity( 653. "Your concentration falters while carrying so much stuff.")) { 654. return (1); 655. } else if (!freehand()) { 656. Your("arms are not free to cast!"); 657. return (0); 658. } 659. 660. if (u.uhave.amulet) { 661. You_feel("the amulet draining your energy away."); 662. energy += rnd(2*energy); 663. } 664. if(energy > u.uen) { 665. You("don't have enough energy to cast that spell."); 666. return(0); 667. } else { 668. if (spellid(spell) != SPE_DETECT_FOOD) { 669. int hungr = energy * 2; 670. 671. /* don't put player (quite) into fainting from 672. * casting a spell, particularly since they might 673. * not even be hungry at the beginning; however, 674. * this is low enough that they must eat before 675. * casting anything else except detect food 676. */ 677. if (hungr > u.uhunger-3) 678. hungr = u.uhunger-3; 679. /* If hero is a wizard, their current intelligence 680. * (bonuses + temporary + current) 681. * affects hunger reduction in casting a spell. 682. * 1. int = 17-18 no reduction 683. * 2. int = 16 1/4 hungr 684. * 3. int = 15 1/2 hungr 685. * 4. int = 1-14 normal reduction 686. * The reason for this is: 687. * a) Intelligence affects the amount of exertion 688. * in thinking. 689. * b) Wizards have spent their life at magic and 690. * understand quite well how to cast spells. 691. */ 692. intell = acurr(A_INT); 693. switch (intell) { 694. case 18: 695. case 17: hungr = 0; break; 696. case 16: hungr /= 4; break; 697. case 15: hungr /= 2; break; 698. } 699. morehungry(hungr); 700. } 701. } 702. 703. chance = percent_success(spell); 704. if (confused || (rnd(100) > chance)) { 705. You("fail to cast the spell correctly."); 706. u.uen -= energy / 2; 707. flags.botl = 1; 708. return(1); 709. } 710. 711. u.uen -= energy; 712. flags.botl = 1; 713. exercise(A_WIS, TRUE); 714. /* pseudo is a temporary "false" object containing the spell stats */ 715. pseudo = mksobj(spellid(spell), FALSE, FALSE); 716. pseudo->blessed = pseudo->cursed = 0; 717. pseudo->quan = 20L; /* do not let useup get it */ 718. /* 719. * Find the skill the hero has in a spell type category. 720. * See spell_skilltype for categories. 721. */ 722. skill = spell_skilltype(pseudo->otyp); 723. role_skill = P_SKILL(skill); 724. 725. switch(pseudo->otyp) { 726. /* 727. * At first these act as expected. As the character increases in 728. * experience the spell increases in its ability. Initially the 729. * spells have their expected levels of damage. When the hero level 730. * reaches three times the level of the spell the spell does special 731. * damage. This special damage is indicated before each spell. Note 732. * even when the hero reaches three times the level of the spell she 733. * still has the choice of casting either spell. Also the new level 734. * of spell has an increased cost in casting it. 735. */ 736. case SPE_CONE_OF_COLD: 737. case SPE_FIREBALL: 738. if (role_skill >= P_SKILLED) { 739. if (throwspell()) { 740. cc.x=u.dx;cc.y=u.dy; 741. n=rnd(8)+1; 742. while(n--) { 743. if(!u.dx && !u.dy && !u.dz) { 744. if ((damage = zapyourself(pseudo, TRUE)) != 0) 745. losehp(damage, 746. self_pronoun("zapped %sself with a spell", 747. "him"), 748. NO_KILLER_PREFIX); 749. } else { 750. explode(u.dx, u.dy, 751. pseudo->otyp - SPE_MAGIC_MISSILE + 10, 752. u.ulevel/2 + 1 + spell_damage_bonus(), 0); 753. } 754. u.dx = cc.x+rnd(3)-2; u.dy = cc.y+rnd(3)-2; 755. if (!cansee(u.dx,u.dy) || IS_STWALL(levl[u.dx][u.dy].typ)) { 756. /* Spell is reflected back to center */ 757. u.dx = cc.x; 758. u.dy = cc.y; 759. } 760. } 761. } 762. break; 763. } /* else fall through... */ 764. 765. /* these spells are all duplicates of wand effects */ 766. case SPE_FORCE_BOLT: 767. case SPE_SLEEP: 768. case SPE_MAGIC_MISSILE: 769. case SPE_KNOCK: 770. case SPE_SLOW_MONSTER: 771. case SPE_WIZARD_LOCK: 772. case SPE_DIG: 773. case SPE_TURN_UNDEAD: 774. case SPE_POLYMORPH: 775. case SPE_TELEPORT_AWAY: 776. case SPE_CANCELLATION: 777. case SPE_FINGER_OF_DEATH: 778. case SPE_LIGHT: 779. case SPE_DETECT_UNSEEN: 780. case SPE_HEALING: 781. case SPE_EXTRA_HEALING: 782. case SPE_DRAIN_LIFE: 783. case SPE_STONE_TO_FLESH: 784. if (!(objects[pseudo->otyp].oc_dir == NODIR)) { 785. if (atme) u.dx = u.dy = u.dz = 0; 786. else (void) getdir((char *)0); 787. if(!u.dx && !u.dy && !u.dz) { 788. if ((damage = zapyourself(pseudo, TRUE)) != 0) 789. losehp(damage, 790. self_pronoun("zapped %sself with a spell", 791. "him"), 792. NO_KILLER_PREFIX); 793. } else weffects(pseudo); 794. } else weffects(pseudo); 795. break; 796. 797. /* these are all duplicates of scroll effects */ 798. case SPE_REMOVE_CURSE: 799. /* 800. * When the hero is skilled enough the spell is equivalent 801. * to a blessed scroll. 802. */ 803. if (role_skill >= P_SKILLED) 804. pseudo->blessed=1; 805. /* fall through */ 806. case SPE_CONFUSE_MONSTER: 807. case SPE_DETECT_FOOD: 808. case SPE_CAUSE_FEAR: 809. case SPE_CHARM_MONSTER: 810. case SPE_MAGIC_MAPPING: 811. case SPE_CREATE_MONSTER: 812. case SPE_IDENTIFY: 813. (void) seffects(pseudo); 814. break; 815. 816. /* these are all duplicates of potion effects */ 817. case SPE_HASTE_SELF: 818. case SPE_DETECT_TREASURE: 819. case SPE_DETECT_MONSTERS: 820. case SPE_LEVITATION: 821. case SPE_RESTORE_ABILITY: 822. case SPE_INVISIBILITY: 823. (void) peffects(pseudo); 824. break; 825. 826. case SPE_CURE_BLINDNESS: 827. healup(0, 0, FALSE, TRUE); 828. break; 829. case SPE_CURE_SICKNESS: 830. if (Sick) You("are no longer ill."); 831. if (Slimed) { 832. pline("The slime disappears!"); 833. Slimed = 0; 834. } 835. healup(0, 0, TRUE, FALSE); 836. break; 837. case SPE_CREATE_FAMILIAR: 838. (void) make_familiar((struct obj *)0, u.ux, u.uy, FALSE); 839. break; 840. case SPE_CLAIRVOYANCE: 841. if (!BClairvoyant) 842. do_vicinity_map(); 843. /* at present, only one thing blocks clairvoyance */ 844. else if (uarmh && uarmh->otyp == CORNUTHAUM) 845. You("sense a pointy hat on top of your %s.", 846. body_part(HEAD)); 847. break; 848. case SPE_PROTECTION: 849. cast_protection(); 850. break; 851. case SPE_JUMPING: 852. if (!jump(role_skill)) 853. pline("Nothing happens."); 854. break; 855. default: 856. impossible("Unknown spell %d attempted.", spell); 857. obfree(pseudo, (struct obj *)0); 858. return(0); 859. } 860. 861. /* gain skill for successful cast */ 862. if (role_skill != P_ISRESTRICTED && role_skill < P_EXPERT) 863. use_skill(skill, spellev(spell)); 864. 865. obfree(pseudo, (struct obj *)0); /* now, get rid of it */ 866. return(1); 867. } 868. 869. /* Choose location where spell takes effect. */ 870. static int 871. throwspell() 872. { 873. coord cc; 874. 875. if (u.uinwater) { 876. pline("You're joking! In this weather?"); return 0; 877. } else if (Is_waterlevel(&u.uz)) { 878. You("had better wait for the sun to come out."); return 0; 879. } 880. 881. pline("Where do you want to cast the spell?"); 882. cc.x = u.ux; 883. cc.y = u.uy; 884. if (getpos(&cc, TRUE, "the desired position") < 0) 885. return 0; /* user pressed ESC */ 886. /* The number of moves from hero to where the spell drops.*/ 887. if (distmin(u.ux, u.uy, cc.x, cc.y) > 10) { 888. pline("The spell dissipates over the distance!"); 889. return 0; 890. } else if (u.uswallow) { 891. pline("The spell is cut short!"); 892. exercise(A_WIS, FALSE); /* What were you THINKING! */ 893. u.dx = 0; 894. u.dy = 0; 895. return 1; 896. } else if (!cansee(cc.x, cc.y) || IS_STWALL(levl[cc.x][cc.y].typ)) { 897. Your("mind fails to lock onto that location!"); 898. return 0; 899. } else { 900. u.dx=cc.x; 901. u.dy=cc.y; 902. return 1; 903. } 904. } 905. 906. void 907. losespells() 908. { 909. boolean confused = (Confusion != 0); 910. int n, nzap, i; 911. 912. book = 0; 913. for (n = 0; n < MAXSPELL && spellid(n) != NO_SPELL; n++) 914. continue; 915. if (n) { 916. nzap = rnd(n) + confused ? 1 : 0; 917. if (nzap > n) nzap = n; 918. for (i = n - nzap; i < n; i++) { 919. spellid(i) = NO_SPELL; 920. exercise(A_WIS, FALSE); /* ouch! */ 921. } 922. } 923. } 924. 925. /* the '+' command -- view known spells */ 926. int 927. dovspell() 928. { 929. char qbuf[QBUFSZ]; 930. int splnum, othnum; 931. struct spell spl_tmp; 932. 933. if (spellid(0) == NO_SPELL) 934. You("don't know any spells right now."); 935. else { 936. while (dospellmenu("Currently known spells", 937. SPELLMENU_VIEW, &splnum)) { 938. Sprintf(qbuf, "Reordering spells; swap '%c' with", 939. spellet(splnum)); 940. if (!dospellmenu(qbuf, splnum, &othnum)) break; 941. 942. spl_tmp = spl_book[splnum]; 943. spl_book[splnum] = spl_book[othnum]; 944. spl_book[othnum] = spl_tmp; 945. } 946. } 947. return 0; 948. } 949. 950. static boolean 951. dospellmenu(prompt, splaction, spell_no) 952. const char *prompt; 953. int splaction; /* SPELLMENU_CAST, SPELLMENU_VIEW, or spl_book[] index */ 954. int *spell_no; 955. { 956. winid tmpwin; 957. int i, n, how; 958. char buf[BUFSZ]; 959. menu_item *selected; 960. anything any; 961. 962. tmpwin = create_nhwindow(NHW_MENU); 963. start_menu(tmpwin); 964. any.a_void = 0; /* zero out all bits */ 965. 966. /* 967. * The correct spacing of the columns depends on the 968. * following that (1) the font is monospaced and (2) 969. * that selection letters are pre-pended to the given 970. * string and are of the form "a - ". 971. * 972. * To do it right would require that we implement columns 973. * in the window-ports (say via a tab character). 974. */ 975. Sprintf(buf, "%-20s Level %-12s Fail", " Name", "Category"); 976. add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED); 977. for (i = 0; i < MAXSPELL && spellid(i) != NO_SPELL; i++) { 978. Sprintf(buf, "%-20s %2d%s %-12s %3d%%", 979. spellname(i), spellev(i), 980. spellknow(i) ? " " : "*", 981. spelltypemnemonic(spell_skilltype(spellid(i))), 982. 100 - percent_success(i)); 983. 984. any.a_int = i+1; /* must be non-zero */ 985. add_menu(tmpwin, NO_GLYPH, &any, 986. spellet(i), 0, ATR_NONE, buf, 987. (i == splaction) ? MENU_SELECTED : MENU_UNSELECTED); 988. } 989. end_menu(tmpwin, prompt); 990. 991. how = PICK_ONE; 992. if (splaction == SPELLMENU_VIEW && spellid(1) == NO_SPELL) 993. how = PICK_NONE; /* only one spell => nothing to swap with */ 994. n = select_menu(tmpwin, how, &selected); 995. destroy_nhwindow(tmpwin); 996. if (n > 0) { 997. *spell_no = selected[0].item.a_int - 1; 998. /* menu selection for `PICK_ONE' does not 999. de-select any preselected entry */ 1000. if (n > 1 && *spell_no == splaction) 1001. *spell_no = selected[1].item.a_int - 1; 1002. free((genericptr_t)selected); 1003. /* default selection of preselected spell means that 1004. user chose not to swap it with anything */ 1005. if (*spell_no == splaction) return FALSE; 1006. return TRUE; 1007. } else if (splaction >= 0) { 1008. /* explicit de-selection of preselected spell means that 1009. user is still swapping but not for the current spell */ 1010. *spell_no = splaction; 1011. return TRUE; 1012. } 1013. return FALSE; 1014. } 1015. 1016. /* Integer square root function without using floating point. */ 1017. static int 1018. isqrt(val) 1019. int val; 1020. { 1021. int rt = 0; 1022. int odd = 1; 1023. while(val >= odd) { 1024. val = val-odd; 1025. odd = odd+2; 1026. rt = rt + 1; 1027. } 1028. return rt; 1029. } 1030. 1031. static int 1032. percent_success(spell) 1033. int spell; 1034. { 1035. /* Intrinsic and learned ability are combined to calculate 1036. * the probability of player's success at cast a given spell. 1037. */ 1038. int chance, splcaster, special, statused; 1039. int difficulty; 1040. int skill; 1041. 1042. /* Calculate intrinsic ability (splcaster) */ 1043. 1044. splcaster = urole.spelbase; 1045. special = urole.spelheal; 1046. statused = ACURR(urole.spelstat); 1047. 1048. if (uarm && is_metallic(uarm)) 1049. splcaster += (uarmc && uarmc->otyp == ROBE) ? 1050. urole.spelarmr/2 : urole.spelarmr; 1051. else if (uarmc && uarmc->otyp == ROBE) 1052. splcaster -= urole.spelarmr; 1053. if (uarms) splcaster += urole.spelshld; 1054. 1055. if (uarmh && is_metallic(uarmh) && uarmh->otyp != HELM_OF_BRILLIANCE) 1056. splcaster += uarmhbon; 1057. if (uarmg && is_metallic(uarmg)) splcaster += uarmgbon; 1058. if (uarmf && is_metallic(uarmf)) splcaster += uarmfbon; 1059. 1060. if (spellid(spell) == urole.spelspec) 1061. splcaster += urole.spelsbon; 1062. 1063. 1064. /* `healing spell' bonus */ 1065. if (spellid(spell) == SPE_HEALING || 1066. spellid(spell) == SPE_EXTRA_HEALING || 1067. spellid(spell) == SPE_CURE_BLINDNESS || 1068. spellid(spell) == SPE_CURE_SICKNESS || 1069. spellid(spell) == SPE_RESTORE_ABILITY || 1070. spellid(spell) == SPE_REMOVE_CURSE) splcaster += special; 1071. 1072. if (splcaster > 20) splcaster = 20; 1073. 1074. /* Calculate learned ability */ 1075. 1076. /* Players basic likelihood of being able to cast any spell 1077. * is based of their `magic' statistic. (Int or Wis) 1078. */ 1079. chance = 11 * statused / 2; 1080. 1081. /* 1082. * High level spells are harder. Easier for higher level casters. 1083. * The difficulty is based on the hero's level and their skill level 1084. * in that spell type. 1085. */ 1086. skill = P_SKILL(spell_skilltype(spellid(spell)))-1; 1087. difficulty= (spellev(spell)-1) * 4 - ((skill * 6) + (u.ulevel/3) + 1); 1088. 1089. if (difficulty > 0) { 1090. /* Player is too low level or unskilled. */ 1091. chance -= isqrt(900 * difficulty + 2000); 1092. } else { 1093. /* Player is above level. Learning continues, but the 1094. * law of diminishing returns sets in quickly for 1095. * low-level spells. That is, a player quickly gains 1096. * no advantage for raising level. 1097. */ 1098. int learning = 15 * -difficulty / spellev(spell); 1099. chance += learning > 20 ? 20 : learning; 1100. } 1101. 1102. /* Clamp the chance: >18 stat and advanced learning only help 1103. * to a limit, while chances below "hopeless" only raise the 1104. * specter of overflowing 16-bit ints (and permit wearing a 1105. * shield to raise the chances :-). 1106. */ 1107. if (chance < 0) chance = 0; 1108. if (chance > 120) chance = 120; 1109. 1110. /* Wearing anything but a light shield makes it very awkward 1111. * to cast a spell. The penalty is not quite so bad for the 1112. * player's role-specific spell. 1113. */ 1114. if (uarms && weight(uarms) > (int) objects[SMALL_SHIELD].oc_weight) { 1115. if (spellid(spell) == urole.spelspec) { 1116. chance /= 2; 1117. } else { 1118. chance /= 4; 1119. } 1120. } 1121. 1122. /* Finally, chance (based on player intell/wisdom and level) is 1123. * combined with ability (based on player intrinsics and 1124. * encumberances). No matter how intelligent/wise and advanced 1125. * a player is, intrinsics and encumberance can prevent casting; 1126. * and no matter how able, learning is always required. 1127. */ 1128. chance = chance * (20-splcaster) / 15 - splcaster; 1129. 1130. /* Clamp to percentile */ 1131. if (chance > 100) chance = 100; 1132. if (chance < 0) chance = 0; 1133. 1134. return chance; 1135. } 1136. 1137. 1138. /* Learn a spell during creation of the initial inventory */ 1139. void 1140. initialspell(obj) 1141. struct obj *obj; 1142. { 1143. int i; 1144. 1145. for (i = 0; i < MAXSPELL; i++) { 1146. if (spellid(i) == obj->otyp) { 1147. pline("Error: Spell %s already known.", 1148. OBJ_NAME(objects[obj->otyp])); 1149. return; 1150. } 1151. if (spellid(i) == NO_SPELL) { 1152. spl_book[i].sp_id = obj->otyp; 1153. spl_book[i].sp_lev = objects[obj->otyp].oc_level; 1154. incrnknow(i); 1155. return; 1156. } 1157. } 1158. impossible("Too many spells memorized!"); 1159. return; 1160. } 1161. 1162. 1163. /*spell.c*/