About: Source:NetHack 3.2.0/spell.c   Sponge Permalink

An Entity of Type : owl:Thing, within Data Space : 134.155.108.49:8890 associated with source dataset(s)

Below is the full text to spell.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.0/spell.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code

AttributesValues
rdfs:label
  • Source:NetHack 3.2.0/spell.c
rdfs:comment
  • Below is the full text to spell.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.0/spell.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code
dcterms:subject
dbkwik:nethack/pro...iPageUsesTemplate
abstract
  • Below is the full text to spell.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.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.2 96/03/16 */ 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. #define spelluses(spell) spl_book[spell].sp_uses 11. #define decrnuses(spell) spl_book[spell].sp_uses-- 12. #define spellev(spell) spl_book[spell].sp_lev 13. #define spellid(spell) spl_book[spell].sp_id 14. #define spellname(spell) OBJ_NAME(objects[spellid(spell)]) 15. #define spellet(spell) \ 16. ((char)((spell < 26) ? ('a' + spell) : ('A' + spell - 26))) 17. 18. static void FDECL(cursed_book, (int)); 19. static void FDECL(deadbook, (struct obj *)); 20. STATIC_PTR int NDECL(learn); 21. static boolean FDECL(getspell, (int *)); 22. static boolean FDECL(dospellmenu, (int, int *)); 23. static int FDECL(percent_success, (int)); 24. 25. /* The cl_sptmp table lists the class-specific values for tuning 26. * percent_success(). 27. * 28. * Reasoning: 29. * splcaster, special: 30. * A are aware of magic through historical research 31. * B abhor magic (Conan finds it "interferes with his animal instincts") 32. * C are ignorant to magic 33. * E are from a magical realm 34. * H are very aware of healing magic through medical research 35. * K are moderately aware of healing from Paladin training 36. * P are very aware of healing magic through theological research 37. * R are moderately aware of magic through trickery 38. * S have limited magical awareness, prefering meditation to conjuring 39. * T are aware of magic from all the great films they have seen 40. * V have limited magical awareness, prefering fighting 41. * W are trained mages 42. * 43. * The arms penalty is lessened for trained fighters B, K, S, V - 44. * the penalty is its metal interference, not encumberance. 45. * The `specspel' is a single spell which is fundamentally easier 46. * for that class to cast. 47. * 48. * specspel, specbon: 49. * A map masters (SPE_MAGIC_MAPPING) 50. * B fugue/berserker (SPE_HASTE_SELF) 51. * C born to dig (SPE_DIG) 52. * E infra-like vision (SPE_DETECT_UNSEEN) 53. * H to heal (SPE_CURE_SICKNESS) 54. * K to turn back evil (SPE_TURN_UNDEAD) 55. * P to bless (SPE_REMOVE_CURSE) 56. * R to find loot (SPE_DETECT_TREASURE) 57. * S to be At One (SPE_CLAIRVOYANCE) 58. * T to smile (SPE_CHARM_MONSTER) 59. * V control the cold (SPE_CONE_OF_COLD) 60. * W all really, but SPE_MAGIC_MISSILE is their party trick 61. * 62. * See percent_success() below for more comments. 63. * 64. * uarmbon, uarmsbon, uarmhbon, uarmgbon, uarmfbon: 65. * Fighters find body armour & shield a little less limiting. 66. * Headgear, Gauntlets and Footwear are not class-specific (but 67. * still have an effect, except helm of brilliance, which is designed 68. * to permit magic-use). 69. */ 70. static struct sptmp { 71. char class; /* key */ 72. int splcaster; /* base spellcasting ability */ 73. int special; /* healing spell bonus */ 74. int uarmsbon; /* penalty for wearing a (small) shield */ 75. int uarmbon; /* penalty for wearing metal armour */ 76. int statused; /* which stat is used */ 77. int specspel; /* spell the class excels at */ 78. int specbon; /* bonus when casting specspel */ 79. } cl_sptmp[] = { 80. { 'A', 5, 0, 2, 10, A_INT, SPE_MAGIC_MAPPING, -4 }, 81. { 'B', 14, 0, 0, 8, A_INT, SPE_HASTE_SELF, -4 }, 82. { 'C', 12, 0, 1, 8, A_INT, SPE_DIG, -4 }, 83. { 'E', 5, 0, 1, 10, A_INT, SPE_DETECT_UNSEEN, -4 }, 84. { 'H', 3,-3, 2, 10, A_WIS, SPE_CURE_SICKNESS, -4 }, 85. { 'K', 8,-2, 0, 9, A_WIS, SPE_TURN_UNDEAD, -4 }, 86. { 'P', 3,-2, 2, 10, A_WIS, SPE_REMOVE_CURSE, -4 }, 87. { 'R', 8, 0, 1, 9, A_INT, SPE_DETECT_TREASURE, -4 }, 88. { 'S', 10, 0, 0, 8, A_INT, SPE_CLAIRVOYANCE, -4 }, 89. #ifdef TOURIST 90. { 'T', 5, 1, 2, 10, A_INT, SPE_CHARM_MONSTER, -4 }, 91. #endif 92. { 'V', 10,-2, 0, 9, A_WIS, SPE_CONE_OF_COLD, -4 }, 93. { 'W', 1, 0, 3, 10, A_INT, SPE_MAGIC_MISSILE, -4 }, 94. { 0, 10, 0, 0, 4, A_INT, 0, -3 } 95. }; 96. 97. #define uarmhbon 4 /* Metal helmets interfere with the mind */ 98. #define uarmgbon 6 /* Casting channels through the hands */ 99. #define uarmfbon 2 /* All metal interferes to some degree */ 100. 101. /* since the spellbook itself doesn't blow up, don't say just "explodes" */ 102. static const char explodes[] = "radiates explosive energy"; 103. 104. static void 105. cursed_book(lev) 106. register int lev; 107. { 108. switch(rn2(lev)) { 109. case 0: 110. You_feel("a wrenching sensation."); 111. tele(); /* teleport him */ 112. break; 113. case 1: 114. You_feel("threatened."); 115. aggravate(); 116. break; 117. case 2: 118. make_blinded(Blinded + rn1(100,250),TRUE); 119. break; 120. case 3: 121. take_gold(); 122. break; 123. case 4: 124. pline("These runes were just too much to comprehend."); 125. make_confused(HConfusion + rn1(7,16),FALSE); 126. break; 127. case 5: 128. pline_The("book was coated with contact poison!"); 129. if (uarmg) { 130. /* Note: at this writing, there are no corrodeable 131. * gloves in the game. If no one plans on adding 132. * copper gauntlets, most of this could be removed. -3. 133. */ 134. if (uarmg->oerodeproof || !is_corrodeable(uarmg)) { 135. Your("gloves seem unaffected."); 136. } else if (uarmg->oeroded < MAX_ERODE) { 137. Your("gloves corrode%s!", 138. uarmg->oeroded+1 == MAX_ERODE ? " completely" : 139. uarmg->oeroded ? " further" : ""); 140. uarmg->oeroded++; 141. } else 142. Your("gloves %s completely corroded.", 143. Blind ? "feel" : "look"); 144. break; 145. } 146. losestr(Poison_resistance ? rn1(2,1) : rn1(4,3)); 147. losehp(rnd(Poison_resistance ? 6 : 10), 148. "contact-poisoned spellbook", KILLED_BY_AN); 149. break; 150. case 6: 151. if(Antimagic) { 152. shieldeff(u.ux, u.uy); 153. pline_The("book %s, but you are unharmed!", explodes); 154. } else { 155. pline("As you read the book, it %s in your %s!", 156. explodes, body_part(FACE)); 157. losehp (2*rnd(10)+5, "exploding rune", KILLED_BY_AN); 158. } 159. break; 160. default: 161. rndcurse(); 162. break; 163. } 164. return; 165. } 166. 167. /* special effects for The Book of the Dead */ 168. static void 169. deadbook(book2) 170. struct obj *book2; 171. { 172. You("turn the pages of the Book of the Dead..."); 173. makeknown(SPE_BOOK_OF_THE_DEAD); 174. if(invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) { 175. register struct obj *otmp; 176. register boolean arti1_primed = FALSE, arti2_primed = FALSE, 177. arti_cursed = FALSE; 178. 179. if(book2->cursed) { 180. pline_The("runes appear scrambled. You can't read them!"); 181. return; 182. } 183. 184. if(!u.uhave.bell || !u.uhave.menorah) { 185. pline("A chill runs down your %s.", body_part(SPINE)); 186. if(!u.uhave.bell) You_hear("a faint chime..."); 187. if(!u.uhave.menorah) pline("Vlad's doppelganger is amused."); 188. return; 189. } 190. 191. for(otmp = invent; otmp; otmp = otmp->nobj) { 192. if(otmp->otyp == CANDELABRUM_OF_INVOCATION && 193. otmp->spe == 7 && otmp->lamplit) { 194. if(!otmp->cursed) arti1_primed = TRUE; 195. else arti_cursed = TRUE; 196. } 197. if(otmp->otyp == BELL_OF_OPENING && 198. (moves - otmp->age) < 5L) { /* you rang it recently */ 199. if(!otmp->cursed) arti2_primed = TRUE; 200. else arti_cursed = TRUE; 201. } 202. } 203. 204. if(arti_cursed) { 205. pline_The("invocation fails!"); 206. pline("At least one of your artifacts is cursed..."); 207. } else if(arti1_primed && arti2_primed) { 208. mkinvokearea(); 209. u.uevent.invoked = 1; 210. } else { /* at least one artifact not prepared properly */ 211. You("have a feeling that %s is amiss...", something); 212. goto raise_dead; 213. } 214. return; 215. } 216. 217. /* when not an invocation situation */ 218. if(book2->cursed) 219. raise_dead: 220. { 221. register struct monst *mtmp; 222. coord mm; 223. 224. You("raised the dead!"); 225. mm.x = u.ux; 226. mm.y = u.uy; 227. mkundead(&mm); 228. if(!rn2(4)) 229. if ((mtmp = makemon(&mons[PM_MASTER_LICH],u.ux,u.uy)) != 0) { 230. mtmp->mpeaceful = 0; 231. set_malign(mtmp); 232. } 233. } else if(book2->blessed) { 234. register struct monst *mtmp, *mtmp2; 235. 236. for(mtmp = fmon; mtmp; mtmp = mtmp2) { 237. mtmp2 = mtmp->nmon; /* tamedog() changes chain */ 238. if(is_undead(mtmp->data) && cansee(mtmp->mx, mtmp->my)) { 239. mtmp->mpeaceful = TRUE; 240. if(sgn(mtmp->data->maligntyp) == sgn(u.ualign.type) 241. && distu(mtmp->mx, mtmp->my) < 4) 242. if (mtmp->mtame) 243. mtmp->mtame++; 244. else 245. (void) tamedog(mtmp, (struct obj *)0); 246. else mtmp->mflee = TRUE; 247. } 248. } 249. } else { 250. switch(rn2(3)) { 251. case 0: 252. Your("ancestors are annoyed with you!"); 253. break; 254. case 1: 255. pline_The("headstones in the cemetery begin to move!"); 256. break; 257. default: 258. pline("Oh my! Your name appears in the book!"); 259. } 260. } 261. return; 262. } 263. 264. STATIC_PTR int 265. learn() 266. { 267. int i; 268. short booktype; 269. 270. if (delay) { /* not if (delay++), so at end delay == 0 */ 271. delay++; 272. return(1); /* still busy */ 273. } 274. exercise(A_WIS, TRUE); /* you're studying. */ 275. booktype = book->otyp; 276. if(booktype == SPE_BOOK_OF_THE_DEAD) { 277. deadbook(book); 278. return(0); 279. } 280. 281. for (i = 0; i < MAXSPELL; i++) { 282. if (spellid(i) == booktype) { 283. if (book->spestudied >= rnd(30 - spellev(i))) { 284. pline("This spellbook is too faint to be read anymore."); 285. book->otyp = booktype = SPE_BLANK_PAPER; 286. makeknown((int)booktype); 287. } 288. else if (spelluses(i) < 20 - spellev(i)) { 289. Your("knowledge of that spell is keener."); 290. spl_book[i].sp_uses += 10 - spellev(i); 291. book->spestudied++; 292. exercise(A_WIS, TRUE); /* extra study */ 293. } else 294. You("know that spell quite well already."); 295. break; 296. } else if (spellid(i) == NO_SPELL) { 297. spl_book[i].sp_id = booktype; 298. spl_book[i].sp_lev = objects[booktype].oc_level; 299. spl_book[i].sp_uses = 30 - spellev(i); 300. book->spestudied++; 301. You("add the spell to your repertoire."); 302. makeknown((int)booktype); 303. break; 304. } 305. } 306. if (i == MAXSPELL) impossible("Too many spells memorized!"); 307. 308. if (book->cursed) { /* maybe a demon cursed it */ 309. cursed_book(objects[booktype].oc_level); 310. } 311. check_unpaid(book); 312. book = 0; 313. return(0); 314. } 315. 316. int 317. study_book(spellbook) 318. register struct obj *spellbook; 319. { 320. register int booktype = spellbook->otyp; 321. register boolean confused = (Confusion != 0); 322. 323. if (delay && spellbook == book) 324. You("continue your efforts to memorize the spell."); 325. else { 326. switch(booktype) { 327. 328. /* blank spellbook */ 329. case SPE_BLANK_PAPER: 330. pline("This spellbook is all blank."); 331. makeknown(SPE_BLANK_PAPER); 332. return(1); 333. /* level 1 spells */ 334. case SPE_HEALING: 335. case SPE_DETECT_MONSTERS: 336. case SPE_FORCE_BOLT: 337. case SPE_LIGHT: 338. case SPE_SLEEP: 339. case SPE_KNOCK: 340. /* level 2 spells */ 341. case SPE_MAGIC_MISSILE: 342. case SPE_CONFUSE_MONSTER: 343. case SPE_SLOW_MONSTER: 344. case SPE_CURE_BLINDNESS: 345. case SPE_CREATE_MONSTER: 346. case SPE_DETECT_FOOD: 347. case SPE_WIZARD_LOCK: 348. delay = -objects[booktype].oc_delay; 349. break; 350. /* level 3 spells */ 351. case SPE_HASTE_SELF: 352. case SPE_CAUSE_FEAR: 353. case SPE_CURE_SICKNESS: 354. case SPE_DETECT_UNSEEN: 355. case SPE_EXTRA_HEALING: 356. case SPE_CHARM_MONSTER: 357. case SPE_CLAIRVOYANCE: 358. /* level 4 spells */ 359. case SPE_LEVITATION: 360. case SPE_RESTORE_ABILITY: 361. case SPE_INVISIBILITY: 362. case SPE_FIREBALL: 363. case SPE_DETECT_TREASURE: 364. delay = -(objects[booktype].oc_level - 1) * objects[booktype].oc_delay; 365. break; 366. /* level 5 spells */ 367. case SPE_REMOVE_CURSE: 368. case SPE_MAGIC_MAPPING: 369. case SPE_CONE_OF_COLD: 370. case SPE_IDENTIFY: 371. case SPE_DIG: 372. /* level 6 spells */ 373. case SPE_TURN_UNDEAD: 374. case SPE_POLYMORPH: 375. case SPE_CREATE_FAMILIAR: 376. case SPE_TELEPORT_AWAY: 377. delay = -objects[booktype].oc_level * objects[booktype].oc_delay; 378. break; 379. /* level 7 spells */ 380. case SPE_CANCELLATION: 381. case SPE_FINGER_OF_DEATH: 382. case SPE_BOOK_OF_THE_DEAD: 383. delay = -8 * objects[booktype].oc_delay; 384. break; 385. /* impossible */ 386. default: 387. impossible("Unknown spellbook, %d;", booktype); 388. return(0); 389. } 390. 391. /* Books are often wiser than their readers (Rus.) */ 392. if(!spellbook->blessed && 393. spellbook->otyp != SPE_BOOK_OF_THE_DEAD && 394. (spellbook->cursed || 395. rn2(20) > (ACURR(A_INT) + 4 + u.ulevel/2 396. - 2*objects[booktype].oc_level))) { 397. cursed_book(objects[booktype].oc_level); 398. nomul(delay); /* study time */ 399. delay = 0; 400. if(!rn2(3)) { 401. useup(spellbook); 402. pline_The("spellbook crumbles to dust!"); 403. } 404. return(1); 405. } 406. else if(confused) { 407. if(!rn2(3) && 408. spellbook->otyp != SPE_BOOK_OF_THE_DEAD) { 409. useup(spellbook); 410. pline("Being confused you have difficulties in controlling your actions."); 411. display_nhwindow(WIN_MESSAGE, FALSE); 412. You("accidentally tear the spellbook to pieces."); 413. } 414. else 415. You("find yourself reading the first line over and over again."); 416. nomul(delay); 417. delay = 0; 418. return(1); 419. } 420. 421. You("begin to %s the runes.", 422. spellbook->otyp == SPE_BOOK_OF_THE_DEAD ? "recite" : 423. "memorize"); 424. } 425. 426. book = spellbook; 427. set_occupation(learn, "studying", 0); 428. return(1); 429. } 430. 431. /* 432. * Return TRUE if a spell was picked, with the spell index in the return 433. * parameter. Otherwise return FALSE. 434. */ 435. static boolean 436. getspell(spell_no) 437. int *spell_no; 438. { 439. int nspells, idx; 440. char ilet, lets[BUFSZ], qbuf[QBUFSZ]; 441. 442. if (spellid(0) == NO_SPELL) { 443. You("don't know any spells right now."); 444. return FALSE; 445. } 446. if (flags.menu_style == MENU_TRADITIONAL) { 447. /* we know there is at least 1 known spell */ 448. for (nspells = 1; nspells < MAXSPELL 449. && spellid(nspells) != NO_SPELL; nspells++) 450. continue; 451. 452. if (nspells == 1) Strcpy(lets, "a"); 453. else if (nspells < 27) Sprintf(lets, "a-%c", 'a' + nspells - 1); 454. else if (nspells == 27) Sprintf(lets, "a-z A"); 455. else Sprintf(lets, "a-z A-%c", 'A' + nspells - 27); 456. 457. for(;;) { 458. Sprintf(qbuf, "Cast which spell? [%s ?]", lets); 459. if ((ilet = yn_function(qbuf, (char *)0, '\0')) == '?') 460. break; 461. 462. if (index(quitchars, ilet)) 463. return FALSE; 464. 465. if (letter(ilet) && ilet != '@') { 466. /* in a-zA-Z, convert back to an index */ 467. if (lowc(ilet) == ilet) /* lower case */ 468. idx = ilet - 'a'; 469. else 470. idx = ilet - 'A' + 26; 471. 472. if (idx < nspells) { 473. *spell_no = idx; 474. return TRUE; 475. } 476. } 477. You("don't know that spell."); 478. } 479. } 480. return dospellmenu(PICK_ONE, spell_no); 481. } 482. 483. int 484. docast() 485. { 486. int spell_no; 487. 488. if (getspell(&spell_no)) 489. return spelleffects(spell_no, FALSE); 490. return 0; 491. } 492. 493. int 494. spelleffects(spell, atme) 495. int spell; 496. boolean atme; 497. { 498. int energy, damage, chance; 499. boolean confused = (Confusion != 0); 500. struct obj *pseudo; 501. 502. /* note that trying to cast it decrements the # of uses, */ 503. /* even if the mage does not have enough food/energy to use */ 504. /* the spell */ 505. switch (spelluses(spell)) { 506. case 0: 507. pline ("Curdled magical energy twists through you..."); 508. pline ("...you have overloaded and burned out this spell."); 509. make_confused((long)spellev(spell) * 3, FALSE); 510. return(0); 511. case 1: 512. case 2: 513. case 3: 514. Your("nerves tingle warningly."); 515. break; 516. case 4: 517. case 5: 518. case 6: 519. pline ("This spell is starting to be over-used."); 520. break; 521. default: 522. break; 523. } 524. decrnuses(spell); 525. energy = (spellev(spell) * 5); /* 5 <= energy <= 35 */ 526. 527. if (u.uhunger <= 10 && spellid(spell) != SPE_DETECT_FOOD) { 528. You("are too hungry to cast that spell."); 529. return(0); 530. } else if (ACURR(A_STR) < 4) { 531. You("lack the strength to cast spells."); 532. return(0); 533. } else if(check_capacity( 534. "Your concentration falters while carrying so much stuff.")) { 535. return (1); 536. } else if (!freehand()) { 537. Your("arms are not free to cast!"); 538. return (0); 539. } 540. 541. 542. if (u.uhave.amulet) { 543. You_feel("the amulet draining your energy away."); 544. energy += rnd(2*energy); 545. } 546. if(energy > u.uen) { 547. You("don't have enough energy to cast that spell."); 548. return(0); 549. } else { 550. if (spellid(spell) != SPE_DETECT_FOOD) { 551. int hungr = energy * 2; 552. 553. /* don't put player (quite) into fainting from 554. * casting a spell, particularly since they might 555. * not even be hungry at the beginning; however, 556. * this is low enough that they must eat before 557. * casting anything else except detect food 558. */ 559. if (hungr > u.uhunger-3) 560. hungr = u.uhunger-3; 561. morehungry(hungr); 562. } 563. } 564. 565. /* u.uen _will_ reduce once here reached */ 566. 567. flags.botl = 1; 568. 569. chance = percent_success(spell); 570. 571. if (confused || (rnd(100) > chance)) { 572. You("fail to cast the spell correctly."); 573. u.uen -= energy / 2; 574. return(1); 575. } 576. 577. u.uen -= energy; 578. exercise(A_WIS, TRUE); 579. /* pseudo is a temporary "false" object containing the spell stats. */ 580. pseudo = mksobj(spellid(spell), FALSE, FALSE); 581. pseudo->blessed = pseudo->cursed = 0; 582. pseudo->quan = 20L; /* do not let useup get it */ 583. switch(pseudo->otyp) { 584. 585. /* These spells are all duplicates of wand effects */ 586. case SPE_FORCE_BOLT: 587. case SPE_SLEEP: 588. case SPE_MAGIC_MISSILE: 589. case SPE_KNOCK: 590. case SPE_SLOW_MONSTER: 591. case SPE_WIZARD_LOCK: 592. case SPE_FIREBALL: 593. case SPE_CONE_OF_COLD: 594. case SPE_DIG: 595. case SPE_TURN_UNDEAD: 596. case SPE_POLYMORPH: 597. case SPE_TELEPORT_AWAY: 598. case SPE_CANCELLATION: 599. case SPE_FINGER_OF_DEATH: 600. case SPE_LIGHT: 601. case SPE_DETECT_UNSEEN: 602. case SPE_HEALING: 603. case SPE_EXTRA_HEALING: 604. if (!(objects[pseudo->otyp].oc_dir == NODIR)) { 605. if (atme) u.dx = u.dy = u.dz = 0; 606. else (void) getdir((char *)0); 607. if(!u.dx && !u.dy && !u.dz) { 608. if ((damage = zapyourself(pseudo, TRUE)) != 0) 609. losehp(damage, 610. self_pronoun("zapped %sself with a spell", 611. "him"), 612. NO_KILLER_PREFIX); 613. } else weffects(pseudo); 614. } else weffects(pseudo); 615. break; 616. /* These are all duplicates of scroll effects */ 617. case SPE_CONFUSE_MONSTER: 618. case SPE_DETECT_FOOD: 619. case SPE_CAUSE_FEAR: 620. case SPE_CHARM_MONSTER: 621. case SPE_REMOVE_CURSE: 622. case SPE_MAGIC_MAPPING: 623. case SPE_CREATE_MONSTER: 624. case SPE_IDENTIFY: 625. (void) seffects(pseudo); 626. break; 627. case SPE_HASTE_SELF: 628. case SPE_DETECT_TREASURE: 629. case SPE_DETECT_MONSTERS: 630. case SPE_LEVITATION: 631. case SPE_RESTORE_ABILITY: 632. case SPE_INVISIBILITY: 633. (void) peffects(pseudo); 634. break; 635. case SPE_CURE_BLINDNESS: 636. healup(0, 0, FALSE, TRUE); 637. break; 638. case SPE_CURE_SICKNESS: 639. if (Sick) You("are no longer ill."); 640. healup(0, 0, TRUE, FALSE); 641. break; 642. case SPE_CREATE_FAMILIAR: 643. make_familiar((struct obj *)0, u.ux, u.uy); 644. break; 645. case SPE_CLAIRVOYANCE: 646. if (!(HClairvoyant & I_BLOCKED)) 647. do_vicinity_map(); 648. /* at present, only one thing blocks clairvoyance */ 649. else if (uarmh && uarmh->otyp == CORNUTHAUM) 650. You("sense a pointy hat on top of your %s.", 651. body_part(HEAD)); 652. break; 653. default: 654. impossible("Unknown spell %d attempted.", spell); 655. obfree(pseudo, (struct obj *)0); 656. return(0); 657. } 658. obfree(pseudo, (struct obj *)0); /* now, get rid of it */ 659. return(1); 660. } 661. 662. void 663. losespells() 664. { 665. boolean confused = (Confusion != 0); 666. int n, nzap, i; 667. 668. book = 0; 669. for (n = 0; n < MAXSPELL && spellid(n) != NO_SPELL; n++) 670. continue; 671. if (n) { 672. nzap = rnd(n) + confused ? 1 : 0; 673. if (nzap > n) nzap = n; 674. for (i = n - nzap; i < n; i++) { 675. spellid(i) = NO_SPELL; 676. exercise(A_WIS, FALSE); /* ouch! */ 677. } 678. } 679. } 680. 681. int 682. dovspell() 683. { 684. int dummy; 685. 686. if (spellid(0) == NO_SPELL) 687. You("don't know any spells right now."); 688. else 689. (void) dospellmenu(PICK_NONE, &dummy); 690. return 0; 691. } 692. 693. static boolean 694. dospellmenu(how, spell_no) 695. int how; 696. int *spell_no; 697. { 698. winid tmpwin; 699. int i, n; 700. char buf[BUFSZ]; 701. menu_item *selected; 702. anything any; 703. 704. tmpwin = create_nhwindow(NHW_MENU); 705. start_menu(tmpwin); 706. any.a_void = 0; /* zero out all bits */ 707. 708. /* 709. * The correct spacing of the columns depends on the 710. * following that (1) the font is monospaced and (2) 711. * that selection letters are pre-pended to the given 712. * string and are of the form "a - ". 713. * 714. * To do it right would require that we implement columns 715. * in the window-ports (say via a tab character). 716. */ 717. Sprintf(buf, "%-20s Level Fail", "Name"); 718. add_menu(tmpwin, NO_GLYPH, &any, 0, 0, buf, MENU_UNSELECTED); 719. for (i = 0; i < MAXSPELL && spellid(i) != NO_SPELL; i++) { 720. Sprintf(buf, "%-20s %2d%s %3d%%", 721. spellname(i), spellev(i), 722. spelluses(i) ? " " : "*", 100 - percent_success(i)); 723. 724. any.a_int = i+1; /* must be non-zero */ 725. add_menu(tmpwin, NO_GLYPH, &any, 726. spellet(i), 0,buf, MENU_UNSELECTED); 727. } 728. end_menu(tmpwin, how == PICK_ONE ? "Choose a spell" : 729. "Currently known spells"); 730. 731. n = select_menu(tmpwin, how, &selected); 732. destroy_nhwindow(tmpwin); 733. if (n > 0) { 734. *spell_no = selected[0].item.a_int - 1; 735. free((genericptr_t)selected); 736. return TRUE; 737. } 738. return FALSE; 739. } 740. 741. static int 742. percent_success(spell) 743. int spell; 744. { 745. /* Intrinsic and learned ability are combined to calculate 746. * the probability of player's success at cast a given spell. 747. */ 748. 749. int i, chance, splcaster, special, statused; 750. int difficulty; 751. 752. /* Calculate intrinsic ability (splcaster) */ 753. 754. for (i = 0; cl_sptmp[i].class; i++) 755. if (cl_sptmp[i].class == pl_character[0]) break; 756. 757. splcaster = cl_sptmp[i].splcaster; 758. special = cl_sptmp[i].special; 759. 760. if (uarm && is_metallic(uarm)) splcaster += cl_sptmp[i].uarmbon; 761. if (uarms) splcaster += cl_sptmp[i].uarmsbon; 762. 763. if (uarmh && is_metallic(uarmh) && uarmh->otyp != HELM_OF_BRILLIANCE) 764. splcaster += uarmhbon; 765. if (uarmg && is_metallic(uarmg)) splcaster += uarmgbon; 766. if (uarmf && is_metallic(uarmf)) splcaster += uarmfbon; 767. 768. if (spellid(spell) == cl_sptmp[i].specspel) 769. splcaster += cl_sptmp[i].specbon; 770. 771. statused = ACURR(cl_sptmp[i].statused); 772. 773. /* `healing spell' bonus */ 774. if (spellid(spell) == SPE_HEALING || 775. spellid(spell) == SPE_EXTRA_HEALING || 776. spellid(spell) == SPE_CURE_BLINDNESS || 777. spellid(spell) == SPE_CURE_SICKNESS || 778. spellid(spell) == SPE_RESTORE_ABILITY || 779. spellid(spell) == SPE_REMOVE_CURSE) splcaster += special; 780. 781. if (splcaster > 20) splcaster = 20; 782. 783. /* Calculate learned ability */ 784. 785. /* Players basic likelihood of being able to cast any spell 786. * is based of their `magic' statistic. (Int or Wis) 787. */ 788. chance = 11 * statused / 2; 789. 790. /* High level spells are harder. Easier for higher level casters */ 791. difficulty = (spellev(spell) - 1) * 4 - (u.ulevel - 1); 792. 793. if (difficulty > 0) { 794. /* Player is too low level. Exponential chance reduction */ 795. chance -= 7 * difficulty * difficulty; 796. } else { 797. /* Player is above level. Learning continues, but the 798. * law of diminishing returns sets in quickly for 799. * low-level spells. That is, a player quickly gains 800. * no advantage for raising level. 801. */ 802. int learning = 15 * -difficulty / spellev(spell); 803. chance += learning > 20 ? 20 : learning; 804. } 805. 806. /* Clamp the chance: >18 stat and advanced learning only help 807. * to a limit, while chances below "hopeless" only raise the 808. * specter of overflowing 16-bit ints (and permit wearing a 809. * shield to raise the chances :-). 810. */ 811. if (chance < 0) chance = 0; 812. if (chance > 120) chance = 120; 813. 814. /* Wearing anything but a light shield makes it very awkward 815. * to cast a spell. The penalty is not quite so bad for the 816. * player's class-specific spell. 817. */ 818. if (uarms && weight(uarms) > (int) objects[SMALL_SHIELD].oc_weight) { 819. if (spellid(spell) == cl_sptmp[i].specspel) { 820. chance /= 2; 821. } else { 822. chance /= 4; 823. } 824. } 825. 826. /* Finally, chance (based on player intell/wisdom and level) is 827. * combined with ability (based on player intrinsics and 828. * encumberances). No matter how intelligent/wise and advanced 829. * a player is, intrinsics and encumberance can prevent casting; 830. * and no matter how able, learning is always required. 831. */ 832. chance = chance * (20-splcaster) / 15 - splcaster; 833. 834. /* Clamp to percentile */ 835. if (chance > 100) chance = 100; 836. if (chance < 0) chance = 0; 837. 838. return chance; 839. } 840. 841. /*spell.c*/
Alternative Linked Data Views: ODE     Raw Data in: CXML | CSV | RDF ( N-Triples N3/Turtle JSON XML ) | OData ( Atom JSON ) | Microdata ( JSON HTML) | JSON-LD    About   
This material is Open Knowledge   W3C Semantic Web Technology [RDF Data] Valid XHTML + RDFa
OpenLink Virtuoso version 07.20.3217, on Linux (x86_64-pc-linux-gnu), Standard Edition
Data on this page belongs to its respective rights holders.
Virtuoso Faceted Browser Copyright © 2009-2012 OpenLink Software