abstract
| - Below is the full text to spell.c from the source code of NetHack 2.2a. To link to a particular line, write [[NetHack 2.2a/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 2.1 87/10/07 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, &mons[dlevel+14+rn2(CMNUM-14-dlevel)]); 309. if(confused) 310. mtmp->mtame = mtmp->mpeaceful = 0; 311. } 312. } 313. break; 314. default: 315. impossible("Unknown spell %d attempted.", spell); 316. obfree(pseudo, (struct obj *)0); 317. return(0); 318. } 319. obfree(pseudo, (struct obj *)0); /* now, get rid of it */ 320. return(1); 321. } 322. 323. getspell() { 324. 325. register int max, ilet, i; 326. char lets[BUFSZ], buf[BUFSZ]; 327. 328. if (spl_book[0].sp_id == NO_SPELL) { 329. 330. pline("You don't know any spells right now."); 331. return(0); 332. } else { 333. 334. for(max = 1; (max < MAXSPELL) && (spl_book[max].sp_id != NO_SPELL); max++); 335. if (max >= MAXSPELL) { 336. 337. impossible("Too many spells memorized."); 338. return(0); 339. } 340. 341. for(i = 0; (i < max) && (i < 26); buf[++i] = 0) buf[i] = 'a' + i; 342. for(i = 26; (i < max) && (i < 52); buf[++i] = 0) buf[i] = 'A' + i - 26; 343. 344. if (max == 1) strcpy(lets, "a"); 345. else if (max < 27) sprintf(lets, "a-%c", 'a' + max - 1); 346. else if (max == 27) sprintf(lets, "a-z A"); 347. else sprintf(lets, "a-z A-%c", 'A' + max - 27); 348. for(;;) { 349. 350. pline("Cast which spell [%s ?]: ", lets); 351. if ((ilet = readchar()) == '?') { 352. dovspell(); 353. continue; 354. } else if ((ilet == '\033')||(ilet == '
')||(ilet == ' ')) 355. return(0); 356. else for(i = 0; buf[i] != 0; i++) if(ilet == buf[i]) return(++i); 357. pline("You don't know that spell."); 358. } 359. } 360. } 361. 362. losespells() { 363. register boolean confused = (Confusion != 0); 364. register int n, nzap, i; 365. 366. for(n = 0;(spl_book[n].sp_id != NO_SPELL) && (n < MAXSPELL); n++); 367. if (!n) return; 368. if (n < MAXSPELL) { 369. nzap = rnd(n); 370. if (nzap < n) nzap += confused; 371. for (i = 0; i < nzap; i++) spl_book[n-i-1].sp_id = NO_SPELL; 372. } else impossible("Too many spells in spellbook!"); 373. return; 374. } 375. 376. dovspell() { 377. 378. register int max, i, side; 379. char buf[BUFSZ], 380. *spellname(); 381. 382. if (spl_book[0].sp_id == NO_SPELL) { 383. 384. pline("You don't know any spells right now."); 385. return(0); 386. } else { 387. 388. for(max = 1; (max < MAXSPELL) && (spl_book[max].sp_id != NO_SPELL); max++); 389. if (max >= MAXSPELL) { 390. 391. impossible("Too many spells memorized."); 392. return(0); 393. } 394. } 395. set_pager(0); 396. side = (max + 1) / 2; 397. if(page_line("Currently known spells:") || page_line("")) goto quit; 398. 399. for(i = 1; i <= side; i++) { 400. 401. if((i < side) || !(max % 2)) { 402. 403. (void) sprintf(buf, "%c - (%d) %22s %c - (%d) %22s", 404. spellet(i), spellev(i), spellname(i), 405. spellet(i + side), spellev(i + side), spellname(i + side)); 406. } else { 407. 408. (void) sprintf(buf, "%c - (%d) %22s", spellet(i), spellev(i), spellname(i)); 409. } 410. if(page_line(buf)) goto quit; 411. } 412. 413. set_pager(1); 414. return(0); 415. quit: 416. set_pager(2); 417. return(0); 418. } 419. 420. spellet(spl) { 421. 422. if (spl < 27) return('a' + spl - 1); 423. else return('A' + spl - 27); 424. } 425. 426. spellev(spl) { 427. 428. return(spl_book[spl-1].sp_lev); 429. } 430. 431. char * 432. spellname(spl) { 433. 434. return(objects[spl_book[spl-1].sp_id].oc_name); 435. } 436. 437. spellid(spl) { return(spl_book[spl-1].sp_id); } 438. 439. #ifdef HARD 440. spelluses(spell) { return(spl_book[spell-1].sp_uses); } 441. decrnuses(spell) { spl_book[spell-1].sp_uses--; } 442. #endif 443. 444. #endif /* SPELLS /**/
|