Source:NetHack 2.3e/spell.c
Jump to navigation
Jump to search
Below is the full text to spell.c from the source code of NetHack 2.3e.
Warning! This is the source code from an old release. For newer releases, see Source code
Screenshots and source code from Hack are used under the CWI license.
1. /* SCCS Id: @(#)spell.c 2.3 87/12/12 2. */ 3. 4. #include "hack.h" 5. #ifdef SPELLS 6. extern char *nomovemsg; 7. 8. doxcribe() { 9. register struct obj *book; 10. struct obj *getobj(); 11. register boolean confused = (Confusion != 0); 12. register boolean oops; 13. register schar delay; 14. register int booktype; 15. register int i; 16. 17. book = getobj("+", "transcribe"); 18. if(!book) return(0); 19. 20. if(Blind) { 21. pline("Being blind, you cannot read the mystic runes."); 22. useup(book); /* well, if you are stupid... */ 23. return(0); 24. } 25. 26. if(confused) { 27. pline("Being confused, you cannot grasp the meaning of this tome."); 28. useup(book); /* and more stupidity... */ 29. return(0); 30. } 31. booktype = book->otyp; 32. oops = !rn2(u.ulevel - objects[booktype].spl_lev + 7); 33. switch(booktype) { 34. 35. /* level 1 spells */ 36. case SPE_HEALING: 37. case SPE_DETECT_MONSTERS: 38. case SPE_FORCE_BOLT: 39. case SPE_LIGHT: 40. case SPE_SLEEP: 41. /* level 2 spells */ 42. case SPE_MAGIC_MISSILE: 43. case SPE_CONFUSE_MONSTER: 44. case SPE_SLOW_MONSTER: 45. case SPE_CURE_BLINDNESS: 46. case SPE_CREATE_MONSTER: 47. case SPE_DETECT_FOOD: 48. delay = -objects[booktype].oc_delay; 49. break; 50. /* level 3 spells */ 51. case SPE_HASTE_SELF: 52. case SPE_CAUSE_FEAR: 53. case SPE_CURE_SICKNESS: 54. case SPE_DETECT_UNSEEN: 55. case SPE_EXTRA_HEALING: 56. case SPE_CHARM_MONSTER: 57. /* level 4 spells */ 58. case SPE_LEVITATION: 59. case SPE_RESTORE_STRENGTH: 60. case SPE_INVISIBILITY: 61. case SPE_FIREBALL: 62. case SPE_DETECT_TREASURE: 63. delay = -(objects[booktype].spl_lev - 1) * objects[booktype].oc_delay; 64. break; 65. /* level 5 spells */ 66. case SPE_REMOVE_CURSE: 67. case SPE_MAGIC_MAPPING: 68. case SPE_CONE_OF_COLD: 69. case SPE_IDENTIFY: 70. case SPE_DIG: 71. /* level 6 spells */ 72. case SPE_TURN_UNDEAD: 73. case SPE_POLYMORPH: 74. case SPE_CREATE_FAMILIAR: 75. case SPE_TELEPORT_AWAY: 76. delay = -objects[booktype].spl_lev * objects[booktype].oc_delay; 77. break; 78. /* level 7 spells */ 79. case SPE_CANCELLATION: 80. case SPE_FINGER_OF_DEATH: 81. case SPE_GENOCIDE: 82. delay = -8 * objects[booktype].oc_delay; 83. break; 84. /* impossible */ 85. default: 86. impossible("Unknown spell-book, %d;", booktype); 87. return(0); 88. } 89. 90. pline("You begin to transcribe the spell."); 91. if(oops || book->cursed) { 92. cursed_book(objects[booktype].spl_lev); 93. nomul(delay); /* study time */ 94. } else { 95. nomul(delay); /* study time */ 96. for(i = 0; i < MAXSPELL; i++) { 97. if(spl_book[i].sp_id == booktype) { 98. #ifdef HARD 99. nomovemsg = "You make that spell more legible."; 100. spl_book[i].sp_uses += rn1(3,8-spl_book[i].sp_lev); 101. #else 102. nomovemsg = "Oh, you already know that one!"; 103. #endif 104. useup(book); 105. return(1); 106. } else if (spl_book[i].sp_id == NO_SPELL) { 107. spl_book[i].sp_id = booktype; 108. spl_book[i].sp_lev = objects[booktype].spl_lev; 109. spl_book[i].sp_flags = objects[booktype].bits; 110. #ifdef HARD 111. /* spells have 2 .. 10-level uses. */ 112. /* ie 2 or 3 uses w/ most potent */ 113. spl_book[i].sp_uses = rn1(3,8-spl_book[i].sp_lev); 114. #endif 115. nomovemsg = "You add the spell to your books."; 116. objects[booktype].oc_name_known = 1; 117. useup(book); 118. return(1); 119. } 120. } 121. impossible("Too many spells in spellbook!"); 122. } 123. useup(book); 124. return(1); 125. } 126. 127. cursed_book(level) 128. register int level; 129. { 130. switch(rn2(level)) { 131. case 0: 132. pline("You feel a wrenching sensation."); 133. tele(); /* teleport him */ 134. break; 135. case 1: 136. pline("You feel threatened."); 137. aggravate(); 138. break; 139. case 2: 140. if(!Blind) pline("A cloud of darkness falls upon you."); 141. Blinded += rn1(100,250); 142. seeoff(0); 143. break; 144. case 3: 145. if (u.ugold <= 0) { 146. pline("You feel a strange sensation."); 147. } else { 148. pline("You notice you have no gold!"); 149. u.ugold = 0; 150. flags.botl = 1; 151. } 152. break; 153. case 4: 154. pline("These runes were just too much to comprehend."); 155. HConfusion += rn1(7,16); 156. break; 157. case 5: 158. pline("The book was coated with contact poison!"); 159. if(Poison_resistance) { 160. losestr(rn1(1,2)); 161. losehp(rnd(6), "contact poison"); 162. } else { 163. losestr(rn1(4,3)); 164. losehp(rnd(10), "contact poison"); 165. } 166. break; 167. case 6: 168. pline("As you read the book, it explodes in your face!"); 169. losehp (2*rnd(10)+5, "exploding rune"); 170. break; 171. default: 172. rndcurse(); 173. break; 174. } 175. return(0); 176. } 177. 178. docast() 179. { 180. register int spell, energy, damage; 181. register boolean confused = (Confusion != 0); 182. register struct obj *pseudo; 183. struct obj *mksobj(); 184. 185. spell = getspell(); 186. if (!spell) return(0); 187. else { 188. #ifdef HARD 189. /* note that turning to the page decrements the # of uses, */ 190. /* even if the mage does not have enough food/energy to use */ 191. /* the spell */ 192. switch (spelluses(spell)) { 193. case 0: 194. pline ("That page is too faint to read at the moment."); 195. return(0); 196. case 1: 197. pline ("You can barely make out the runes on this page."); 198. break; 199. case 2: 200. pline ("This spell is starting to look well used."); 201. break; 202. default: 203. break; 204. } 205. decrnuses(spell); 206. #endif 207. energy = spellev(spell); 208. #ifdef BVH 209. if (has_amulet()) { 210. 211. pline("You feel the amulet draining your energy away."); 212. energy *= rnd(6); 213. } 214. #endif 215. if(energy > u.uen) { 216. pline("You are too weak to cast that spell."); 217. return(0); 218. } else if ((u.uhunger <= 100) || (u.ustr < 6)) { 219. pline("You miss the strength for that spell."); 220. return(0); 221. } else { 222. morehungry(energy * 10); 223. u.uen -= energy; 224. } 225. flags.botl = 1; 226. } 227. #ifdef HARD 228. if (confused || 229. (rn2(10) + (int)(u.ulevel + u.uluck) - 3*spellev(spell)) < 0) { 230. 231. if (Hallucination) 232. pline("Far out... a light show!"); 233. else pline("The air around you crackles as you goof up."); 234. return(0); 235. } 236. #endif 237. 238. /* pseudo is a temporary "false" object containing the spell stats. */ 239. pseudo = mksobj(spellid(spell)); 240. pseudo->quan = 20; /* do not let useup get it */ 241. switch(pseudo->otyp) { 242. 243. /* These spells are all duplicates of wand effects */ 244. case SPE_FORCE_BOLT: 245. case SPE_SLEEP: 246. case SPE_MAGIC_MISSILE: 247. case SPE_SLOW_MONSTER: 248. case SPE_FIREBALL: 249. case SPE_CONE_OF_COLD: 250. case SPE_DIG: 251. case SPE_TURN_UNDEAD: 252. case SPE_POLYMORPH: 253. case SPE_TELEPORT_AWAY: 254. case SPE_CANCELLATION: 255. case SPE_FINGER_OF_DEATH: 256. case SPE_LIGHT: 257. case SPE_DETECT_UNSEEN: 258. if (!(objects[pseudo->otyp].bits & NODIR)) { 259. getdir(1); 260. if(!u.dx && !u.dy && !u.dz && (u.ulevel > 8)) { 261. if((damage = zapyourself(pseudo))) 262. losehp(damage, "self-inflicted injury"); 263. } else weffects(pseudo); 264. } else weffects(pseudo); 265. break; 266. /* These are all duplicates of scroll effects */ 267. case SPE_CONFUSE_MONSTER: 268. case SPE_DETECT_FOOD: 269. case SPE_CAUSE_FEAR: 270. case SPE_CHARM_MONSTER: 271. case SPE_REMOVE_CURSE: 272. case SPE_MAGIC_MAPPING: 273. case SPE_CREATE_MONSTER: 274. case SPE_IDENTIFY: 275. case SPE_GENOCIDE: 276. seffects(pseudo); 277. break; 278. case SPE_HASTE_SELF: 279. case SPE_DETECT_TREASURE: 280. case SPE_DETECT_MONSTERS: 281. case SPE_LEVITATION: 282. case SPE_RESTORE_STRENGTH: 283. case SPE_INVISIBILITY: 284. peffects(pseudo); 285. break; 286. case SPE_HEALING: 287. pline("You feel a bit better."); 288. healup(rnd(8), 0, 0, 0); 289. break; 290. case SPE_CURE_BLINDNESS: 291. healup(0, 0, 0, 1); 292. break; 293. case SPE_CURE_SICKNESS: 294. pline("You are no longer ill."); 295. healup(0, 0, 1, 0); 296. break; 297. case SPE_EXTRA_HEALING: 298. pline("You feel a fair bit better."); 299. healup(d(2,8), 1, 0, 0); 300. break; 301. case SPE_CREATE_FAMILIAR: 302. { register struct monst *mtmp; 303. struct monst *makedog(); 304. 305. mtmp = makedog(); 306. if(mtmp) { 307. /* make it into something else */ 308. (void) newcham(mtmp, 309. #ifndef RPH 310. &mons[dlevel+14+rn2(CMNUM-14-dlevel)]); 311. #else 312. (struct pemonst *)0); 313. #endif 314. if(confused) 315. mtmp->mtame = mtmp->mpeaceful = 0; 316. } 317. } 318. break; 319. default: 320. impossible("Unknown spell %d attempted.", spell); 321. obfree(pseudo, (struct obj *)0); 322. return(0); 323. } 324. obfree(pseudo, (struct obj *)0); /* now, get rid of it */ 325. return(1); 326. } 327. 328. getspell() { 329. 330. register int max, ilet, i; 331. char lets[BUFSZ], buf[BUFSZ]; 332. 333. if (spl_book[0].sp_id == NO_SPELL) { 334. 335. pline("You don't know any spells right now."); 336. return(0); 337. } else { 338. 339. for(max = 1; (max < MAXSPELL) && (spl_book[max].sp_id != NO_SPELL); max++); 340. if (max >= MAXSPELL) { 341. 342. impossible("Too many spells memorized."); 343. return(0); 344. } 345. 346. for(i = 0; (i < max) && (i < 26); buf[++i] = 0) buf[i] = 'a' + i; 347. for(i = 26; (i < max) && (i < 52); buf[++i] = 0) buf[i] = 'A' + i - 26; 348. 349. if (max == 1) strcpy(lets, "a"); 350. else if (max < 27) sprintf(lets, "a-%c", 'a' + max - 1); 351. else if (max == 27) sprintf(lets, "a-z A"); 352. else sprintf(lets, "a-z A-%c", 'A' + max - 27); 353. for(;;) { 354. 355. pline("Cast which spell [%s ?]: ", lets); 356. if ((ilet = readchar()) == '?') { 357. dovspell(); 358. continue; 359. } else if ((ilet == '\033')||(ilet == '\n')||(ilet == ' ')) 360. return(0); 361. else for(i = 0; buf[i] != 0; i++) if(ilet == buf[i]) return(++i); 362. pline("You don't know that spell."); 363. } 364. } 365. } 366. 367. losespells() { 368. register boolean confused = (Confusion != 0); 369. register int n, nzap, i; 370. 371. for(n = 0;(spl_book[n].sp_id != NO_SPELL) && (n < MAXSPELL); n++); 372. if (!n) return; 373. if (n < MAXSPELL) { 374. nzap = rnd(n); 375. if (nzap < n) nzap += confused; 376. for (i = 0; i < nzap; i++) spl_book[n-i-1].sp_id = NO_SPELL; 377. } else impossible("Too many spells in spellbook!"); 378. return; 379. } 380. 381. dovspell() { 382. 383. register int max, i, side; 384. extern char morc; 385. char buf[BUFSZ], 386. any[BUFSZ], 387. *spellname(); 388. 389. if (spl_book[0].sp_id == NO_SPELL) { 390. 391. pline("You don't know any spells right now."); 392. return(0); 393. } 394. 395. for(max = 1; (max < MAXSPELL) && (spl_book[max].sp_id != NO_SPELL); max++); 396. if (max >= MAXSPELL) { 397. 398. impossible("Too many spells memorized."); 399. return(0); 400. } 401. morc = 0; /* just to be sure */ 402. cornline(0, "Currently known spells:"); 403. 404. for(i = 1; i <= max; i++) { 405. 406. (void) sprintf(buf, "%c - %s (%d)", 407. spellet(i),spellname(i),spellev(i)); 408. cornline(1, buf); 409. any[i-1] = spellet(i); 410. } 411. any[i-1] = 0; 412. cornline(2, any); 413. 414. return(0); 415. } 416. 417. spellet(spl) { 418. 419. if (spl < 27) return('a' + spl - 1); 420. else return('A' + spl - 27); 421. } 422. 423. spellev(spl) { 424. 425. return(spl_book[spl-1].sp_lev); 426. } 427. 428. char * 429. spellname(spl) { 430. 431. return(objects[spl_book[spl-1].sp_id].oc_name); 432. } 433. 434. spellid(spl) { return(spl_book[spl-1].sp_id); } 435. 436. #ifdef HARD 437. spelluses(spell) { return(spl_book[spell-1].sp_uses); } 438. decrnuses(spell) { spl_book[spell-1].sp_uses--; } 439. #endif 440. 441. #endif /* SPELLS /**/