Source:NetHack 3.4.0/spell.c

Below is the full text to spell.c from the source code of NetHack 3.4.0. To link to a particular line, write [[NetHack 3.4.0/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	3.4	2002/02/12	*/ 2.   /*	Copyright (c) M. Stephenson 1988			  */ 3.   /* NetHack may be freely redistributed. See license for details. */ 4.     5.    #include "hack.h"  6. 7.   static NEARDATA schar delay;		/* moves left for this spell */ 8.   static NEARDATA struct obj *book;	/* last/current book being xscribed */ 9.    10.   /* spellmenu arguments; 0 thru n-1 used as spl_book[] index when swapping */ 11.  #define SPELLMENU_CAST (-2) 12.  #define SPELLMENU_VIEW (-1) 13.   14.   #define KEEN 20000 15.  #define MAX_SPELL_STUDY 3 16.  #define incrnknow(spell)        spl_book[spell].sp_know = KEEN 17.   18.   #define spellev(spell)		spl_book[spell].sp_lev 19.  #define spellname(spell)	OBJ_NAME(objects[spellid(spell)]) 20.  #define spellet(spell)	\ 21.  	((char)((spell < 26) ? ('a' + spell) : ('A' + spell - 26))) 22.   23.   STATIC_DCL int FDECL(spell_let_to_idx, (CHAR_P)); 24.  STATIC_DCL void FDECL(cursed_book, (int)); 25.  STATIC_DCL void FDECL(deadbook, (struct obj *)); 26.  STATIC_PTR int NDECL(learn); 27.  STATIC_DCL boolean FDECL(getspell, (int *)); 28.  STATIC_DCL boolean FDECL(dospellmenu, (const char *,int,int *)); 29.  STATIC_DCL int FDECL(percent_success, (int)); 30.  STATIC_DCL int NDECL(throwspell); 31.  STATIC_DCL void NDECL(cast_protection); 32.  STATIC_DCL const char *FDECL(spelltypemnemonic, (int)); 33.  STATIC_DCL int FDECL(isqrt, (int)); 34.   35.   /* The roles[] table lists the role-specific values for tuning 36.   * percent_success. 37.   *  38.    * Reasoning: 39.   *   spelbase, spelheal: 40.   *	Arc are aware of magic through historical research 41.   *	Bar abhor magic (Conan finds it "interferes with his animal instincts") 42.   *	Cav are ignorant to magic 43.   *	Hea are very aware of healing magic through medical research 44.   *	Kni are moderately aware of healing from Paladin training 45.   *	Mon use magic to attack and defend in lieu of weapons and armor 46.   *	Pri are very aware of healing magic through theological research 47.   *	Ran avoid magic, preferring to fight unseen and unheard 48.   *	Rog are moderately aware of magic through trickery 49.   *	Sam have limited magical awareness, prefering meditation to conjuring 50.   *	Tou are aware of magic from all the great films they have seen 51.   *	Val have limited magical awareness, prefering fighting 52.   *	Wiz are trained mages 53.   *  54.    *	The arms penalty is lessened for trained fighters Bar, Kni, Ran, 55.   *	Sam, Val - 56.   *	the penalty is its metal interference, not encumbrance. 57.   *	The `spelspec' is a single spell which is fundamentally easier 58.   *	 for that role to cast. 59.   *  60.    *  spelspec, spelsbon: 61.   *	Arc map masters (SPE_MAGIC_MAPPING) 62.   *	Bar fugue/berserker (SPE_HASTE_SELF) 63.   *	Cav born to dig (SPE_DIG) 64.   *	Hea to heal (SPE_CURE_SICKNESS) 65.   *	Kni to turn back evil (SPE_TURN_UNDEAD) 66.   *	Mon to preserve their abilities (SPE_RESTORE_ABILITY) 67.   *	Pri to bless (SPE_REMOVE_CURSE) 68.   *	Ran to hide (SPE_INVISIBILITY) 69.   *	Rog to find loot (SPE_DETECT_TREASURE) 70.   *	Sam to be At One (SPE_CLAIRVOYANCE) 71.   *	Tou to smile (SPE_CHARM_MONSTER) 72.   *	Val control the cold (SPE_CONE_OF_COLD) 73.   *	Wiz all really, but SPE_MAGIC_MISSILE is their party trick 74.   *  75.    *	See percent_success below for more comments. 76.   *  77.    *  uarmbon, uarmsbon, uarmhbon, uarmgbon, uarmfbon: 78.   *	Fighters find body armour & shield a little less limiting. 79.   *	Headgear, Gauntlets and Footwear are not role-specific (but  80.    *	still have an effect, except helm of brilliance, which is designed  81.    *	to permit magic-use). 82.   */  83.    84.   #define uarmhbon 4 /* Metal helmets interfere with the mind */ 85.  #define uarmgbon 6 /* Casting channels through the hands */ 86.  #define uarmfbon 2 /* All metal interferes to some degree */ 87.   88.   /* since the spellbook itself doesn't blow up, don't say just "explodes" */ 89.  static const char explodes[] = "radiates explosive energy"; 90.   91.   /* convert a letter into a number in the range 0..51, or -1 if not a letter */ 92.  STATIC_OVL int 93.  spell_let_to_idx(ilet) 94.  char ilet; 95.  {  96.       int indx; 97.   98.       indx = ilet - 'a'; 99.      if (indx >= 0 && indx < 26) return indx; 100.     indx = ilet - 'A'; 101.     if (indx >= 0 && indx < 26) return indx + 26; 102.     return -1; 103. }  104.   105.  STATIC_OVL void 106. cursed_book(lev) 107. 	register int	lev; 108. {  109.  	switch(rn2(lev)) { 110. 	case 0: 111. 		You_feel("a wrenching sensation."); 112. 		tele;		/* teleport him */ 113. 		break; 114. 	case 1: 115. 		You_feel("threatened."); 116. 		aggravate; 117. 		break; 118. 	case 2: 119. 		make_blinded(Blinded + rn1(100,250),TRUE); 120. 		break; 121. 	case 3: 122. 		take_gold; 123. 		break; 124. 	case 4: 125. 		pline("These runes were just too much to comprehend."); 126. 		make_confused(HConfusion + rn1(7,16),FALSE); 127. 		break; 128. 	case 5: 129. 		pline_The("book was coated with contact poison!"); 130. 		if (uarmg) { 131. 		    if (uarmg->oerodeproof || !is_corrodeable(uarmg)) { 132. 			Your("gloves seem unaffected."); 133. 		    } else if (uarmg->oeroded2 < MAX_ERODE) { 134. 			if (uarmg->greased) { 135. 			    grease_protect(uarmg, "gloves", &youmonst); 136. 			} else { 137. 			    Your("gloves corrode%s!",  138.  				 uarmg->oeroded2+1 == MAX_ERODE ?  139.  				 " completely" : uarmg->oeroded2 ?  140.  				 " further" : ""); 141. 			    uarmg->oeroded2++; 142. 			}  143.  		    } else 144. 			Your("gloves %s completely corroded.",  145.  			     Blind ? "feel" : "look"); 146. 		    break; 147. 		}  148.  		losestr(Poison_resistance ? rn1(2,1) : rn1(4,3)); 149. 		losehp(rnd(Poison_resistance ? 6 : 10), 150.  		       "contact-poisoned spellbook", KILLED_BY_AN); 151. 		break; 152. 	case 6: 153. 		if(Antimagic) { 154. 		    shieldeff(u.ux, u.uy); 155. 		    pline_The("book %s, but you are unharmed!", explodes); 156. 		} else { 157. 		    pline("As you read the book, it %s in your %s!",  158.  			  explodes, body_part(FACE)); 159. 		    losehp (2*rnd(10)+5, "exploding rune", KILLED_BY_AN); 160. 		}  161.  		break; 162. 	default: 163. 		rndcurse; 164. 		break; 165. 	}  166.  	return; 167. }  168.   169.  /* special effects for The Book of the Dead */ 170. STATIC_OVL void 171. deadbook(book2) 172. struct obj *book2; 173. {  174.      struct monst *mtmp, *mtmp2; 175.     coord mm; 176.  177.      You("turn the pages of the Book of the Dead..."); 178.     makeknown(SPE_BOOK_OF_THE_DEAD); 179.     /* KMH -- Need ->known to avoid "_a_ Book of the Dead" */ 180.     book2->known = 1; 181.     if(invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) { 182. 	register struct obj *otmp; 183. 	register boolean arti1_primed = FALSE, arti2_primed = FALSE, 184. 			 arti_cursed = FALSE; 185.  186.  	if(book2->cursed) { 187. 	    pline_The("runes appear scrambled.  You can't read them!"); 188. 	    return; 189. 	}  190.   191.  	if(!u.uhave.bell || !u.uhave.menorah) { 192. 	    pline("A chill runs down your %s.", body_part(SPINE)); 193. 	    if(!u.uhave.bell) You_hear("a faint chime..."); 194. 	    if(!u.uhave.menorah) pline("Vlad's doppelganger is amused."); 195. 	    return; 196. 	}  197.   198.  	for(otmp = invent; otmp; otmp = otmp->nobj) { 199. 	    if(otmp->otyp == CANDELABRUM_OF_INVOCATION &&  200.  	       otmp->spe == 7 && otmp->lamplit) { 201. 		if(!otmp->cursed) arti1_primed = TRUE; 202. 		else arti_cursed = TRUE; 203. 	    }  204.  	    if(otmp->otyp == BELL_OF_OPENING &&  205.  	       (moves - otmp->age) < 5L) { /* you rang it recently */ 206. 		if(!otmp->cursed) arti2_primed = TRUE; 207. 		else arti_cursed = TRUE; 208. 	    }  209.  	}  210.   211.  	if(arti_cursed) { 212. 	    pline_The("invocation fails!"); 213. 	    pline("At least one of your artifacts is cursed..."); 214. 	} else if(arti1_primed && arti2_primed) { 215. 	    mkinvokearea; 216. 	    u.uevent.invoked = 1; 217. 	} else {	/* at least one artifact not prepared properly */ 218. 	    You("have a feeling that %s is amiss...", something); 219. 	    goto raise_dead; 220. 	}  221.  	return; 222.     }  223.   224.      /* when not an invocation situation */ 225.     if (book2->cursed) { 226. raise_dead: 227.  228.  	You("raised the dead!"); 229. 	/* first maybe place a dangerous adversary */ 230. 	if (!rn2(3) && ((mtmp = makemon(&mons[PM_MASTER_LICH], 231. 					u.ux, u.uy, NO_MINVENT)) != 0 || 232. 			(mtmp = makemon(&mons[PM_NALFESHNEE], 233. 					u.ux, u.uy, NO_MINVENT)) != 0)) { 234. 	    mtmp->mpeaceful = 0; 235. 	    set_malign(mtmp); 236. 	}  237.  	/* next handle the affect on things you're carrying */ 238. 	(void) unturn_dead(&youmonst); 239. 	/* last place some monsters around you */ 240. 	mm.x = u.ux; 241. 	mm.y = u.uy; 242. 	mkundead(&mm, TRUE, NO_MINVENT); 243.     } else if(book2->blessed) { 244. 	for(mtmp = fmon; mtmp; mtmp = mtmp2) { 245. 	    mtmp2 = mtmp->nmon;		/* tamedog changes chain */ 246. 	    if (DEADMONSTER(mtmp)) continue; 247.  248.  	    if (is_undead(mtmp->data) && cansee(mtmp->mx, mtmp->my)) { 249. 		mtmp->mpeaceful = TRUE; 250. 		if(sgn(mtmp->data->maligntyp) == sgn(u.ualign.type)  251.  		   && distu(mtmp->mx, mtmp->my) < 4) 252. 		    if (mtmp->mtame) { 253. 			if (mtmp->mtame < 20) 254. 			    mtmp->mtame++; 255. 		    } else 256. 			(void) tamedog(mtmp, (struct obj *)0); 257. 		else monflee(mtmp, 0, FALSE, TRUE); 258. 	    }  259.  	}  260.      } else { 261. 	switch(rn2(3)) { 262. 	case 0: 263. 	    Your("ancestors are annoyed with you!"); 264. 	    break; 265. 	case 1: 266. 	    pline_The("headstones in the cemetery begin to move!"); 267. 	    break; 268. 	default: 269. 	    pline("Oh my!  Your name appears in the book!"); 270. 	}  271.      }  272.      return; 273. }  274.   275.  STATIC_PTR int 276. learn 277. {  278.  	int i;  279. short booktype; 280. 	char splname[BUFSZ]; 281. 	boolean costly = TRUE; 282.  283.  	/* JDS: lenses give 50% faster reading; 33% smaller read time */ 284. 	if (delay && ublindf && ublindf->otyp == LENSES && rn2(2)) delay++; 285. 	if (delay) {	/* not if (delay++), so at end delay == 0 */ 286. 		delay++; 287. 		return(1); /* still busy */ 288. 	}  289.  	exercise(A_WIS, TRUE);		/* you're studying. */ 290.  	booktype = book->otyp; 291. 	if(booktype == SPE_BOOK_OF_THE_DEAD) { 292. 	    deadbook(book); 293. 	    return(0); 294. 	}  295.   296.  	Sprintf(splname, objects[booktype].oc_name_known ?  297.  			"\"%s\"" : "the \"%s\" spell",  298.  		OBJ_NAME(objects[booktype])); 299. 	for (i = 0; i < MAXSPELL; i++)  { 300. 		if (spellid(i) == booktype)  { 301. 			if (book->spestudied > MAX_SPELL_STUDY) { 302. 			    pline("This spellbook is too faint to be read any more."); 303. 			    book->otyp = booktype = SPE_BLANK_PAPER; 304. 			} else if (spellknow(i) <= 1000) { 305. 			    Your("knowledge of %s is keener.", splname); 306. 			    incrnknow(i); 307. 			    book->spestudied++; 308. 			    exercise(A_WIS,TRUE);       /* extra study */ 309. 			} else { /* 1000 < spellknow(i) <= MAX_SPELL_STUDY */ 310. 			    You("know %s quite well already.", splname); 311. 			    costly = FALSE; 312. 			}  313.  			/* make book become known even when spell is already 314. 			   known, in case amnesia made you forget the book */ 315. 			makeknown((int)booktype); 316. 			break; 317. 		} else if (spellid(i) == NO_SPELL)  { 318. 			spl_book[i].sp_id = booktype; 319. 			spl_book[i].sp_lev = objects[booktype].oc_level; 320. 			incrnknow(i); 321. 			book->spestudied++; 322. 			You(i > 0 ? "add %s to your repertoire." : "learn %s.",  323.  			    splname); 324. 			makeknown((int)booktype); 325. 			break; 326. 		}  327.  	}  328.  	if (i == MAXSPELL) impossible("Too many spells memorized!"); 329.  330.  	if (book->cursed) {	/* maybe a demon cursed it */ 331. 		cursed_book(objects[booktype].oc_level); 332. 	}  333.  	if (costly) check_unpaid(book); 334. 	book = 0; 335. 	return(0); 336. }  337.   338.  int 339. study_book(spellbook) 340. register struct obj *spellbook; 341. {  342.  	register int	 booktype = spellbook->otyp; 343. 	register boolean confused = (Confusion != 0); 344. 	boolean too_hard = FALSE; 345.  346.  	if (delay && spellbook == book &&  347.  		    /* handle the sequence: start reading, get interrupted,  348.  		       have book become erased somehow, resume reading it */  349.  		    booktype != SPE_BLANK_PAPER) { 350. 		You("continue your efforts to memorize the spell."); 351. 	} else { 352. 		/* KMH -- Simplified this code */ 353. 		if (booktype == SPE_BLANK_PAPER) { 354. 			pline("This spellbook is all blank."); 355. 			makeknown(booktype); 356. 			return(1); 357. 		}  358.  		switch (objects[booktype].oc_level) { 359. 		 case 1: 360. 		 case 2: 361. 			delay = -objects[booktype].oc_delay; 362. 			break; 363. 		 case 3: 364. 		 case 4: 365. 			delay = -(objects[booktype].oc_level - 1) * 366. 				objects[booktype].oc_delay; 367. 			break; 368. 		 case 5: 369. 		 case 6: 370. 			delay = -objects[booktype].oc_level * 371. 				objects[booktype].oc_delay; 372. 			break; 373. 		 case 7: 374. 			delay = -8 * objects[booktype].oc_delay; 375. 			break; 376. 		 default: 377. 			impossible("Unknown spellbook level %d, book %d;",  378.  				objects[booktype].oc_level, booktype); 379. 			return 0; 380. 		}  381.   382.  		/* Books are often wiser than their readers (Rus.) */ 383. 		spellbook->in_use = TRUE; 384. 		if (!spellbook->blessed &&  385.  		    spellbook->otyp != SPE_BOOK_OF_THE_DEAD) { 386. 		    if (spellbook->cursed) { 387. 			too_hard = TRUE; 388. 		    } else { 389. 			/* uncursed - chance to fail */ 390. 			int read_ability = ACURR(A_INT) + 4 + u.ulevel/2 391. 			    - 2*objects[booktype].oc_level 392. 			    + ((ublindf && ublindf->otyp == LENSES) ? 2 : 0); 393. 			/* only wizards know if a spell is too difficult */ 394. 			if (Role_if(PM_WIZARD) && read_ability < 20) { 395. 			    char qbuf[QBUFSZ]; 396. 			    Sprintf(qbuf,  397.  		      "This spellbook is %sdifficult to comprehend. Continue?",  398.  				    (read_ability < 12 ? "very " : "")); 399. 			    if (yn(qbuf) != 'y') { 400. 				spellbook->in_use = FALSE; 401. 				return(1); 402. 			    }  403.  			}  404.  			/* its up to random luck now */ 405. 			if (rnd(20) > read_ability) { 406. 			    too_hard = TRUE; 407. 			}  408.  		    }  409.  		}  410.   411.  		if (too_hard) { 412. 		    cursed_book(objects[booktype].oc_level); 413. 		    nomul(delay);			/* study time */ 414. 		    delay = 0; 415. 		    if(!rn2(3)) { 416. 			pline_The("spellbook crumbles to dust!"); 417. 			if (!objects[spellbook->otyp].oc_name_known &&  418.  				!objects[spellbook->otyp].oc_uname) 419. 			    docall(spellbook); 420. 			useup(spellbook); 421. 		    } else 422. 			spellbook->in_use = FALSE; 423. 		    return(1); 424. 		} else if (confused) { 425. 			if (!rn2(3) &&  426.  				spellbook->otyp != SPE_BOOK_OF_THE_DEAD) { 427. 			    pline(  428.  	  "Being confused you have difficulties in controlling your actions."); 429. 			    display_nhwindow(WIN_MESSAGE, FALSE); 430. 			    You("accidentally tear the spellbook to pieces."); 431. 			    if (!objects[spellbook->otyp].oc_name_known &&  432.  				   !objects[spellbook->otyp].oc_uname) 433. 				docall(spellbook); 434. 			    useup(spellbook); 435. 			} else { 436. 			    You(  437.  		  "find yourself reading the first line over and over again."); 438. 			    spellbook->in_use = FALSE; 439. 			}  440.  			nomul(delay); 441. 			delay = 0; 442. 			return(1); 443. 		}  444.  		spellbook->in_use = FALSE; 445.  446.  		You("begin to %s the runes.",  447.  		    spellbook->otyp == SPE_BOOK_OF_THE_DEAD ? "recite" :  448.  		    "memorize"); 449. 	}  450.   451.  	book = spellbook; 452. 	set_occupation(learn, "studying", 0); 453. 	return(1); 454. }  455.   456.  /* a spellbook has been destroyed or the character has changed levels; 457.    the stored address for the current book is no longer valid */ 458. void 459. book_disappears(obj) 460. struct obj *obj; 461. {  462.  	if (obj == book) book = (struct obj *)0; 463. }  464.   465.  /* renaming an object usually results in it having a different address; 466.    so the sequence start reading, get interrupted, name the book, resume 467.    reading would read the "new" book from scratch */ 468. void 469. book_substitution(old_obj, new_obj) 470. struct obj *old_obj, *new_obj; 471. {  472.  	if (old_obj == book) book = new_obj; 473. }  474.   475.  /* called from moveloop */ 476. void 477. age_spells 478. {  479.  	int i;  480. /* 481.  	 * The time relative to the hero (a pass through move  482.  	 * loop) causes all spell knowledge to be decremented. 483. 	 * The hero's speed, rest status, conscious status etc. 484. 	 * does not alter the loss of memory. 485. 	 */  486.  	for (i = 0; i < MAXSPELL && spellid(i) != NO_SPELL; i++) 487. 	    if (spellknow(i)) 488. 		decrnknow(i); 489. 	return; 490. }  491.   492.  /*  493.   * Return TRUE if a spell was picked, with the spell index in the return 494.  * parameter. Otherwise return FALSE. 495.  */  496.  STATIC_OVL boolean 497. getspell(spell_no) 498. 	int *spell_no; 499. {  500.  	int nspells, idx; 501. 	char ilet, lets[BUFSZ], qbuf[QBUFSZ]; 502.  503.  	if (spellid(0) == NO_SPELL)  { 504. 	    You("don't know any spells right now."); 505. 	    return FALSE; 506. 	}  507.  	if (flags.menu_style == MENU_TRADITIONAL) { 508. 	    /* we know there is at least 1 known spell */ 509. 	    for (nspells = 1; nspells < MAXSPELL  510.  			    && spellid(nspells) != NO_SPELL; nspells++) 511. 		continue; 512.  513.  	    if (nspells == 1)  Strcpy(lets, "a"); 514. 	    else if (nspells < 27)  Sprintf(lets, "a-%c", 'a' + nspells - 1); 515. 	    else if (nspells == 27)  Sprintf(lets, "a-zA"); 516. 	    else Sprintf(lets, "a-zA-%c", 'A' + nspells - 27); 517.  518.  	    for  { 519. 		Sprintf(qbuf, "Cast which spell? [%s ?]", lets); 520. 		if ((ilet = yn_function(qbuf, (char *)0, '\0')) == '?') 521. 		    break; 522.  523.  		if (index(quitchars, ilet)) 524. 		    return FALSE; 525.  526.  		idx = spell_let_to_idx(ilet); 527. 		if (idx >= 0 && idx < nspells) { 528. 		    *spell_no = idx; 529. 		    return TRUE; 530. 		} else 531. 		    You("don't know that spell."); 532. 	    }  533.  	}  534.  	return dospellmenu("Choose which spell to cast",  535.  			   SPELLMENU_CAST, spell_no); 536. }  537.   538.  /* the 'Z' command -- cast a spell */ 539. int 540. docast 541. {  542.  	int spell_no; 543.  544.  	if (getspell(&spell_no)) 545. 	    return spelleffects(spell_no, FALSE); 546. 	return 0; 547. }  548.   549.  STATIC_OVL const char * 550. spelltypemnemonic(skill) 551. int skill; 552. {  553.  	switch (skill) { 554. 	    case P_ATTACK_SPELL: 555. 		return "attack"; 556. 	    case P_HEALING_SPELL: 557. 		return "healing"; 558. 	    case P_DIVINATION_SPELL: 559. 		return "divination"; 560. 	    case P_ENCHANTMENT_SPELL: 561. 		return "enchantment"; 562. 	    case P_CLERIC_SPELL: 563. 		return "clerical"; 564. 	    case P_ESCAPE_SPELL: 565. 		return "escape"; 566. 	    case P_MATTER_SPELL: 567. 		return "matter"; 568. 	    default: 569. 		impossible("Unknown spell skill, %d;", skill); 570. 		return ""; 571. 	}  572.  }  573.   574.  int 575. spell_skilltype(booktype) 576. int booktype; 577. {  578.  	return (objects[booktype].oc_skill); 579. }  580.   581.  STATIC_OVL void 582. cast_protection 583. {  584.  	int loglev = 0; 585. 	int l = u.ulevel; 586. 	int natac = u.uac - u.uspellprot; 587. 	int gain; 588.  589.  	/* loglev=log2(u.ulevel)+1 (1..5) */ 590. 	while (l) { 591. 	    loglev++; 592. 	    l /= 2; 593. 	}  594.   595.  	/* The more u.uspellprot you already have, the less you get, 596. 	 * and the better your natural ac, the less you get. 597. 	 *  598.  	 *	LEVEL AC    SPELLPROT from sucessive SPE_PROTECTION casts 599. 	 *      1     10    0,  1,  2,  3,  4  600.  	 *      1      0    0,  1,  2,  3  601.  	 *      1    -10    0,  1,  2  602.  	 *      2-3   10    0,  2,  4,  5,  6,  7,  8  603.  	 *      2-3    0    0,  2,  4,  5,  6  604.  	 *      2-3  -10    0,  2,  3,  4  605.  	 *      4-7   10    0,  3,  6,  8,  9, 10, 11, 12  606.  	 *      4-7    0    0,  3,  5,  7,  8,  9  607.  	 *      4-7  -10    0,  3,  5,  6  608.  	 *      7-15 -10    0,  3,  5,  6  609.  	 *      8-15  10    0,  4,  7, 10, 12, 13, 14, 15, 16  610.  	 *      8-15   0    0,  4,  7,  9, 10, 11, 12  611.  	 *      8-15 -10    0,  4,  6,  7,  8  612.  	 *     16-30  10    0,  5,  9, 12, 14, 16, 17, 18, 19, 20  613.  	 *     16-30   0    0,  5,  9, 11, 13, 14, 15  614.  	 *     16-30 -10    0,  5,  8,  9, 10  615.  	 */  616.  	gain = loglev - (int)u.uspellprot / (4 - min(3,(10 - natac)/10)); 617.  618.  	if (gain > 0) { 619. 	    if (!Blind) { 620. 		const char *hgolden = hcolor(golden); 621.  622.  		if (u.uspellprot) 623. 		    pline_The("%s haze around you becomes more dense.",  624.  			      hgolden); 625. 		else 626. 		    pline_The("%s around you begins to shimmer with %s haze.",  627.  			/*[ what about being inside solid rock while polyd? ]*/  628.  			(Underwater || Is_waterlevel(&u.uz)) ? "water" : "air",  629.  			      an(hgolden)); 630. 	    }  631.  	    u.uspellprot += gain; 632. 	    u.uspmtime = 633. 		P_SKILL(spell_skilltype(SPE_PROTECTION)) == P_EXPERT ? 20 : 10; 634.  	    if (!u.usptime) 635. 		u.usptime = u.uspmtime; 636. 	    find_ac; 637. 	} else { 638. 	    Your("skin feels warm for a moment."); 639. 	}  640.  }  641.   642.  int 643. spelleffects(spell, atme) 644. int spell; 645. boolean atme; 646. {  647.  	int energy, damage, chance, n, intell; 648. 	int skill, role_skill; 649. 	boolean confused = (Confusion != 0); 650. 	struct obj *pseudo; 651. 	coord cc; 652.  653.  	/*  654.  	 * Spell casting no longer affects knowledge of the spell. A 655. * decrement of spell knowledge is done every turn. 656. 	 */  657.  	if (spellknow(spell) <= 0) { 658. 	    Your("knowledge of this spell is twisted."); 659. 	    pline("It invokes nightmarish images in your mind..."); 660. 	    make_confused((long)spellev(spell) * 3, FALSE); 661. 	    return(0); 662. 	} else if (spellknow(spell) <= 100) { 663. 	    You("strain to recall the spell."); 664. 	} else if (spellknow(spell) <= 1000) { 665. 	    Your("knowledge of this spell is growing faint."); 666. 	}  667.  	energy = (spellev(spell) * 5);    /* 5 <= energy <= 35 */ 668.  669.  	if (u.uhunger <= 10 && spellid(spell) != SPE_DETECT_FOOD) { 670. 		You("are too hungry to cast that spell."); 671. 		return(0); 672. 	} else if (ACURR(A_STR) < 4)  { 673. 		You("lack the strength to cast spells."); 674. 		return(0); 675. 	} else if(check_capacity( 676. 		"Your concentration falters while carrying so much stuff.")) { 677. 	    return (1); 678. 	} else if (!freehand) { 679. 		Your("arms are not free to cast!"); 680. 		return (0); 681. 	}  682.   683.  	if (u.uhave.amulet) { 684. 		You_feel("the amulet draining your energy away."); 685. 		energy += rnd(2*energy); 686. 	}  687.  	if(energy > u.uen)  { 688. 		You("don't have enough energy to cast that spell."); 689. 		return(0); 690. 	} else { 691. 		if (spellid(spell) != SPE_DETECT_FOOD) { 692. 			int hungr = energy * 2; 693.  694.  			/* If hero is a wizard, their current intelligence 695. 			 * (bonuses + temporary + current) 696. 			 * affects hunger reduction in casting a spell. 697. 			 * 1. int = 17-18 no reduction 698. 			 * 2. int = 16    1/4 hungr 699. 			 * 3. int = 15    1/2 hungr 700. 			 * 4. int = 1-14  normal reduction 701. 			 * The reason for this is: 702. 			 * a) Intelligence affects the amount of exertion  703.  			 * in thinking.  704.  			 * b) Wizards have spent their life at magic and 705. 			 * understand quite well how to cast spells. 706. 			 */  707.  			intell = acurr(A_INT); 708. 			if (!Role_if(PM_WIZARD)) intell = 10; 709. 			switch (intell) { 710. 				case 25: case 24: case 23: case 22: 711. 				case 21: case 20: case 19: case 18: 712. 				case 17: hungr = 0; break; 713. 				case 16: hungr /= 4; break; 714. 				case 15: hungr /= 2; break; 715. 			}  716.  			/* don't put player (quite) into fainting from 717. 			 * casting a spell, particularly since they might 718. 			 * not even be hungry at the beginning; however, 719. 			 * this is low enough that they must eat before 720. 			 * casting anything else except detect food 721. 			 */  722.  			if (hungr > u.uhunger-3) 723. 				hungr = u.uhunger-3; 724. 			morehungry(hungr); 725. 		}  726.  	}  727.   728.  	chance = percent_success(spell); 729. 	if (confused || (rnd(100) > chance)) { 730. 		You("fail to cast the spell correctly."); 731. 		u.uen -= energy / 2; 732. 		flags.botl = 1; 733. 		return(1); 734. 	}  735.   736.  	u.uen -= energy; 737. 	flags.botl = 1; 738. 	exercise(A_WIS, TRUE); 739. 	/* pseudo is a temporary "false" object containing the spell stats */ 740. 	pseudo = mksobj(spellid(spell), FALSE, FALSE); 741. 	pseudo->blessed = pseudo->cursed = 0; 742. 	pseudo->quan = 20L;			/* do not let useup get it */ 743. 	/*  744.  	 * Find the skill the hero has in a spell type category. 745. 	 * See spell_skilltype for categories. 746. 	 */  747.  	skill = spell_skilltype(pseudo->otyp); 748. 	role_skill = P_SKILL(skill); 749.  750.  	switch(pseudo->otyp)  { 751. 	/*  752.  	 * At first spells act as expected. As the hero increases in skill 753. 	 * with the appropriate spell type, some spells increase in their 754. 	 * effects, e.g. more damage, further distance, and so on, without 755. 	 * additional cost to the spellcaster. 756. 	 */  757.  	case SPE_CONE_OF_COLD: 758. 	case SPE_FIREBALL: 759. 	    if (role_skill >= P_SKILLED) { 760. 	        if (throwspell) { 761. 		    cc.x=u.dx;cc.y=u.dy; 762. 		    n=rnd(8)+1; 763. 		    while(n--) { 764. 			if(!u.dx && !u.dy && !u.dz) { 765. 			    if ((damage = zapyourself(pseudo, TRUE)) != 0) { 766. 				char buf[BUFSZ]; 767. 				Sprintf(buf, "zapped %sself with a spell", uhim); 768. 				losehp(damage, buf, NO_KILLER_PREFIX); 769. 			    }  770.  			} else { 771. 			    explode(u.dx, u.dy,  772.  				    pseudo->otyp - SPE_MAGIC_MISSILE + 10,  773.  				    u.ulevel/2 + 1 + spell_damage_bonus, 0,  774.  					(pseudo->otyp == SPE_CONE_OF_COLD) ?  775.  						EXPL_FROSTY : EXPL_FIERY); 776. 			}  777.  			u.dx = cc.x+rnd(3)-2; u.dy = cc.y+rnd(3)-2; 778. 			if (!isok(u.dx,u.dy) || !cansee(u.dx,u.dy) ||  779.  			    IS_STWALL(levl[u.dx][u.dy].typ) || u.uswallow) { 780. 			    /* Spell is reflected back to center */ 781. 			    u.dx = cc.x;  782. u.dy = cc.y; 783. } 784.  		    }  785.  		}  786.  		break; 787. 	    } /* else fall through... */ 788.   789.  	/* these spells are all duplicates of wand effects */ 790. 	case SPE_FORCE_BOLT: 791. 	case SPE_SLEEP: 792. 	case SPE_MAGIC_MISSILE: 793. 	case SPE_KNOCK: 794. 	case SPE_SLOW_MONSTER: 795. 	case SPE_WIZARD_LOCK: 796. 	case SPE_DIG: 797. 	case SPE_TURN_UNDEAD: 798. 	case SPE_POLYMORPH: 799. 	case SPE_TELEPORT_AWAY: 800. 	case SPE_CANCELLATION: 801. 	case SPE_FINGER_OF_DEATH: 802. 	case SPE_LIGHT: 803. 	case SPE_DETECT_UNSEEN: 804. 	case SPE_HEALING: 805. 	case SPE_EXTRA_HEALING: 806. 	case SPE_DRAIN_LIFE: 807. 	case SPE_STONE_TO_FLESH: 808. 		if (!(objects[pseudo->otyp].oc_dir == NODIR)) { 809. 			if (atme) u.dx = u.dy = u.dz = 0; 810. 			else (void) getdir((char *)0); 811. 			if(!u.dx && !u.dy && !u.dz) { 812. 			    if ((damage = zapyourself(pseudo, TRUE)) != 0) { 813. 				char buf[BUFSZ]; 814. 				Sprintf(buf, "zapped %sself with a spell", uhim); 815. 				losehp(damage, buf, NO_KILLER_PREFIX); 816. 			    }  817.  			} else weffects(pseudo); 818. 		} else weffects(pseudo); 819. 		update_inventory;	/* spell may modify inventory */ 820. 		break; 821.  822.  	/* these are all duplicates of scroll effects */ 823. 	case SPE_REMOVE_CURSE: 824. 	case SPE_CONFUSE_MONSTER: 825. 	case SPE_DETECT_FOOD: 826. 	case SPE_CAUSE_FEAR: 827. 		/* high skill yields effect equivalent to blessed scroll */ 828. 		if (role_skill >= P_SKILLED) pseudo->blessed = 1; 829. 		/* fall through */ 830. 	case SPE_CHARM_MONSTER: 831. 	case SPE_MAGIC_MAPPING: 832. 	case SPE_CREATE_MONSTER: 833. 	case SPE_IDENTIFY: 834. 		(void) seffects(pseudo); 835. 		break; 836.  837.  	/* these are all duplicates of potion effects */ 838. 	case SPE_HASTE_SELF: 839. 	case SPE_DETECT_TREASURE: 840. 	case SPE_DETECT_MONSTERS: 841. 	case SPE_LEVITATION: 842. 	case SPE_RESTORE_ABILITY: 843. 		/* high skill yields effect equivalent to blessed potion */ 844. 		if (role_skill >= P_SKILLED) pseudo->blessed = 1; 845. 		/* fall through */ 846. 	case SPE_INVISIBILITY: 847. 		(void) peffects(pseudo); 848. 		break; 849.  850.  	case SPE_CURE_BLINDNESS: 851. 		healup(0, 0, FALSE, TRUE); 852. 		break; 853. 	case SPE_CURE_SICKNESS: 854. 		if (Sick) You("are no longer ill."); 855. 		if (Slimed) { 856. 		    pline_The("slime disappears!"); 857. 		    Slimed = 0; 858. 		 /* flags.botl = 1; -- healup handles this */ 859. 		}  860.  		healup(0, 0, TRUE, FALSE); 861. 		break; 862. 	case SPE_CREATE_FAMILIAR: 863. 		(void) make_familiar((struct obj *)0, u.ux, u.uy, FALSE); 864. 		break; 865. 	case SPE_CLAIRVOYANCE: 866. 		if (!BClairvoyant) 867. 		    do_vicinity_map; 868. 		/* at present, only one thing blocks clairvoyance */ 869. 		else if (uarmh && uarmh->otyp == CORNUTHAUM) 870. 		    You("sense a pointy hat on top of your %s.",  871.  			body_part(HEAD)); 872. 		break; 873. 	case SPE_PROTECTION: 874. 		cast_protection; 875. 		break; 876. 	case SPE_JUMPING: 877. 		if (!jump(max(role_skill,1))) 878. 			pline(nothing_happens); 879. 		break; 880. 	default: 881. 		impossible("Unknown spell %d attempted.", spell); 882. 		obfree(pseudo, (struct obj *)0); 883. 		return(0); 884. 	}  885.   886.  	/* gain skill for successful cast */ 887. 	if (role_skill != P_ISRESTRICTED && role_skill < P_EXPERT) 888. 	    use_skill(skill, spellev(spell)); 889.  890.  	obfree(pseudo, (struct obj *)0);	/* now, get rid of it */ 891. 	return(1); 892. }  893.   894.  /* Choose location where spell takes effect. */ 895.  STATIC_OVL int 896. throwspell 897. {  898.  	coord cc; 899.  900.  	if (u.uinwater) { 901. 	    pline("You're joking! In this weather?"); return 0; 902. 	} else if (Is_waterlevel(&u.uz)) { 903. 	    You("had better wait for the sun to come out."); return 0; 904. 	}  905.   906.  	pline("Where do you want to cast the spell?"); 907. 	cc.x = u.ux; 908. 	cc.y = u.uy; 909. 	if (getpos(&cc, TRUE, "the desired position") < 0) 910. 	    return 0;	/* user pressed ESC */ 911. 	/* The number of moves from hero to where the spell drops.*/ 912. 	if (distmin(u.ux, u.uy, cc.x, cc.y) > 10) { 913. 	    pline_The("spell dissipates over the distance!"); 914. 	    return 0; 915. 	} else if (u.uswallow) { 916. 	    pline_The("spell is cut short!"); 917. 	    exercise(A_WIS, FALSE); /* What were you THINKING! */ 918.  	    u.dx = 0; 919. 	    u.dy = 0; 920. 	    return 1; 921. 	} else if (!cansee(cc.x, cc.y) || IS_STWALL(levl[cc.x][cc.y].typ)) { 922. 	    Your("mind fails to lock onto that location!"); 923. 	    return 0; 924. 	} else { 925. 	    u.dx=cc.x;  926. u.dy=cc.y; 927. return 1; 928. 	}  929.  }  930.   931.  void 932. losespells 933. {  934.  	boolean confused = (Confusion != 0); 935. 	int  n, nzap, i;  936. 937. 	book = 0; 938. 	for (n = 0; n < MAXSPELL && spellid(n) != NO_SPELL; n++) 939. 		continue; 940. 	if (n) { 941. 		nzap = rnd(n) + confused ? 1 : 0; 942.  		if (nzap > n) nzap = n;  943. for (i = n - nzap; i < n; i++) { 944. 		    spellid(i) = NO_SPELL; 945. 		    exercise(A_WIS, FALSE);	/* ouch! */ 946.  		}  947.  	}  948.  }  949.   950.  /* the '+' command -- view known spells */ 951. int 952. dovspell 953. {  954.  	char qbuf[QBUFSZ]; 955. 	int splnum, othnum; 956. 	struct spell spl_tmp; 957.  958.  	if (spellid(0) == NO_SPELL) 959. 	    You("don't know any spells right now."); 960. 	else { 961. 	    while (dospellmenu("Currently known spells", 962. 			       SPELLMENU_VIEW, &splnum)) { 963. 		Sprintf(qbuf, "Reordering spells; swap '%c' with",  964.  			spellet(splnum)); 965. 		if (!dospellmenu(qbuf, splnum, &othnum)) break; 966.  967.  		spl_tmp = spl_book[splnum]; 968. 		spl_book[splnum] = spl_book[othnum]; 969. 		spl_book[othnum] = spl_tmp; 970. 	    }  971.  	}  972.  	return 0; 973. }  974.   975.  STATIC_OVL boolean 976. dospellmenu(prompt, splaction, spell_no) 977. const char *prompt; 978. int splaction;	/* SPELLMENU_CAST, SPELLMENU_VIEW, or spl_book[] index */ 979. int *spell_no; 980. {  981.  	winid tmpwin; 982. 	int i, n, how; 983. 	char buf[BUFSZ]; 984. 	menu_item *selected; 985. 	anything any; 986.  987.  	tmpwin = create_nhwindow(NHW_MENU); 988. 	start_menu(tmpwin); 989. 	any.a_void = 0;		/* zero out all bits */ 990.  991.  	/*  992.  	 * The correct spacing of the columns depends on the 993. 	 * following that (1) the font is monospaced and (2) 994. 	 * that selection letters are pre-pended to the given 995. 	 * string and are of the form "a - ". 996. 	 *  997.  	 * To do it right would require that we implement columns 998. 	 * in the window-ports (say via a tab character). 999. 	 */  1000. 	if (!iflags.menu_tab_sep) 1001. 		Sprintf(buf, "%-20s    Level  %-12s Fail", "    Name", "Category"); 1002. 	else 1003. 		Sprintf(buf, "Name\tLevel\tCategory\tFail"); 1004. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED); 1005. 	for (i = 0; i < MAXSPELL && spellid(i) != NO_SPELL; i++) { 1006. 		Sprintf(buf, iflags.menu_tab_sep ? 1007. 			"%s\t%-d%s\t%s\t%-d%%" : "%-20s  %2d%s   %-12s %3d%%",  1008. 			spellname(i), spellev(i),  1009. 			spellknow(i) ? " " : "*",  1010. 			spelltypemnemonic(spell_skilltype(spellid(i))),  1011. 			100 - percent_success(i)); 1012. 1013. 		any.a_int = i+1;	/* must be non-zero */ 1014. 		add_menu(tmpwin, NO_GLYPH, &any, 1015. 			 spellet(i), 0, ATR_NONE, buf,  1016. 			 (i == splaction) ? MENU_SELECTED : MENU_UNSELECTED); 1017. 	     }  1018. 	end_menu(tmpwin, prompt); 1019. 1020. 	how = PICK_ONE; 1021. 	if (splaction == SPELLMENU_VIEW && spellid(1) == NO_SPELL) 1022. 	   how = PICK_NONE;	/* only one spell => nothing to swap with */ 1023. 	n = select_menu(tmpwin, how, &selected); 1024. 	destroy_nhwindow(tmpwin); 1025. 	if (n > 0) { 1026. 		*spell_no = selected[0].item.a_int - 1; 1027. 		/* menu selection for `PICK_ONE' does not 1028. 		  de-select any preselected entry */ 1029. 		if (n > 1 && *spell_no == splaction) 1030. 		   *spell_no = selected[1].item.a_int - 1; 1031. 		free((genericptr_t)selected); 1032. 		/* default selection of preselected spell means that 1033. 		  user chose not to swap it with anything */ 1034. 		if (*spell_no == splaction) return FALSE; 1035. 		return TRUE; 1036. 	} else if (splaction >= 0) { 1037. 	   /* explicit de-selection of preselected spell means that 1038. 	      user is still swapping but not for the current spell */ 1039. 	   *spell_no = splaction; 1040. 	   return TRUE; 1041. 	} 1042. 	return FALSE; 1043. } 1044.  1045. /* Integer square root function without using floating point. */ 1046. STATIC_OVL int 1047. isqrt(val) 1048. int val; 1049. { 1050.     int rt = 0; 1051.    int odd = 1; 1052.    while(val >= odd) { 1053. 	val = val-odd; 1054. 	odd = odd+2; 1055. 	rt = rt + 1; 1056.    }  1057.     return rt; 1058. } 1059.  1060. STATIC_OVL int 1061. percent_success(spell) 1062. int spell; 1063. { 1064. 	/* Intrinsic and learned ability are combined to calculate 1065. 	 * the probability of player's success at cast a given spell. 1066. 	 */ 1067. 	int chance, splcaster, special, statused; 1068. 	int difficulty; 1069. 	int skill; 1070. 1071. 	/* Calculate intrinsic ability (splcaster) */ 1072. 1073. 	splcaster = urole.spelbase; 1074. 	special = urole.spelheal; 1075. 	statused = ACURR(urole.spelstat); 1076. 1077. 	if (uarm && is_metallic(uarm)) 1078. 	   splcaster += (uarmc && uarmc->otyp == ROBE) ? 1079. 		urole.spelarmr/2 : urole.spelarmr; 1080. 	else if (uarmc && uarmc->otyp == ROBE) 1081. 	   splcaster -= urole.spelarmr; 1082. 	if (uarms) splcaster += urole.spelshld; 1083. 1084. 	if (uarmh && is_metallic(uarmh) && uarmh->otyp != HELM_OF_BRILLIANCE) 1085. 		splcaster += uarmhbon; 1086. 	if (uarmg && is_metallic(uarmg)) splcaster += uarmgbon; 1087. 	if (uarmf && is_metallic(uarmf)) splcaster += uarmfbon; 1088. 1089. 	if (spellid(spell) == urole.spelspec) 1090. 		splcaster += urole.spelsbon; 1091. 1092.  1093. 	/* `healing spell' bonus */ 1094. 	if (spellid(spell) == SPE_HEALING || 1095. 	    spellid(spell) == SPE_EXTRA_HEALING ||  1096. 	    spellid(spell) == SPE_CURE_BLINDNESS ||  1097. 	    spellid(spell) == SPE_CURE_SICKNESS ||  1098. 	    spellid(spell) == SPE_RESTORE_ABILITY ||  1099. 	    spellid(spell) == SPE_REMOVE_CURSE) splcaster += special; 1100. 1101. 	if (splcaster > 20) splcaster = 20; 1102. 1103. 	/* Calculate learned ability */ 1104. 1105. 	/* Players basic likelihood of being able to cast any spell 1106. 	 * is based of their `magic' statistic. (Int or Wis) 1107. 	 */ 1108. 	chance = 11 * statused / 2; 1109. 1110. 	/*  1111. 	 * High level spells are harder. Easier for higher level casters. 1112. 	 * The difficulty is based on the hero's level and their skill level 1113. 	 * in that spell type. 1114. 	 */ 1115. 	skill = P_SKILL(spell_skilltype(spellid(spell))); 1116. 	skill = max(skill,P_UNSKILLED) - 1;	/* unskilled => 0 */ 1117. 	difficulty= (spellev(spell)-1) * 4 - ((skill * 6) + (u.ulevel/3) + 1); 1118. 1119. 	if (difficulty > 0) { 1120. 		/* Player is too low level or unskilled. */ 1121. 		chance -= isqrt(900 * difficulty + 2000); 1122. 	} else { 1123. 		/* Player is above level. Learning continues, but the 1124. 		 * law of diminishing returns sets in quickly for 1125. 		 * low-level spells. That is, a player quickly gains 1126. 		 * no advantage for raising level. 1127. 		 */ 1128. 		int learning = 15 * -difficulty / spellev(spell); 1129. 		chance += learning > 20 ? 20 : learning; 1130. 	} 1131.  1132. 	/* Clamp the chance: >18 stat and advanced learning only help 1133. 	 * to a limit, while chances below "hopeless" only raise the 1134. 	 * specter of overflowing 16-bit ints (and permit wearing a 1135. 	 * shield to raise the chances :-). 1136. 	 */ 1137. 	if (chance < 0) chance = 0; 1138. 	if (chance > 120) chance = 120; 1139. 1140. 	/* Wearing anything but a light shield makes it very awkward 1141. 	 * to cast a spell. The penalty is not quite so bad for the 1142. 	 * player's role-specific spell. 1143. 	 */ 1144. 	if (uarms && weight(uarms) > (int) objects[SMALL_SHIELD].oc_weight) { 1145. 		if (spellid(spell) == urole.spelspec) { 1146. 			chance /= 2; 1147. 		} else { 1148. 			chance /= 4; 1149. 		} 1150. 	}  1151.  1152. 	/* Finally, chance (based on player intell/wisdom and level) is  1153. * combined with ability (based on player intrinsics and 1154. 	 * encumbrances). No matter how intelligent/wise and advanced 1155. 	 * a player is, intrinsics and encumbrance can prevent casting; 1156. 	 * and no matter how able, learning is always required. 1157. 	 */ 1158. 	chance = chance * (20-splcaster) / 15 - splcaster; 1159. 1160. 	/* Clamp to percentile */ 1161. 	if (chance > 100) chance = 100; 1162. 	if (chance < 0) chance = 0; 1163. 1164. 	return chance; 1165. } 1166.  1167.  1168. /* Learn a spell during creation of the initial inventory */ 1169. void 1170. initialspell(obj) 1171. struct obj *obj; 1172. { 1173. 	int i;  1174. 1175. 	for (i = 0; i < MAXSPELL; i++) { 1176. 	   if (spellid(i) == obj->otyp) { 1177. 	        pline("Error: Spell %s already known.",  1178. 	         		OBJ_NAME(objects[obj->otyp])); 1179. 	        return; 1180. 	   }  1181. 	    if (spellid(i) == NO_SPELL)  { 1182. 	       spl_book[i].sp_id = obj->otyp; 1183. 	       spl_book[i].sp_lev = objects[obj->otyp].oc_level; 1184. 	       incrnknow(i); 1185. 	       return; 1186. 	   }  1187. 	}  1188. 	impossible("Too many spells memorized!"); 1189. 	return; 1190. } 1191.  1192. /*spell.c*/