Source:NetHack 1.4f/spell.c

Below is the full text to spell.c from the source code of NetHack 1.4f. To link to a particular line, write [[NetHack 1.4f/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	1.4	87/08/08 2.   /* spell.c - version 1.0.1		M. Stephenson 07-04-86 */ 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.  				nomovemsg = "Oh, you already know that one!"; 99.  				useup(book); 100. 				return(1); 101. 			} else if (spl_book[i].sp_id == NO_SPELL)  { 102. 				spl_book[i].sp_id = booktype; 103. 				spl_book[i].sp_lev = objects[booktype].spl_lev; 104. 				spl_book[i].sp_flags = objects[booktype].bits; 105. 				nomovemsg = "You add the spell to your books."; 106. 				objects[booktype].oc_name_known = 1; 107. 				useup(book); 108. 				return(1); 109. 			}  110.  		}  111.  		impossible("Too many spells in spellbook!"); 112. 	}  113.  	useup(book); 114. 	return(1); 115. }  116.   117.  cursed_book(level) 118. 	register int	level; 119. {  120.  	register int	nobj, cnt, onum; 121. 	register struct obj	*otmp; 122.  123.  	switch(rn2(level)) { 124. 	case 0: 125. 		pline("you feel a wrenching sensation."); 126. 		tele;		/* teleport him */ 127. 		break; 128. 	case 1: 129. 		pline("you feel threatened."); 130. 		aggravate; 131. 		break; 132. 	case 2: 133. 		if(!Blind)	pline("a cloud of darkness falls upon you."); 134. 		Blind += rn1(100,250); 135. 		seeoff(0); 136. 		break; 137. 	case 3: 138. 		if (u.ugold <= 0)  { 139. 			pline("you feel a strange sensation."); 140. 		} else { 141. 			pline("you notice you have no gold!"); 142. 			u.ugold = 0; 143. 			flags.botl = 1; 144. 		}  145.  		break; 146. 	case 4: 147. 		pline("These runes were just too much to comprehend."); 148. 		HConfusion += rn1(7,16); 149. 		break; 150. 	case 5: 151. 		pline("The book was coated with contact poison!"); 152. 		if(Poison_resistance) { 153. 		    losestr(rn1(1,2)); 154. 		    losehp(rnd(6), "contact poison"); 155. 		} else { 156. 		    losestr(rn1(4,3)); 157. 		    losehp(rnd(10), "contact poison"); 158. 		}  159.  		break; 160. 	case 6: 161. 		pline("As you read the book, it explodes in your face!"); 162. 		losehp (2*rnd(10)+5, "exploding rune"); 163. 		break; 164. 	default: 165. 		rndcurse; 166. 		break; 167. 	}  168.  	return(0); 169. }  170.   171.  docast 172. {  173.  	register int	 spell, energy, damage; 174. 	register boolean confused = (Confusion != 0); 175. 	register struct  obj	*pseudo; 176. 	struct	 obj	 *mksobj; 177.  178.  	spell = getspell; 179. 	if (!spell) return(0); 180. 	else  { 181.  182.  		energy = spellev(spell); 183. 		if(energy > u.uen)  { 184. 			pline("You are too weak to cast that spell."); 185. 			return(0); 186. 		} else  if ((u.uhunger <= 100) || (u.ustr < 6))  { 187. 			pline("You miss the strength for that spell."); 188. 			return(0); 189. 		} else	{ 190. 			morehungry(energy * 10); 191. 			u.uen -= energy; 192. 		}  193.  	}  194.  #ifdef HARD 195. 	if (confused ||  196.  	    (rn2(10) + u.ulevel + u.uluck - spellev(spell)) <= 0) { 197.  198.  		if (Hallucination) 199. 			pline("Far out... a light show!"); 200. 		else	pline("The air around you crackles as you goof up."); 201. 		return(0); 202. 	}  203.  #endif 204.  205.  /*	pseudo is a temporary "false" object containing the spell stats. */ 206.  	pseudo = mksobj(spellid(spell)); 207. 	pseudo->quan = 20;			/* do not let useup get it */ 208. 	switch(pseudo->otyp)  { 209.  210.  /* These spells are all duplicates of wand effects */ 211. 	case SPE_FORCE_BOLT: 212. 	case SPE_SLEEP: 213. 	case SPE_MAGIC_MISSILE: 214. 	case SPE_SLOW_MONSTER: 215. 	case SPE_FIREBALL: 216. 	case SPE_CONE_OF_COLD: 217. 	case SPE_DIG: 218. 	case SPE_TURN_UNDEAD: 219. 	case SPE_POLYMORPH: 220. 	case SPE_TELEPORT_AWAY: 221. 	case SPE_CANCELLATION: 222. 	case SPE_FINGER_OF_DEATH: 223. 	case SPE_LIGHT: 224. 	case SPE_DETECT_UNSEEN: 225. 		if (!(objects[pseudo->otyp].bits & NODIR)) { 226. 			getdir(1); 227. 			if(!u.dx && !u.dy && !u.dz && (u.ulevel > 8)) { 228. 			    if((damage = zapyourself(pseudo))) 229. 				losehp(damage, "self-inflicted injury"); 230. 			} else	weffects(pseudo); 231. 		} else weffects(pseudo); 232. 		break; 233. /* These are all duplicates of scroll effects */ 234. 	case SPE_CONFUSE_MONSTER: 235. 	case SPE_DETECT_FOOD: 236. 	case SPE_CAUSE_FEAR: 237. 	case SPE_CHARM_MONSTER: 238. 	case SPE_REMOVE_CURSE: 239. 	case SPE_MAGIC_MAPPING: 240. 	case SPE_CREATE_MONSTER: 241. 	case SPE_IDENTIFY: 242. 	case SPE_GENOCIDE: 243. 		seffects(pseudo); 244. 		break; 245. 	case SPE_HASTE_SELF: 246. 	case SPE_DETECT_TREASURE: 247. 	case SPE_DETECT_MONSTERS: 248. 	case SPE_LEVITATION: 249. 	case SPE_RESTORE_STRENGTH: 250. 	case SPE_INVISIBILITY: 251. 		peffects(pseudo); 252. 		break; 253. 	case SPE_HEALING: 254. 		pline("You feel a bit better."); 255. 		healup(rnd(8), 0, 0, 0); 256. 		break; 257. 	case SPE_CURE_BLINDNESS: 258. 		healup(0, 0, 0, 1); 259. 		break; 260. 	case SPE_CURE_SICKNESS: 261. 		pline("You are no longer ill."); 262. 		healup(0, 0, 1, 0); 263. 		break; 264. 	case SPE_EXTRA_HEALING: 265. 		pline("You feel a fair bit better."); 266. 		healup(d(2,8), 1, 0, 0); 267. 		break; 268. 	case SPE_CREATE_FAMILIAR: 269. 		{	register struct monst *mtmp; 270. 			struct   monst  *makedog; 271.  272.  			mtmp = makedog; 273. 			if(mtmp) { 274. 				/* make it into something else */ 275. 				(void) newcham(mtmp, &mons[dlevel+14+rn2(CMNUM-14-dlevel)]); 276. 				if(confused) 277. 					mtmp->mtame = mtmp->mpeaceful = 0; 278. 			}  279.  		}  280.  		break; 281. 	default: 282. 		impossible("Unknown spell %d attempted.", spell); 283. 		obfree(pseudo, (struct obj *)0); 284. 		return(0); 285. 	}  286.  	flags.botl = 1; 287. 	obfree(pseudo, (struct obj *)0);	/* now, get rid of it */ 288. 	return(1); 289. }  290.   291.  getspell  { 292.  293.  	register int	max, ilet, i;  294. char	 lets[BUFSZ], buf[BUFSZ]; 295.  296.  	if (spl_book[0].sp_id == NO_SPELL)  { 297.  298.  		pline("You don't know any spells right now."); 299. 		return(0); 300. 	} else  { 301.  302.  	    for(max = 1; (max < MAXSPELL) && (spl_book[max].sp_id != NO_SPELL); max++); 303. 	    if (max >= MAXSPELL)  { 304.  305.  		impossible("Too many spells memorized."); 306. 		return(0); 307. 	    }  308.   309.  	    for(i = 0; (i < max) && (i < 26); buf[++i] = 0)  buf[i] = 'a' + i;  310. for(i = 26; (i < max) && (i < 52); buf[++i] = 0) buf[i] = 'A' + i - 26; 311.  312.  	    if (max == 1)  strcpy(lets, "a"); 313. 	    else if (max < 27)  sprintf(lets, "a-%c", 'a' + max - 1); 314. 	    else if (max == 27)  sprintf(lets, "a-z A"); 315. 	    else sprintf(lets, "a-z A-%c", 'A' + max - 27); 316. 	    for  { 317.  318.  		pline("Cast which spell [%s ?]: ", lets); 319. 		if ((ilet = readchar) == '?')  { 320. 			dovspell; 321. 			continue; 322. 		} else if ((ilet == '\033')||(ilet == '\n')||(ilet == ' ')) 323. 			return(0); 324. 		else for(i = 0; buf[i] != 0; i++)  if(ilet == buf[i])  return(++i); 325. 		pline("You don't know that spell."); 326. 	    }  327.  	}  328.  }  329.   330.  losespells { 331. 	register boolean confused = (Confusion != 0); 332. 	register int	 n, nzap, i;  333. 334. 	for(n = 0;(spl_book[n].sp_id != NO_SPELL) && (n < MAXSPELL); n++); 335. 	if (!n) return; 336. 	if (n < MAXSPELL) { 337. 		nzap = rnd(n); 338. 		if (nzap < n) nzap += confused; 339. 		for (i = 0; i < nzap; i++) spl_book[n-i-1].sp_id = NO_SPELL; 340. 	} else impossible("Too many spells in spellbook!"); 341. 	return; 342. }  343.   344.  dovspell { 345.  346.  	register int max, i, side; 347. 	char     buf[BUFSZ], 348. 		 *spellname; 349.  350.  	if (spl_book[0].sp_id == NO_SPELL)  { 351.  352.  		pline("You don't know any spells right now."); 353. 		return(0); 354. 	} else  { 355.  356.  	    for(max = 1; (max < MAXSPELL) && (spl_book[max].sp_id != NO_SPELL); max++); 357. 	    if (max >= MAXSPELL)  { 358.  359.  		impossible("Too many spells memorized."); 360. 		return(0); 361. 	    }  362.  	}  363.  	set_pager(0); 364. 	side = (max + 1) / 2; 365. 	if(page_line("Currently known spells:") || page_line(""))  goto quit; 366.  367.  	for(i = 1; i <= side; i++) { 368.  369.  		if((i < side) || !(max % 2))  { 370.  371.  		    (void) sprintf(buf, "%c - (%d) %22s          %c - (%d) %22s",  372.  				   spellet(i), spellev(i), spellname(i),  373.  				   spellet(i + side), spellev(i + side), spellname(i + side)); 374. 		} else { 375.  376.  		    (void) sprintf(buf, "%c - (%d) %22s", spellet(i), spellev(i), spellname(i)); 377. 		}  378.  		if(page_line(buf)) goto quit; 379. 	}  380.   381.  	set_pager(1); 382. 	return(0); 383. quit: 384. 	set_pager(2); 385. 	return(0); 386. }  387.   388.  spellet(spl)  { 389.  390.  	if (spl < 27)	return('a' + spl - 1); 391. 	else		return('A' + spl - 27); 392. }  393.   394.  spellev(spl)  { 395.  396.  	return(spl_book[spl-1].sp_lev); 397. }  398.   399.  char * 400. spellname(spl)  { 401.  402.  	return(objects[spl_book[spl-1].sp_id].oc_name); 403. }  404.   405.  spellid(spl)  { 406.  407.  	return(spl_book[spl-1].sp_id); 408. }  409.   410.  #endif /* SPELLS /**/