About: Source:SLASH'EM 0.0.7E7F2/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 SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/spell.c#line123]], for example. The latest source code for vanilla NetHack is at Source code.

AttributesValues
rdfs:label
  • Source:SLASH'EM 0.0.7E7F2/spell.c
rdfs:comment
  • Below is the full text to spell.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/spell.c#line123]], for example. The latest source code for vanilla NetHack is at Source code.
dcterms:subject
dbkwik:nethack/pro...iPageUsesTemplate
abstract
  • Below is the full text to spell.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/spell.c#line123]], for example. The latest source code for vanilla NetHack is at Source code. 1. /* SCCS Id: @(#)spell.c 3.4 2003/01/17 */ 2. /* Copyright (c) M. Stephenson 1988 */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. #include "hack.h" 6. #include "edog.h" 7. 8. /* Are now ints */ 9. static NEARDATA int delay; /* moves left for this spell */ 10. static NEARDATA int end_delay; /* when to stop studying */ 11. static NEARDATA struct obj *book; /* last/current book being xscribed */ 12. 13. /* spellmenu arguments; 0 thru n-1 used as spl_book[] index when swapping */ 14. #define SPELLMENU_CAST (-2) 15. #define SPELLMENU_VIEW (-1) 16. 17. #define KEEN 10000 /* memory increase reading the book */ 18. #define CAST_BOOST 500 /* memory increase for successful casting */ 19. #define MAX_KNOW 70000 /* Absolute Max timeout */ 20. #define MAX_CAN_STUDY 60000 /* Can study while timeout is less than */ 21. 22. #define MAX_STUDY_TIME 300 /* Max time for one study session */ 23. #define MAX_SPELL_STUDY 30 /* Uses before spellbook crumbles */ 24. 25. #define spellknow(spell) spl_book[spell].sp_know 26. 27. #define incrnknow(spell) spl_book[spell].sp_know = ((spl_book[spell].sp_know < 1) ? KEEN \ 28. : ((spl_book[spell].sp_know + KEEN) > MAX_KNOW) ? MAX_KNOW \ 29. : spl_book[spell].sp_know + KEEN) 30. #define boostknow(spell,boost) spl_book[spell].sp_know = ((spl_book[spell].sp_know + boost > MAX_KNOW) ? MAX_KNOW \ 31. : spl_book[spell].sp_know + boost) 32. 33. #define spellev(spell) spl_book[spell].sp_lev 34. #define spellid(spell) spl_book[spell].sp_id 35. #define spellname(spell) OBJ_NAME(objects[spellid(spell)]) 36. #define spellet(spell) \ 37. ((char)((spell < 26) ? ('a' + spell) : \ 38. (spell < 52) ? ('A' + spell - 26) : \ 39. (spell < 62) ? ('0' + spell - 52) : 0 )) 40. 41. STATIC_DCL int FDECL(spell_let_to_idx, (CHAR_P)); 42. STATIC_DCL boolean FDECL(cursed_book, (struct obj *bp)); 43. STATIC_DCL boolean FDECL(confused_book, (struct obj *)); 44. STATIC_DCL void FDECL(deadbook, (struct obj *)); 45. STATIC_PTR int NDECL(learn); 46. STATIC_DCL void NDECL(do_reset_learn); 47. STATIC_DCL boolean FDECL(getspell, (int *)); 48. STATIC_DCL boolean FDECL(dospellmenu, (const char *,int,int *)); 49. STATIC_DCL int FDECL(percent_success, (int)); 50. STATIC_DCL void NDECL(cast_protection); 51. STATIC_DCL void FDECL(spell_backfire, (int)); 52. STATIC_DCL const char *FDECL(spelltypemnemonic, (int)); 53. STATIC_DCL int FDECL(isqrt, (int)); 54. 55. /* The roles[] table lists the role-specific values for tuning 56. * percent_success(). 57. * 58. * Reasoning: 59. * splcaster, special: 60. * Arc are aware of magic through historical research 61. * Bar abhor magic (Conan finds it "interferes with his animal instincts") 62. * Cav are ignorant to magic 63. * Hea are very aware of healing magic through medical research 64. * Kni are moderately aware of healing from Paladin training 65. * Mon use magic to attack and defend in lieu of weapons and armor 66. * Pri are very aware of healing magic through theological research 67. * Ran avoid magic, preferring to fight unseen and unheard 68. * Rog are moderately aware of magic through trickery 69. * Sam have limited magical awareness, prefering meditation to conjuring 70. * Tou are aware of magic from all the great films they have seen 71. * Val have limited magical awareness, prefering fighting 72. * Wiz are trained mages 73. * 74. * The arms penalty is lessened for trained fighters Bar, Kni, Ran, 75. * Sam, Val - 76. * the penalty is its metal interference, not encumbrance. 77. * The `spelspec' is a single spell which is fundamentally easier 78. * for that role to cast. 79. * 80. * spelspec, spelsbon: 81. * Arc map masters (SPE_MAGIC_MAPPING) 82. * Bar fugue/berserker (SPE_HASTE_SELF) 83. * Cav born to dig (SPE_DIG) 84. * Hea to heal (SPE_CURE_SICKNESS) 85. * Kni to turn back evil (SPE_TURN_UNDEAD) 86. * Mon to preserve their abilities (SPE_RESTORE_ABILITY) 87. * Pri to bless (SPE_REMOVE_CURSE) 88. * Ran to hide (SPE_INVISIBILITY) 89. * Rog to find loot (SPE_DETECT_TREASURE) 90. * Sam to be At One (SPE_CLAIRVOYANCE) 91. * Tou to smile (SPE_CHARM_MONSTER) 92. * Val control lightning (SPE_LIGHTNING) 93. * Wiz all really, but SPE_MAGIC_MISSILE is their party trick 94. * Yeo guard doors (SPE_KNOCK) 95. * 96. * See percent_success() below for more comments. 97. * 98. * uarmbon, uarmsbon, uarmhbon, uarmgbon, uarmfbon: 99. * Fighters find body armour & shield a little less limiting. 100. * Headgear, Gauntlets and Footwear are not role-specific (but 101. * still have an effect, except helm of brilliance, which is designed 102. * to permit magic-use). 103. */ 104. 105. #define uarmhbon 4 /* Metal helmets interfere with the mind */ 106. #define uarmgbon 6 /* Casting channels through the hands */ 107. #define uarmfbon 2 /* All metal interferes to some degree */ 108. 109. /* since the spellbook itself doesn't blow up, don't say just "explodes" */ 110. static const char explodes[] = "radiates explosive energy"; 111. 112. /* convert an alnum into a number in the range 0..61, or -1 if not an alnum */ 113. STATIC_OVL int 114. spell_let_to_idx(ilet) 115. char ilet; 116. { 117. int indx; 118. 119. indx = ilet - 'a'; 120. if (indx >= 0 && indx < 26) return indx; 121. indx = ilet - 'A'; 122. if (indx >= 0 && indx < 26) return indx + 26; 123. indx = ilet - '0'; 124. if (indx >= 0 && indx < 10) return indx + 52; 125. return -1; 126. } 127. 128. /* TRUE: book should be destroyed by caller */ 129. STATIC_OVL boolean 130. cursed_book(bp) 131. struct obj *bp; 132. { 133. int lev = objects[bp->otyp].oc_level; 134. 135. switch(rn2(lev)) { 136. case 0: 137. You_feel("a wrenching sensation."); 138. tele(); /* teleport him */ 139. break; 140. case 1: 141. You_feel("threatened."); 142. aggravate(); 143. break; 144. case 2: 145. /* [Tom] lowered this (used to be 100,250) */ 146. make_blinded(Blinded + rn1(50,25),TRUE); 147. break; 148. case 3: 149. take_gold(); 150. break; 151. case 4: 152. pline("These runes were just too much to comprehend."); 153. make_confused(HConfusion + rn1(7,16),FALSE); 154. break; 155. case 5: 156. pline_The("book was coated with contact poison!"); 157. if (uarmg) { 158. if (uarmg->oerodeproof || !is_corrodeable(uarmg)) { 159. Your("gloves seem unaffected."); 160. } else if (uarmg->oeroded2 < MAX_ERODE) { 161. if (uarmg->greased) { 162. grease_protect(uarmg, "gloves", &youmonst); 163. } else { 164. Your("gloves corrode%s!", 165. uarmg->oeroded2+1 == MAX_ERODE ? 166. " completely" : uarmg->oeroded2 ? 167. " further" : ""); 168. uarmg->oeroded2++; 169. } 170. } else 171. Your("gloves %s completely corroded.", 172. Blind ? "feel" : "look"); 173. break; 174. } 175. /* temp disable in_use; death should not destroy the book */ 176. bp->in_use = FALSE; 177. losestr(Poison_resistance ? rn1(2,1) : rn1(4,3)); 178. losehp(rnd(Poison_resistance ? 6 : 10), 179. "contact-poisoned spellbook", KILLED_BY_AN); 180. bp->in_use = TRUE; 181. break; 182. case 6: 183. if(Antimagic) { 184. shieldeff(u.ux, u.uy); 185. pline_The("book %s, but you are unharmed!", explodes); 186. } else { 187. pline("As you read the book, it %s in your %s!", 188. explodes, body_part(FACE)); 189. losehp(2*rnd(10)+5, "exploding rune", KILLED_BY_AN); 190. } 191. return TRUE; 192. default: 193. rndcurse(); 194. break; 195. } 196. return FALSE; 197. } 198. 199. /* study while confused: returns TRUE if the book is destroyed */ 200. STATIC_OVL boolean 201. confused_book(spellbook) 202. struct obj *spellbook; 203. { 204. boolean gone = FALSE; 205. 206. if (!rn2(3) && spellbook->otyp != SPE_BOOK_OF_THE_DEAD) { 207. spellbook->in_use = TRUE; /* in case called from learn */ 208. pline( 209. "Being confused you have difficulties in controlling your actions."); 210. display_nhwindow(WIN_MESSAGE, FALSE); 211. You("accidentally tear the spellbook to pieces."); 212. if (!objects[spellbook->otyp].oc_name_known && 213. !objects[spellbook->otyp].oc_uname) 214. docall(spellbook); 215. if (carried(spellbook)) useup(spellbook); 216. else useupf(spellbook, 1L); 217. gone = TRUE; 218. } else { 219. You("find yourself reading the %s line over and over again.", 220. spellbook == book ? "next" : "first"); 221. } 222. return gone; 223. } 224. 225. /* special effects for The Book of the Dead */ 226. STATIC_OVL void 227. deadbook(book2) 228. struct obj *book2; 229. { 230. struct monst *mtmp, *mtmp2; 231. coord mm; 232. 233. You("turn the pages of the Book of the Dead..."); 234. makeknown(SPE_BOOK_OF_THE_DEAD); 235. /* KMH -- Need ->known to avoid "_a_ Book of the Dead" */ 236. book2->known = 1; 237. if(invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) { 238. register struct obj *otmp; 239. register boolean arti1_primed = FALSE, arti2_primed = FALSE, 240. arti_cursed = FALSE; 241. 242. if(book2->cursed) { 243. pline_The("runes appear scrambled. You can't read them!"); 244. return; 245. } 246. 247. if(!u.uhave.bell || !u.uhave.menorah) { 248. pline("A chill runs down your %s.", body_part(SPINE)); 249. if(!u.uhave.bell) You_hear("a faint chime..."); 250. if(!u.uhave.menorah) pline("Vlad's doppelganger is amused."); 251. return; 252. } 253. 254. for(otmp = invent; otmp; otmp = otmp->nobj) { 255. if(otmp->otyp == CANDELABRUM_OF_INVOCATION && 256. otmp->spe == 7 && otmp->lamplit) { 257. if(!otmp->cursed) arti1_primed = TRUE; 258. else arti_cursed = TRUE; 259. } 260. if(otmp->otyp == BELL_OF_OPENING && 261. (moves - otmp->age) < 5L) { /* you rang it recently */ 262. if(!otmp->cursed) arti2_primed = TRUE; 263. else arti_cursed = TRUE; 264. } 265. } 266. 267. if(arti_cursed) { 268. pline_The("invocation fails!"); 269. pline("At least one of your artifacts is cursed..."); 270. } else if(arti1_primed && arti2_primed) { 271. unsigned soon = (unsigned) d(2,6); /* time til next intervene() */ 272. 273. /* successful invocation */ 274. mkinvokearea(); 275. u.uevent.invoked = 1; 276. /* in case you haven't killed the Wizard yet, behave as if 277. you just did */ 278. u.uevent.udemigod = 1; /* wizdead() */ 279. if (!u.udg_cnt || u.udg_cnt > soon) u.udg_cnt = soon; 280. } else { /* at least one artifact not prepared properly */ 281. You("have a feeling that %s is amiss...", something); 282. goto raise_dead; 283. } 284. return; 285. } 286. 287. /* when not an invocation situation */ 288. if (book2->cursed) { 289. raise_dead: 290. 291. You("raised the dead!"); 292. /* first maybe place a dangerous adversary */ 293. if (!rn2(3) && ((mtmp = makemon(&mons[PM_MASTER_LICH], 294. u.ux, u.uy, NO_MINVENT)) != 0 || 295. (mtmp = makemon(&mons[PM_NALFESHNEE], 296. u.ux, u.uy, NO_MINVENT)) != 0)) { 297. mtmp->mpeaceful = 0; 298. set_malign(mtmp); 299. } 300. /* next handle the affect on things you're carrying */ 301. (void) unturn_dead(&youmonst); 302. /* last place some monsters around you */ 303. mm.x = u.ux; 304. mm.y = u.uy; 305. mkundead(&mm, TRUE, NO_MINVENT); 306. } else if(book2->blessed) { 307. for(mtmp = fmon; mtmp; mtmp = mtmp2) { 308. mtmp2 = mtmp->nmon; /* tamedog() changes chain */ 309. if (DEADMONSTER(mtmp)) continue; 310. 311. if (is_undead(mtmp->data) && cansee(mtmp->mx, mtmp->my)) { 312. mtmp->mpeaceful = TRUE; 313. if(sgn(mtmp->data->maligntyp) == sgn(u.ualign.type) 314. && distu(mtmp->mx, mtmp->my) < 4) 315. if (mtmp->mtame) { 316. if (mtmp->mtame < 20) 317. mtmp->mtame++; 318. } else 319. (void) tamedog(mtmp, (struct obj *)0); 320. else monflee(mtmp, 0, FALSE, TRUE); 321. } 322. } 323. } else { 324. switch(rn2(3)) { 325. case 0: 326. Your("ancestors are annoyed with you!"); 327. break; 328. case 1: 329. pline_The("headstones in the cemetery begin to move!"); 330. break; 331. default: 332. pline("Oh my! Your name appears in the book!"); 333. } 334. } 335. return; 336. } 337. 338. STATIC_PTR int 339. learn() 340. { 341. int i; 342. short booktype; 343. char splname[BUFSZ]; 344. boolean costly = TRUE; 345. 346. if (!book || !(carried(book) || 347. (book->where == OBJ_FLOOR && 348. book->ox == u.ux && book->oy == u.uy))) { 349. /* maybe it was stolen or polymorphed? */ 350. do_reset_learn(); 351. return(0); 352. } 353. /* JDS: lenses give 50% faster reading; 33% smaller read time */ 354. if (delay < end_delay && ublindf && ublindf->otyp == LENSES && rn2(2)) 355. delay++; 356. if (Confusion) { /* became confused while learning */ 357. (void) confused_book(book); 358. book = 0; /* no longer studying */ 359. nomul(delay - end_delay); /* remaining delay is uninterrupted */ 360. delay = end_delay; 361. return(0); 362. } 363. if (delay < end_delay) { /* not if (delay++), so at end delay == 0 */ 364. delay++; 365. return(1); /* still busy */ 366. } 367. exercise(A_WIS, TRUE); /* you're studying. */ 368. booktype = book->otyp; 369. if(booktype == SPE_BOOK_OF_THE_DEAD) { 370. deadbook(book); 371. return(0); 372. } 373. 374. Sprintf(splname, objects[booktype].oc_name_known ? 375. "\"%s\"" : "the \"%s\" spell", 376. OBJ_NAME(objects[booktype])); 377. for (i = 0; i < MAXSPELL; i++) { 378. if (spellid(i) == booktype) { 379. if (book->spestudied > MAX_SPELL_STUDY) { 380. pline("This spellbook is too faint to be read anymore."); 381. book->otyp = booktype = SPE_BLANK_PAPER; 382. } else if (spellknow(i) <= MAX_CAN_STUDY) { 383. Your("knowledge of that spell is keener."); 384. incrnknow(i); 385. book->spestudied++; 386. if (end_delay) { 387. boostknow(i, 388. end_delay * (book->spe > 0 ? 20 : 10)); 389. use_skill(spell_skilltype(book->otyp), 390. end_delay / (book->spe > 0 ? 10 : 20)); 391. } 392. exercise(A_WIS, TRUE); /* extra study */ 393. } else { /* MAX_CAN_STUDY < spellknow(i) <= MAX_SPELL_STUDY */ 394. You("know %s quite well already.", splname); 395. costly = FALSE; 396. } 397. /* make book become known even when spell is already 398. known, in case amnesia made you forget the book */ 399. makeknown((int)booktype); 400. break; 401. } else if (spellid(i) == NO_SPELL) { 402. spl_book[i].sp_id = booktype; 403. spl_book[i].sp_lev = objects[booktype].oc_level; 404. incrnknow(i); 405. book->spestudied++; 406. You("have keen knowledge of the spell."); 407. You(i > 0 ? "add %s to your repertoire." : "learn %s.", 408. splname); 409. makeknown((int)booktype); 410. break; 411. } 412. } 413. if (i == MAXSPELL) impossible("Too many spells memorized!"); 414. 415. if (book->cursed) { /* maybe a demon cursed it */ 416. if (cursed_book(book)) { 417. if (carried(book)) useup(book); 418. else useupf(book, 1L); 419. book = 0; 420. return 0; 421. } 422. } 423. if (costly) check_unpaid(book); 424. book = 0; 425. return(0); 426. } 427. 428. int 429. study_book(spellbook) 430. register struct obj *spellbook; 431. { 432. register int booktype = spellbook->otyp; 433. register boolean confused = (Confusion != 0); 434. boolean too_hard = FALSE; 435. 436. if (delay && !confused && spellbook == book && 437. /* handle the sequence: start reading, get interrupted, 438. have book become erased somehow, resume reading it */ 439. booktype != SPE_BLANK_PAPER) { 440. You("continue your efforts to memorize the spell."); 441. } else { 442. /* KMH -- Simplified this code */ 443. if (booktype == SPE_BLANK_PAPER) { 444. pline("This spellbook is all blank."); 445. makeknown(booktype); 446. return(1); 447. } 448. if (spellbook->spe && confused) { 449. check_unpaid_usage(spellbook, TRUE); 450. consume_obj_charge(spellbook, FALSE); 451. pline_The("words on the page seem to glow faintly purple."); 452. You_cant("quite make them out."); 453. return 1; 454. } 455. 456. switch (objects[booktype].oc_level) { 457. case 1: 458. case 2: 459. delay = -objects[booktype].oc_delay; 460. break; 461. case 3: 462. case 4: 463. delay = -(objects[booktype].oc_level - 1) * 464. objects[booktype].oc_delay; 465. break; 466. case 5: 467. case 6: 468. delay = -objects[booktype].oc_level * 469. objects[booktype].oc_delay; 470. break; 471. case 7: 472. delay = -8 * objects[booktype].oc_delay; 473. break; 474. default: 475. impossible("Unknown spellbook level %d, book %d;", 476. objects[booktype].oc_level, booktype); 477. return 0; 478. } 479. 480. /* Books are often wiser than their readers (Rus.) */ 481. spellbook->in_use = TRUE; 482. if (!spellbook->blessed && 483. spellbook->otyp != SPE_BOOK_OF_THE_DEAD) { 484. if (spellbook->cursed) { 485. too_hard = TRUE; 486. } else { 487. /* uncursed - chance to fail */ 488. int read_ability = ACURR(A_INT) + 4 + u.ulevel/2 489. - 2*objects[booktype].oc_level 490. + ((ublindf && ublindf->otyp == LENSES) ? 2 : 0); 491. /* only wizards know if a spell is too difficult */ 492. if (Role_if(PM_WIZARD) && read_ability < 20 && 493. !confused && !spellbook->spe) { 494. char qbuf[QBUFSZ]; 495. Sprintf(qbuf, 496. "This spellbook is %sdifficult to comprehend. Continue?", 497. (read_ability < 12 ? "very " : "")); 498. if (yn(qbuf) != 'y') { 499. spellbook->in_use = FALSE; 500. return(1); 501. } 502. } 503. /* its up to random luck now */ 504. if (rnd(20) > read_ability) { 505. too_hard = TRUE; 506. } 507. } 508. } 509. 510. if (too_hard && (spellbook->cursed || !spellbook->spe)) { 511. boolean gone = cursed_book(spellbook); 512. 513. nomul(delay); /* study time */ 514. delay = 0; 515. if(gone || !rn2(3)) { 516. if (!gone) pline_The("spellbook crumbles to dust!"); 517. if (!objects[spellbook->otyp].oc_name_known && 518. !objects[spellbook->otyp].oc_uname) 519. docall(spellbook); 520. if (carried(spellbook)) useup(spellbook); 521. else useupf(spellbook, 1L); 522. } else 523. spellbook->in_use = FALSE; 524. return(1); 525. } else if (confused) { 526. if (!confused_book(spellbook)) { 527. spellbook->in_use = FALSE; 528. } 529. nomul(delay); 530. delay = 0; 531. return(1); 532. } 533. spellbook->in_use = FALSE; 534. 535. /* The glowing words make studying easier */ 536. if (spellbook->otyp != SPE_BOOK_OF_THE_DEAD) { 537. delay *= 2; 538. if (spellbook->spe) { 539. check_unpaid_usage(spellbook, TRUE); 540. consume_obj_charge(spellbook, FALSE); 541. pline_The("words on the page seem to glow faintly."); 542. if (!too_hard) 543. delay /= 3; 544. } 545. } 546. end_delay = 0; /* Changed if multi != 0 */ 547. 548. #ifdef DEBUG 549. pline("Delay: %i", delay); 550. #endif 551. if (multi) { 552. /* Count == practice reading :) */ 553. char qbuf[QBUFSZ]; 554. 555. if (multi + 1 > MAX_STUDY_TIME) multi = MAX_STUDY_TIME - 1; 556. Sprintf(qbuf, "Study for at least %i turns?", (multi+1)); 557. if (ynq(qbuf) != 'y') { 558. multi = 0; 559. return(1); 560. } 561. if ((--multi) > (-delay)) end_delay = multi + delay; 562. multi = 0; 563. #ifdef DEBUG 564. pline("end_delay: %i", end_delay); 565. #endif 566. } 567. 568. You("begin to %s the runes.", 569. spellbook->otyp == SPE_BOOK_OF_THE_DEAD ? "recite" : 570. "memorize"); 571. } 572. 573. book = spellbook; 574. set_occupation(learn, "studying", 0); 575. return(1); 576. } 577. 578. /* a spellbook has been destroyed or the character has changed levels; 579. the stored address for the current book is no longer valid */ 580. void 581. book_disappears(obj) 582. struct obj *obj; 583. { 584. if (obj == book) book = (struct obj *)0; 585. } 586. 587. /* renaming an object usually results in it having a different address; 588. so the sequence start reading, get interrupted, name the book, resume 589. reading would read the "new" book from scratch */ 590. void 591. book_substitution(old_obj, new_obj) 592. struct obj *old_obj, *new_obj; 593. { 594. if (old_obj == book) book = new_obj; 595. } 596. 597. static void 598. do_reset_learn() 599. { 600. stop_occupation(); 601. } 602. 603. /* called from moveloop() */ 604. void 605. age_spells() 606. { 607. int i; 608. /* 609. * The time relative to the hero (a pass through move 610. * loop) causes all spell knowledge to be decremented. 611. * The hero's speed, rest status, conscious status etc. 612. * does not alter the loss of memory. 613. */ 614. for (i = 0; i < MAXSPELL && spellid(i) != NO_SPELL; i++) 615. if (spellknow(i)) 616. decrnknow(i); 617. return; 618. } 619. 620. /* 621. * Return TRUE if a spell was picked, with the spell index in the return 622. * parameter. Otherwise return FALSE. 623. */ 624. STATIC_OVL boolean 625. getspell(spell_no) 626. int *spell_no; 627. { 628. int nspells, idx; 629. char ilet, lets[BUFSZ], qbuf[QBUFSZ]; 630. 631. if (spellid(0) == NO_SPELL) { 632. You("don't know any spells right now."); 633. return FALSE; 634. } 635. if (flags.menu_style == MENU_TRADITIONAL) { 636. /* we know there is at least 1 known spell */ 637. for (nspells = 1; nspells < MAXSPELL 638. && spellid(nspells) != NO_SPELL; nspells++) 639. continue; 640. 641. if (nspells == 1) Strcpy(lets, "a"); 642. else if (nspells < 27) Sprintf(lets, "a-%c", 'a' + nspells - 1); 643. else if (nspells == 27) Sprintf(lets, "a-z A"); 644. else if (nspells < 53) 645. Sprintf(lets, "a-z A-%c", 'A' + nspells - 27); 646. else if (nspells == 53) Sprintf(lets, "a-z A-Z 0"); 647. else if (nspells < 62) 648. Sprintf(lets, "a-z A-Z 0-%c", '0' + nspells - 53); 649. else Sprintf(lets, "a-z A-Z 0-9"); 650. 651. for(;;) { 652. Sprintf(qbuf, "Cast which spell? [%s ?]", lets); 653. if ((ilet = yn_function(qbuf, (char *)0, '\0')) == '?') 654. break; 655. 656. if (index(quitchars, ilet)) 657. return FALSE; 658. 659. idx = spell_let_to_idx(ilet); 660. if (idx >= 0 && idx < nspells) { 661. *spell_no = idx; 662. return TRUE; 663. } else 664. You("don't know that spell."); 665. } 666. } 667. return dospellmenu("Choose which spell to cast", 668. SPELLMENU_CAST, spell_no); 669. } 670. 671. /* the 'Z' command -- cast a spell */ 672. int 673. docast() 674. { 675. int spell_no; 676. 677. if (getspell(&spell_no)) 678. return spelleffects(spell_no, FALSE); 679. return 0; 680. } 681. 682. STATIC_OVL const char* 683. spelltypemnemonic(int skill) 684. { 685. switch (skill) { 686. case P_ATTACK_SPELL: 687. return " attack"; 688. case P_HEALING_SPELL: 689. return "healing"; 690. case P_DIVINATION_SPELL: 691. return " divine"; 692. case P_ENCHANTMENT_SPELL: 693. return "enchant"; 694. case P_PROTECTION_SPELL: 695. return "protect"; 696. case P_BODY_SPELL: 697. return " body"; 698. case P_MATTER_SPELL: 699. return " matter"; 700. default: 701. impossible("Unknown spell skill, %d;", skill); 702. return ""; 703. } 704. } 705. 706. int 707. spell_skilltype(booktype) 708. int booktype; 709. { 710. return (objects[booktype].oc_skill); 711. } 712. 713. STATIC_OVL void 714. cast_protection() 715. { 716. int loglev = 0; 717. int l = u.ulevel; 718. int natac = u.uac - u.uspellprot; 719. int gain; 720. 721. /* loglev=log2(u.ulevel)+1 (1..5) */ 722. while (l) { 723. loglev++; 724. l /= 2; 725. } 726. 727. /* The more u.uspellprot you already have, the less you get, 728. * and the better your natural ac, the less you get. 729. * 730. * LEVEL AC SPELLPROT from sucessive SPE_PROTECTION casts 731. * 1 10 0, 1, 2, 3, 4 732. * 1 0 0, 1, 2, 3 733. * 1 -10 0, 1, 2 734. * 2-3 10 0, 2, 4, 5, 6, 7, 8 735. * 2-3 0 0, 2, 4, 5, 6 736. * 2-3 -10 0, 2, 3, 4 737. * 4-7 10 0, 3, 6, 8, 9, 10, 11, 12 738. * 4-7 0 0, 3, 5, 7, 8, 9 739. * 4-7 -10 0, 3, 5, 6 740. * 7-15 -10 0, 3, 5, 6 741. * 8-15 10 0, 4, 7, 10, 12, 13, 14, 15, 16 742. * 8-15 0 0, 4, 7, 9, 10, 11, 12 743. * 8-15 -10 0, 4, 6, 7, 8 744. * 16-30 10 0, 5, 9, 12, 14, 16, 17, 18, 19, 20 745. * 16-30 0 0, 5, 9, 11, 13, 14, 15 746. * 16-30 -10 0, 5, 8, 9, 10 747. */ 748. gain = loglev - (int)u.uspellprot / (4 - min(3,(10 - natac)/10)); 749. 750. if (gain > 0) { 751. if (!Blind) { 752. const char *hgolden = hcolor(NH_GOLDEN); 753. 754. if (u.uspellprot) 755. pline_The("%s haze around you becomes more dense.", 756. hgolden); 757. else 758. pline_The("%s around you begins to shimmer with %s haze.", 759. /*[ what about being inside solid rock while polyd? ]*/ 760. (Underwater || Is_waterlevel(&u.uz)) ? "water" : "air", 761. an(hgolden)); 762. } 763. u.uspellprot += gain; 764. u.uspmtime = 765. P_SKILL(spell_skilltype(SPE_PROTECTION)) == P_EXPERT ? 20 : 10; 766. if (!u.usptime) 767. u.usptime = u.uspmtime; 768. find_ac(); 769. } else { 770. Your("skin feels warm for a moment."); 771. } 772. } 773. 774. /* attempting to cast a forgotten spell will cause disorientation */ 775. STATIC_OVL void 776. spell_backfire(spell) 777. int spell; 778. { 779. long duration = (long)((spellev(spell) + 1) * 3); /* 6..24 */ 780. 781. /* prior to 3.4.1, the only effect was confusion; it still predominates */ 782. switch (rn2(10)) { 783. case 0: 784. case 1: 785. case 2: 786. case 3: make_confused(duration, FALSE); /* 40% */ 787. break; 788. case 4: 789. case 5: 790. case 6: make_confused(2L * duration / 3L, FALSE); /* 30% */ 791. make_stunned(duration / 3L, FALSE); 792. break; 793. case 7: 794. case 8: make_stunned(2L * duration / 3L, FALSE); /* 20% */ 795. make_confused(duration / 3L, FALSE); 796. break; 797. case 9: make_stunned(duration, FALSE); /* 10% */ 798. break; 799. } 800. return; 801. } 802. 803. int 804. spelleffects(spell, atme) 805. int spell; 806. boolean atme; 807. { 808. int energy, damage, chance, n, intell; 809. int hungr; 810. int skill, role_skill; 811. boolean confused = (Confusion != 0); 812. struct obj *pseudo; 813. 814. /* 815. * Find the skill the hero has in a spell type category. 816. * See spell_skilltype for categories. 817. */ 818. skill = spell_skilltype(spellid(spell)); 819. role_skill = P_SKILL(skill); 820. 821. /* 822. * Spell casting no longer affects knowledge of the spell. A 823. * decrement of spell knowledge is done every turn. 824. */ 825. if (spellknow(spell) <= 0) { 826. Your("knowledge of this spell is twisted."); 827. pline("It invokes nightmarish images in your mind..."); 828. spell_backfire(spell); 829. return(0); 830. } else if (spellknow(spell) <= 100) { 831. You("strain to recall the spell."); 832. } else if (spellknow(spell) <= 1000) { 833. Your("knowledge of this spell is growing faint."); 834. } 835. energy = (spellev(spell) * 5); /* 5 <= energy <= 35 */ 836. 837. if (u.uhunger <= 10 && spellid(spell) != SPE_DETECT_FOOD) { 838. You("are too hungry to cast that spell."); 839. return(0); 840. } else if (ACURR(A_STR) < 4) { 841. You("lack the strength to cast spells."); 842. return(0); 843. } else if(check_capacity( 844. "Your concentration falters while carrying so much stuff.")) { 845. return (1); 846. } else if (!freehand()) { 847. Your("arms are not free to cast!"); 848. return (0); 849. } 850. 851. if (u.uhave.amulet) { 852. You_feel("the amulet draining your energy away."); 853. energy += rnd(2*energy); 854. } 855. if (spellid(spell) != SPE_DETECT_FOOD) { 856. hungr = energy * 2; 857. 858. /* If hero is a wizard, their current intelligence 859. * (bonuses + temporary + current) 860. * affects hunger reduction in casting a spell. 861. * 1. int = 17-18 no reduction 862. * 2. int = 16 1/4 hungr 863. * 3. int = 15 1/2 hungr 864. * 4. int = 1-14 normal reduction 865. * The reason for this is: 866. * a) Intelligence affects the amount of exertion 867. * in thinking. 868. * b) Wizards have spent their life at magic and 869. * understand quite well how to cast spells. 870. */ 871. intell = acurr(A_INT); 872. if (!Role_if(PM_WIZARD)) intell = 10; 873. switch (intell) { 874. case 25: case 24: case 23: case 22: 875. case 21: case 20: case 19: case 18: 876. case 17: hungr = 0; break; 877. case 16: hungr /= 4; break; 878. case 15: hungr /= 2; break; 879. } 880. } 881. else 882. hungr = 0; 883. /* don't put player (quite) into fainting from 884. * casting a spell, particularly since they might 885. * not even be hungry at the beginning; however, 886. * this is low enough that they must eat before 887. * casting anything else except detect food 888. */ 889. if (hungr > u.uhunger-3) 890. hungr = u.uhunger-3; 891. if (energy > u.uen) { 892. You("don't have enough energy to cast that spell."); 893. /* WAC/ALI Experts can override with HP/hunger loss */ 894. if ((role_skill >= P_SKILLED) && (yn("Continue?") == 'y')) { 895. energy -= u.uen; 896. hungr += energy * 2; 897. if (hungr > u.uhunger - 1) 898. hungr = u.uhunger - 1; 899. losehp(energy,"spellcasting exhaustion", KILLED_BY); 900. if (role_skill < P_EXPERT) exercise(A_WIS, FALSE); 901. energy = u.uen; 902. } else 903. return 0; 904. } 905. morehungry(hungr); 906. 907. chance = percent_success(spell); 908. if (confused || (rnd(100) > chance)) { 909. pline("You fail to cast the spell correctly."); 910. 911. #ifdef ALLEG_FX 912. if (iflags.usealleg) alleg_aura(u.ux, u.uy, P_ATTACK_SPELL-1); 913. #endif 914. 915. u.uen -= (energy / 2); 916. flags.botl = 1; 917. return(1); 918. } 919. 920. u.uen -= energy; 921. 922. flags.botl = 1; 923. exercise(A_WIS, TRUE); 924. 925. /* pseudo is a temporary "false" object containing the spell stats. */ 926. pseudo = mksobj(spellid(spell), FALSE, FALSE); 927. pseudo->blessed = pseudo->cursed = 0; 928. pseudo->quan = 20L; /* do not let useup get it */ 929. 930. /* WAC -- If skilled enough, will act like a blessed version */ 931. if (role_skill >= P_SKILLED) 932. pseudo->blessed = 1; 933. 934. #ifdef ALLEG_FX 935. if (iflags.usealleg) alleg_aura(u.ux, u.uy, skill); 936. #endif 937. switch(pseudo->otyp) { 938. /* 939. * At first spells act as expected. As the hero increases in skill 940. * with the appropriate spell type, some spells increase in their 941. * effects, e.g. more damage, further distance, and so on, without 942. * additional cost to the spellcaster. 943. */ 944. case SPE_MAGIC_MISSILE: 945. case SPE_FIREBALL: 946. case SPE_CONE_OF_COLD: 947. case SPE_LIGHTNING: 948. case SPE_ACID_STREAM: 949. case SPE_POISON_BLAST: 950. if (tech_inuse(T_SIGIL_TEMPEST)) { 951. weffects(pseudo); 952. break; 953. } /* else fall through... */ 954. /* these spells are all duplicates of wand effects */ 955. case SPE_FORCE_BOLT: 956. case SPE_SLEEP: 957. case SPE_KNOCK: 958. case SPE_SLOW_MONSTER: 959. case SPE_WIZARD_LOCK: 960. case SPE_DIG: 961. case SPE_TURN_UNDEAD: 962. case SPE_POLYMORPH: 963. case SPE_TELEPORT_AWAY: 964. case SPE_CANCELLATION: 965. case SPE_FINGER_OF_DEATH: 966. case SPE_LIGHT: 967. case SPE_DETECT_UNSEEN: 968. case SPE_HEALING: 969. case SPE_EXTRA_HEALING: 970. case SPE_DRAIN_LIFE: 971. case SPE_STONE_TO_FLESH: 972. if (!(objects[pseudo->otyp].oc_dir == NODIR)) { 973. if (atme) u.dx = u.dy = u.dz = 0; 974. else if (!getdir((char *)0)) { 975. /* getdir cancelled, re-use previous direction */ 976. pline_The("magical energy is released!"); 977. } 978. if(!u.dx && !u.dy && !u.dz) { 979. if ((damage = zapyourself(pseudo, TRUE)) != 0) { 980. char buf[BUFSZ]; 981. Sprintf(buf, "zapped %sself with a spell", uhim()); 982. losehp(damage, buf, NO_KILLER_PREFIX); 983. } 984. } else weffects(pseudo); 985. } else weffects(pseudo); 986. update_inventory(); /* spell may modify inventory */ 987. break; 988. /* these are all duplicates of scroll effects */ 989. case SPE_REMOVE_CURSE: 990. case SPE_CONFUSE_MONSTER: 991. case SPE_DETECT_FOOD: 992. case SPE_CAUSE_FEAR: 993. #if 0 994. /* high skill yields effect equivalent to blessed scroll */ 995. if (role_skill >= P_SKILLED) pseudo->blessed = 1; 996. #endif 997. /* fall through */ 998. case SPE_CHARM_MONSTER: 999. case SPE_MAGIC_MAPPING: 1000. case SPE_CREATE_MONSTER: 1001. case SPE_IDENTIFY: 1002. case SPE_COMMAND_UNDEAD: 1003. case SPE_SUMMON_UNDEAD: 1004. (void) seffects(pseudo); 1005. break; 1006. 1007. case SPE_ENCHANT_WEAPON: 1008. case SPE_ENCHANT_ARMOR: 1009. if (role_skill >= P_EXPERT) n = 8; 1010. else if (role_skill >= P_SKILLED) n = 10; 1011. else if (role_skill >= P_BASIC) n = 12; 1012. else n = 14; /* Unskilled or restricted */ 1013. if (!rn2(n)) { 1014. pseudo->blessed = 0; 1015. (void) seffects(pseudo); 1016. } else 1017. Your("enchantment failed!"); 1018. break; 1019. 1020. /* these are all duplicates of potion effects */ 1021. case SPE_HASTE_SELF: 1022. case SPE_DETECT_TREASURE: 1023. case SPE_DETECT_MONSTERS: 1024. case SPE_LEVITATION: 1025. case SPE_RESTORE_ABILITY: 1026. #if 0 1027. /* high skill yields effect equivalent to blessed potion */ 1028. if (role_skill >= P_SKILLED) pseudo->blessed = 1; 1029. #endif 1030. /* fall through */ 1031. case SPE_INVISIBILITY: 1032. (void) peffects(pseudo); 1033. break; 1034. case SPE_CURE_BLINDNESS: 1035. healup(0, 0, FALSE, TRUE); 1036. break; 1037. case SPE_CURE_SICKNESS: 1038. if (Sick) You("are no longer ill."); 1039. if (Slimed) { 1040. pline_The("slime disappears!"); 1041. Slimed = 0; 1042. /* flags.botl = 1; -- healup() handles this */ 1043. } 1044. healup(0, 0, TRUE, FALSE); 1045. break; 1046. case SPE_CREATE_FAMILIAR: 1047. (void) make_familiar((struct obj *)0, u.ux, u.uy, FALSE); 1048. break; 1049. case SPE_CLAIRVOYANCE: 1050. if (!BClairvoyant) 1051. do_vicinity_map(); 1052. /* at present, only one thing blocks clairvoyance */ 1053. else if (uarmh && uarmh->otyp == CORNUTHAUM) 1054. You("sense a pointy hat on top of your %s.", 1055. body_part(HEAD)); 1056. break; 1057. case SPE_PROTECTION: 1058. cast_protection(); 1059. break; 1060. case SPE_JUMPING: 1061. if (!jump(max(role_skill,1))) 1062. pline(nothing_happens); 1063. break; 1064. case SPE_RESIST_POISON: 1065. if(!(HPoison_resistance & INTRINSIC)) { 1066. You("feel healthy ..... for the moment at least."); 1067. incr_itimeout(&HPoison_resistance, rn1(1000, 500) + 1068. spell_damage_bonus(spellid(spell))*100); 1069. } else pline(nothing_happens); /* Already have as intrinsic */ 1070. break; 1071. case SPE_RESIST_SLEEP: 1072. if(!(HSleep_resistance & INTRINSIC)) { 1073. if (Hallucination) 1074. pline("Too much coffee!"); 1075. else 1076. You("no longer feel tired."); 1077. incr_itimeout(&HSleep_resistance, rn1(1000, 500) + 1078. spell_damage_bonus(spellid(spell))*100); 1079. } else pline(nothing_happens); /* Already have as intrinsic */ 1080. break; 1081. case SPE_ENDURE_COLD: 1082. if(!(HCold_resistance & INTRINSIC)) { 1083. You("feel warmer."); 1084. incr_itimeout(&HCold_resistance, rn1(1000, 500) + 1085. spell_damage_bonus(spellid(spell))*100); 1086. } else pline(nothing_happens); /* Already have as intrinsic */ 1087. break; 1088. case SPE_ENDURE_HEAT: 1089. if(!(HFire_resistance & INTRINSIC)) { 1090. if (Hallucination) 1091. pline("Excellent! You feel, like, totally cool!"); 1092. else 1093. You("feel colder."); 1094. incr_itimeout(&HFire_resistance, rn1(1000, 500) + 1095. spell_damage_bonus(spellid(spell))*100); 1096. } else pline(nothing_happens); /* Already have as intrinsic */ 1097. break; 1098. case SPE_INSULATE: 1099. if(!(HShock_resistance & INTRINSIC)) { 1100. if (Hallucination) 1101. pline("Bummer! You've been grounded!"); 1102. else 1103. You("are not at all shocked by this feeling."); 1104. incr_itimeout(&HShock_resistance, rn1(1000, 500) + 1105. spell_damage_bonus(spellid(spell))*100); 1106. } else pline(nothing_happens); /* Already have as intrinsic */ 1107. break; 1108. case SPE_ENLIGHTEN: 1109. You("feel self-knowledgeable..."); 1110. display_nhwindow(WIN_MESSAGE, FALSE); 1111. enlightenment(FALSE); 1112. pline("The feeling subsides."); 1113. exercise(A_WIS, TRUE); 1114. break; 1115. 1116. /* WAC -- new spells */ 1117. case SPE_FLAME_SPHERE: 1118. case SPE_FREEZE_SPHERE: 1119. { register int cnt = 1; 1120. struct monst *mtmp; 1121. 1122. 1123. if (role_skill >= P_SKILLED) cnt += (role_skill - P_BASIC); 1124. while(cnt--) { 1125. mtmp = make_helper((pseudo->otyp == SPE_FLAME_SPHERE) ? 1126. PM_FLAMING_SPHERE : PM_FREEZING_SPHERE, u.ux, u.uy); 1127. if (!mtmp) continue; 1128. mtmp->mtame = 10; 1129. mtmp->mhpmax = mtmp->mhp = 1; 1130. mtmp->isspell = mtmp->uexp = TRUE; 1131. } /* end while... */ 1132. break; 1133. } 1134. 1135. /* KMH -- new spells */ 1136. case SPE_PASSWALL: 1137. if (!Passes_walls) 1138. You_feel("ethereal."); 1139. incr_itimeout(&HPasses_walls, rn1(100, 50)); 1140. break; 1141. 1142. default: 1143. impossible("Unknown spell %d attempted.", spell); 1144. obfree(pseudo, (struct obj *)0); 1145. return(0); 1146. } 1147. 1148. /* gain skill for successful cast */ 1149. use_skill(skill, spellev(spell)); 1150. 1151. /* WAC successful casting increases solidity of knowledge */ 1152. boostknow(spell,CAST_BOOST); 1153. 1154. obfree(pseudo, (struct obj *)0); /* now, get rid of it */ 1155. return(1); 1156. } 1157. 1158. 1159. void 1160. losespells() 1161. { 1162. boolean confused = (Confusion != 0); 1163. int n, nzap, i; 1164. 1165. book = 0; 1166. for (n = 0; n < MAXSPELL && spellid(n) != NO_SPELL; n++) 1167. continue; 1168. if (n) { 1169. nzap = rnd(n) + confused ? 1 : 0; 1170. if (nzap > n) nzap = n; 1171. for (i = n - nzap; i < n; i++) { 1172. spellid(i) = NO_SPELL; 1173. exercise(A_WIS, FALSE); /* ouch! */ 1174. } 1175. } 1176. } 1177. 1178. 1179. /* the '+' command -- view known spells */ 1180. int 1181. dovspell() 1182. { 1183. char qbuf[QBUFSZ]; 1184. int splnum, othnum; 1185. struct spell spl_tmp; 1186. 1187. if (spellid(0) == NO_SPELL) 1188. You("don't know any spells right now."); 1189. else { 1190. while (dospellmenu("Currently known spells", 1191. SPELLMENU_VIEW, &splnum)) { 1192. Sprintf(qbuf, "Reordering spells; swap '%s' with", 1193. spellname(splnum)); 1194. if (!dospellmenu(qbuf, splnum, &othnum)) break; 1195. 1196. spl_tmp = spl_book[splnum]; 1197. spl_book[splnum] = spl_book[othnum]; 1198. spl_book[othnum] = spl_tmp; 1199. } 1200. } 1201. return 0; 1202. } 1203. 1204. STATIC_OVL boolean 1205. dospellmenu(prompt, splaction, spell_no) 1206. const char *prompt; 1207. int splaction; /* SPELLMENU_CAST, SPELLMENU_VIEW, or spl_book[] index */ 1208. int *spell_no; 1209. { 1210. winid tmpwin; 1211. int i, n, how; 1212. char buf[BUFSZ]; 1213. menu_item *selected; 1214. anything any; 1215. 1216. tmpwin = create_nhwindow(NHW_MENU); 1217. start_menu(tmpwin); 1218. any.a_void = 0; /* zero out all bits */ 1219. 1220. /* 1221. * The correct spacing of the columns depends on the 1222. * following that (1) the font is monospaced and (2) 1223. * that selection letters are pre-pended to the given 1224. * string and are of the form "a - ". 1225. * 1226. * To do it right would require that we implement columns 1227. * in the window-ports (say via a tab character). 1228. */ 1229. if (!iflags.menu_tab_sep) 1230. Sprintf(buf, "%-20s Level %-12s Fail", " Name", "Category"); 1231. else 1232. Sprintf(buf, "Name Level Category Fail"); 1233. if (flags.menu_style == MENU_TRADITIONAL) 1234. Strcat(buf, iflags.menu_tab_sep ? " Key" : " Key"); 1235. add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_BOLD, buf, MENU_UNSELECTED); 1236. for (i = 0; i < MAXSPELL && spellid(i) != NO_SPELL; i++) { 1237. Sprintf(buf, iflags.menu_tab_sep ? 1238. "%s %-d%s %s %-d%%" : "%-20s %2d%s %-12s %3d%%", 1239. spellname(i), spellev(i), 1240. spellknow(i) ? " " : "*", 1241. spelltypemnemonic(spell_skilltype(spellid(i))), 1242. 100 - percent_success(i)); 1243. if (flags.menu_style == MENU_TRADITIONAL) 1244. Sprintf(eos(buf), iflags.menu_tab_sep ? 1245. " %c" : "%4c ", spellet(i) ? spellet(i) : ' '); 1246. 1247. any.a_int = i+1; /* must be non-zero */ 1248. add_menu(tmpwin, NO_GLYPH, &any, 1249. 0, 0, ATR_NONE, buf, 1250. (i == splaction) ? MENU_SELECTED : MENU_UNSELECTED); 1251. } 1252. end_menu(tmpwin, prompt); 1253. 1254. how = PICK_ONE; 1255. if (splaction == SPELLMENU_VIEW && spellid(1) == NO_SPELL) 1256. how = PICK_NONE; /* only one spell => nothing to swap with */ 1257. n = select_menu(tmpwin, how, &selected); 1258. destroy_nhwindow(tmpwin); 1259. if (n > 0) { 1260. *spell_no = selected[0].item.a_int - 1; 1261. /* menu selection for `PICK_ONE' does not 1262. de-select any preselected entry */ 1263. if (n > 1 && *spell_no == splaction) 1264. *spell_no = selected[1].item.a_int - 1; 1265. free((genericptr_t)selected); 1266. /* default selection of preselected spell means that 1267. user chose not to swap it with anything */ 1268. if (*spell_no == splaction) return FALSE; 1269. return TRUE; 1270. } else if (splaction >= 0) { 1271. /* explicit de-selection of preselected spell means that 1272. user is still swapping but not for the current spell */ 1273. *spell_no = splaction; 1274. return TRUE; 1275. } 1276. return FALSE; 1277. } 1278. 1279. /* Integer square root function without using floating point. */ 1280. STATIC_OVL int 1281. isqrt(val) 1282. int val; 1283. { 1284. int rt = 0; 1285. int odd = 1; 1286. while(val >= odd) { 1287. val = val-odd; 1288. odd = odd+2; 1289. rt = rt + 1; 1290. } 1291. return rt; 1292. } 1293. 1294. 1295. STATIC_OVL int 1296. percent_success(spell) 1297. int spell; 1298. { 1299. /* Intrinsic and learned ability are combined to calculate 1300. * the probability of player's success at cast a given spell. 1301. */ 1302. int chance, splcaster, special, statused; 1303. int difficulty; 1304. int skill; 1305. 1306. splcaster = urole.spelbase; 1307. special = urole.spelheal; 1308. statused = ACURR(urole.spelstat); 1309. 1310. /* Calculate armor penalties */ 1311. if (uarm && !(uarm->otyp == ROBE || 1312. uarm->otyp == ROBE_OF_POWER || 1313. uarm->otyp == ROBE_OF_PROTECTION)) 1314. splcaster += 5; 1315. 1316. /* Robes are body armour in SLASH'EM */ 1317. if (uarm && is_metallic(uarm)) 1318. splcaster += /*(uarmc && uarmc->otyp == ROBE) ? 1319. urole.spelarmr/2 : */urole.spelarmr; 1320. else if (uarmc && uarmc->otyp == ROBE) 1321. splcaster -= urole.spelarmr; 1322. if (uarms) splcaster += urole.spelshld; 1323. 1324. if (uarmh && is_metallic(uarmh) && uarmh->otyp != HELM_OF_BRILLIANCE) 1325. splcaster += uarmhbon; 1326. if (uarmg && is_metallic(uarmg)) splcaster += uarmgbon; 1327. if (uarmf && is_metallic(uarmf)) splcaster += uarmfbon; 1328. 1329. if (spellid(spell) == urole.spelspec) 1330. splcaster += urole.spelsbon; 1331. 1332. /* `healing spell' bonus */ 1333. if (spell_skilltype(spellid(spell)) == P_HEALING_SPELL) 1334. splcaster += special; 1335. 1336. if (uarm && uarm->otyp == ROBE_OF_POWER) splcaster -= 3; 1337. if (splcaster < 5) splcaster = 5; 1338. if (splcaster > 20) splcaster = 20; 1339. 1340. /* Calculate learned ability */ 1341. 1342. /* Players basic likelihood of being able to cast any spell 1343. * is based of their `magic' statistic. (Int or Wis) 1344. */ 1345. chance = 11 * statused / 2; 1346. 1347. /* 1348. * High level spells are harder. Easier for higher level casters. 1349. * The difficulty is based on the hero's level and their skill level 1350. * in that spell type. 1351. */ 1352. skill = P_SKILL(spell_skilltype(spellid(spell))); 1353. skill = max(skill,P_UNSKILLED) - 1; /* unskilled => 0 */ 1354. difficulty= (spellev(spell)-1) * 4 - ((skill * 6) + (u.ulevel/3) + 1); 1355. 1356. if (difficulty > 0) { 1357. /* Player is too low level or unskilled. */ 1358. chance -= isqrt(900 * difficulty + 2000); 1359. } else { 1360. /* Player is above level. Learning continues, but the 1361. * law of diminishing returns sets in quickly for 1362. * low-level spells. That is, a player quickly gains 1363. * no advantage for raising level. 1364. */ 1365. int learning = 15 * -difficulty / spellev(spell); 1366. chance += learning > 20 ? 20 : learning; 1367. } 1368. 1369. /* Clamp the chance: >18 stat and advanced learning only help 1370. * to a limit, while chances below "hopeless" only raise the 1371. * specter of overflowing 16-bit ints (and permit wearing a 1372. * shield to raise the chances :-). 1373. */ 1374. if (chance < 0) chance = 0; 1375. if (chance > 120) chance = 120; 1376. 1377. /* Wearing anything but a light shield makes it very awkward 1378. * to cast a spell. The penalty is not quite so bad for the 1379. * player's class-specific spell. 1380. */ 1381. if (uarms && weight(uarms) > (int) objects[SMALL_SHIELD].oc_weight) { 1382. if (spellid(spell) == urole.spelspec) { 1383. chance /= 2; 1384. } else { 1385. chance /= 4; 1386. } 1387. } 1388. 1389. /* Finally, chance (based on player intell/wisdom and level) is 1390. * combined with ability (based on player intrinsics and 1391. * encumbrances). No matter how intelligent/wise and advanced 1392. * a player is, intrinsics and encumbrance can prevent casting; 1393. * and no matter how able, learning is always required. 1394. */ 1395. chance = chance * (20-splcaster) / 15 - splcaster; 1396. 1397. /* Clamp to percentile */ 1398. if (chance > 100) chance = 100; 1399. if (chance < 0) chance = 0; 1400. 1401. return chance; 1402. } 1403. 1404. /* Learn a spell during creation of the initial inventory */ 1405. void 1406. initialspell(obj) 1407. struct obj *obj; 1408. { 1409. int i; 1410. 1411. for (i = 0; i < MAXSPELL; i++) { 1412. if (spellid(i) == obj->otyp) { 1413. pline("Error: Spell %s already known.", 1414. OBJ_NAME(objects[obj->otyp])); 1415. return; 1416. } 1417. if (spellid(i) == NO_SPELL) { 1418. spl_book[i].sp_id = obj->otyp; 1419. spl_book[i].sp_lev = objects[obj->otyp].oc_level; 1420. incrnknow(i); 1421. return; 1422. } 1423. } 1424. impossible("Too many spells memorized!"); 1425. return; 1426. } 1427. 1428. boolean 1429. studyspell() 1430. { 1431. /*Vars are for studying spells 'W', 'F', 'I', 'N'*/ 1432. int spell_no; 1433. 1434. if (getspell(&spell_no)) { 1435. if (spellknow(spell_no) <= 0) { 1436. You("are unable to focus your memory of the spell."); 1437. return (FALSE); 1438. } else if (spellknow(spell_no) <= 1000) { 1439. Your("focus and reinforce your memory of the spell."); 1440. incrnknow(spell_no); 1441. exercise(A_WIS, TRUE); /* extra study */ 1442. return (TRUE); 1443. } else /* 1000 < spellknow(spell_no) <= 5000 */ 1444. You("know that spell quite well already."); 1445. } 1446. return (FALSE); 1447. } 1448. 1449. /*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