Source:NetHack 2.2a/spell.c

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 == '\n')||(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 /**/