abstract
| - 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 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*/
|