Source:NetHack 2.3e/spell.c

Below is the full text to spell.c from the source code of NetHack 2.3e. To link to a particular line, write [[NetHack 2.3e/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.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 /**/