Source:NetHack 1.3d/spell.c

Below is the full text to spell.c from the source code of NetHack 1.3d. To link to a particular line, write [[NetHack 1.3d/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.3	87/07/14 2.   /* hack.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(rnd(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. 	case 7: 165. 		/* curse a few inventory items at random! */ 166.  		nobj = 0; 167. 		for (otmp = invent; otmp; otmp = otmp->nobj)  nobj++; 168.  169.  		for (cnt = rnd(6); cnt > 0; cnt--)  { 170.  171.  			onum = rn2(nobj); 172. 			for(otmp = invent; onum != 0; onum--) otmp = otmp->nobj; 173. 			otmp->cursed++; 174. 		}  175.  		break; 176. 	}  177.  	return(0); 178. }  179.   180.  docast 181. {  182.  	register int	 spell, energy; 183. 	register boolean confused = (Confusion != 0); 184. 	register struct  obj	*pseudo; 185. 	struct	 obj	 *mksobj; 186.  187.  	spell = getspell; 188. 	if (!spell) return(0); 189. 	else  { 190.  191.  		energy = spellev(spell); 192. 		if(energy > u.uen)  { 193. 			pline("You are too weak to cast that spell."); 194. 			return(0); 195. 		} else  if ((u.uhunger <= 100) || (u.ustr < 6))  { 196. 			pline("You miss the strength for that spell."); 197. 			return(0); 198. 		} else	{ 199. 			morehungry(energy * 10); 200. 			u.uen -= energy; 201. 		}  202.  	}  203.  #ifdef HARD 204. 	if ((rn2(10) + u.ulevel + u.uluck - spellev(spell)) < 0) { 205.  206.  		pline("Fizzle....."); 207. 		return(0); 208. 	}  209.  #endif 210.  211.  /*	pseudo is a temporary "false" object containing the spell stats. */ 212.  	pseudo = mksobj(spellid(spell)); 213. 	pseudo->quan = 20;			/* do not let useup get it */ 214. 	switch(pseudo->otyp)  { 215.  216.  /* These spells are all duplicates of wand effects */ 217. 	case SPE_FORCE_BOLT: 218. 	case SPE_SLEEP: 219. 	case SPE_MAGIC_MISSILE: 220. 	case SPE_SLOW_MONSTER: 221. 	case SPE_FIREBALL: 222. 	case SPE_CONE_OF_COLD: 223. 	case SPE_DIG: 224. 	case SPE_TURN_UNDEAD: 225. 	case SPE_POLYMORPH: 226. 	case SPE_TELEPORT_AWAY: 227. 	case SPE_CANCELLATION: 228. 	case SPE_FINGER_OF_DEATH: 229. 	case SPE_LIGHT: 230. 	case SPE_DETECT_UNSEEN: 231. 		if (!(objects[pseudo->otyp].bits & NODIR))	getdir(1); 232. 		weffects(pseudo); 233. 		break; 234. /* These are all duplicates of scroll effects */ 235. 	case SPE_CONFUSE_MONSTER: 236. 	case SPE_DETECT_FOOD: 237. 	case SPE_CAUSE_FEAR: 238. 	case SPE_CHARM_MONSTER: 239. 	case SPE_REMOVE_CURSE: 240. 	case SPE_MAGIC_MAPPING: 241. 	case SPE_CREATE_MONSTER: 242. 	case SPE_IDENTIFY: 243. 	case SPE_GENOCIDE: 244. 		seffects(pseudo); 245. 		break; 246. 	case SPE_HASTE_SELF: 247. 	case SPE_DETECT_TREASURE: 248. 	case SPE_DETECT_MONSTERS: 249. 	case SPE_LEVITATION: 250. 	case SPE_RESTORE_STRENGTH: 251. 	case SPE_INVISIBILITY: 252. 		peffects(pseudo); 253. 		break; 254. 	case SPE_HEALING: 255. 		pline("You feel a bit better."); 256. 		healup(rnd(8), 1, 0, 0); 257. 		break; 258. 	case SPE_CURE_BLINDNESS: 259. 		healup(0, 0, 0, 1); 260. 		break; 261. 	case SPE_CURE_SICKNESS: 262. 		pline("You are no longer ill."); 263. 		healup(0, 0, 1, 0); 264. 		break; 265. 	case SPE_EXTRA_HEALING: 266. 		pline("You feel a fair bit better."); 267. 		healup(d(2,8), 1, 0, 0); 268. 		break; 269. 	case SPE_CREATE_FAMILIAR: 270. 		{	register struct monst *mtmp; 271. 			struct   monst  *makedog; 272.  273.  			mtmp = makedog; 274. 			if(mtmp) { 275. 				/* make it into something else */ 276. 				(void) newcham(mtmp, &mons[dlevel+14+rn2(CMNUM-14-dlevel)]); 277. 				if(confused) 278. 					mtmp->mtame = mtmp->mpeaceful = 0; 279. 			}  280.  		}  281.  		break; 282. 	default: 283. 		impossible("Unknown spell %d attempted.", spell); 284. 		obfree(pseudo, (struct obj *)0); 285. 		return(0); 286. 	}  287.  	flags.botl = 1; 288. 	obfree(pseudo, (struct obj *)0);	/* now, get rid of it */ 289. 	return(1); 290. }  291.   292.  getspell  { 293.  294.  	register int	max, ilet, i;  295. char	 lets[BUFSZ], buf[BUFSZ]; 296.  297.  	if (spl_book[0].sp_id == NO_SPELL)  { 298.  299.  		pline("You don't know any spells right now."); 300. 		return(0); 301. 	} else  { 302.  303.  	    for(max = 1; (max < MAXSPELL) && (spl_book[max].sp_id != NO_SPELL); max++); 304. 	    if (max >= MAXSPELL)  { 305.  306.  		impossible("Too many spells memorized."); 307. 		return(0); 308. 	    }  309.   310.  	    for(i = 0; (i < max) && (i < 26); buf[++i] = 0)  buf[i] = 'a' + i;  311. for(i = 26; (i < max) && (i < 52); buf[++i] = 0) buf[i] = 'A' + i - 26; 312.  313.  	    if (max == 1)  strcpy(lets, "a"); 314. 	    else if (max < 27)  sprintf(lets, "a-%c", 'a' + max - 1); 315. 	    else if (max == 27)  sprintf(lets, "a-z A"); 316. 	    else sprintf(lets, "a-z A-%c", 'A' + max - 27); 317. 	    for  { 318.  319.  		pline("Cast which spell [%s ?]: ", lets); 320. 		if ((ilet = readchar) == '?')  { 321. 			dovspell; 322. 			continue; 323. 		} else if ((ilet == '\033')||(ilet == '\n')||(ilet == ' ')) 324. 			return(0); 325. 		else for(i = 0; buf[i] != 0; i++)  if(ilet == buf[i])  return(++i); 326. 		pline("You don't know that spell."); 327. 	    }  328.  	}  329.  }  330.   331.  losespells { 332. 	register boolean confused = (Confusion != 0); 333. 	register int	 n, nzap, i;  334. 335. 	for(n = 0;(spl_book[n].sp_id != NO_SPELL) && (n < MAXSPELL); n++); 336. 	if (!n) return; 337. 	if (n < MAXSPELL) { 338. 		nzap = rnd(n); 339. 		if (nzap < n) nzap += confused; 340. 		for (i = 0; i < nzap; i++) spl_book[n-i-1].sp_id = NO_SPELL; 341. 	} else impossible("Too many spells in spellbook!"); 342. 	return; 343. }  344.   345.  dovspell { 346.  347.  	register int max, i, side; 348. 	char     buf[BUFSZ], 349. 		 *spellname; 350.  351.  	if (spl_book[0].sp_id == NO_SPELL)  { 352.  353.  		pline("You don't know any spells right now."); 354. 		return(0); 355. 	} else  { 356.  357.  	    for(max = 1; (max < MAXSPELL) && (spl_book[max].sp_id != NO_SPELL); max++); 358. 	    if (max >= MAXSPELL)  { 359.  360.  		impossible("Too many spells memorized."); 361. 		return(0); 362. 	    }  363.  	}  364.  	set_pager(0); 365. 	side = (max + 1) / 2; 366. 	if(page_line("Currently known spells:") || page_line(""))  goto quit; 367.  368.  	for(i = 1; i <= side; i++) { 369.  370.  		if((i < side) || !(max % 2))  { 371.  372.  		    (void) sprintf(buf, "%c - (%d) %22s          %c - (%d) %22s",  373.  				   spellet(i), spellev(i), spellname(i),  374.  				   spellet(i + side), spellev(i + side), spellname(i + side)); 375. 		} else { 376.  377.  		    (void) sprintf(buf, "%c - (%d) %22s", spellet(i), spellev(i), spellname(i)); 378. 		}  379.  		if(page_line(buf)) goto quit; 380. 	}  381.   382.  	set_pager(1); 383. 	return(0); 384. quit: 385. 	set_pager(2); 386. 	return(0); 387. }  388.   389.  spellet(spl)  { 390.  391.  	if (spl < 27)	return('a' + spl - 1); 392. 	else		return('A' + spl - 27); 393. }  394.   395.  spellev(spl)  { 396.  397.  	return(spl_book[spl-1].sp_lev); 398. }  399.   400.  char * 401. spellname(spl)  { 402.  403.  	return(objects[spl_book[spl-1].sp_id].oc_name); 404. }  405.   406.  spellid(spl)  { 407.  408.  	return(spl_book[spl-1].sp_id); 409. }  410.   411.  #endif /* SPELLS /**/