Source:NetHack 3.1.0/spell.c

Below is the full text to spell.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.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.1	92/12/10 2.   /*	Copyright (c) M. Stephenson 1988			  */ 3.   /* NetHack may be freely redistributed. See license for details. */ 4.     5.    #include "hack.h"  6. 7.   static schar NEARDATA delay;		/* moves left for this spell */ 8.   static struct obj NEARDATA *book;	/* last/current book being xscribed */ 9.    10.   #define spelluses(spell)	spl_book[spell-1].sp_uses 11.  #define decrnuses(spell)	spl_book[spell-1].sp_uses-- 12.  #define spellev(spell)		spl_book[spell-1].sp_lev 13.  #define spellname(spell)	OBJ_NAME(objects[spl_book[spell-1].sp_id]) 14.  #define spellid(spell)		spl_book[spell-1].sp_id 15.   16.   static void FDECL(cursed_book, (int)); 17.  static void FDECL(deadbook, (struct obj *)); 18.  STATIC_PTR int NDECL(learn); 19.  static int NDECL(getspell); 20.  static char FDECL(spellet, (int)); 21.  static char NDECL(dospellmenu); 22.   23.   static void 24.  cursed_book(lev) 25.  	register int	lev; 26.  {  27.   	switch(rn2(lev)) { 28.  	case 0: 29.  		You("feel a wrenching sensation."); 30.  		tele;		/* teleport him */ 31.  		break; 32.  	case 1: 33.  		You("feel threatened."); 34.  		aggravate; 35.  		break; 36.  	case 2: 37.  		make_blinded(Blinded + rn1(100,250),TRUE); 38.  		break; 39.  	case 3: 40.  		take_gold; 41.  		break; 42.  	case 4: 43.  		pline("These runes were just too much to comprehend."); 44.  		make_confused(HConfusion + rn1(7,16),FALSE); 45.  		break; 46.  	case 5: 47.  		pline("The book was coated with contact poison!"); 48.  		if (uarmg) { 49.  		    /* Note: at this writing, there are no corrodeable 50.  		     * gloves in the game. If no one plans on adding 51.  		     * copper gauntlets, most of this could be removed. -3. 52.   		     */  53.   		    if (uarmg->oerodeproof || !is_corrodeable(uarmg)) { 54.  			Your("gloves seem unaffected."); 55.  		    } else if (uarmg->oeroded < MAX_ERODE) { 56.  			Your("gloves corrode%s!",  57.   			     uarmg->oeroded+1 == MAX_ERODE ? " completely" :  58.   			     uarmg->oeroded ? " further" : ""); 59.  			uarmg->oeroded++; 60.  		    } else 61.  			Your("gloves %s completely corroded.",  62.   			     Blind ? "feel" : "look"); 63.  		    break; 64.  		}  65.   		if(Poison_resistance) { 66.  		    losestr(rn1(1,2)); 67.  		    losehp(rnd(6), "contact-poisoned spellbook", KILLED_BY_AN); 68.  		} else { 69.  		    losestr(rn1(4,3)); 70.  		    losehp(rnd(10), "contact-poisoned spellbook", KILLED_BY_AN); 71.  		}  72.   		break; 73.  	case 6: 74.  		if(Antimagic) { 75.  		    shieldeff(u.ux, u.uy); 76.  		    pline("The book explodes, but you are unharmed!"); 77.  		} else { 78.  		    pline("As you read the book, it explodes in your %s!",  79.   			body_part(FACE)); 80.  		    losehp (2*rnd(10)+5, "exploding rune", KILLED_BY_AN); 81.  		}  82.   		break; 83.  	default: 84.  		rndcurse; 85.  		break; 86.  	}  87.   	return; 88.  }  89.    90.   /* special effects for The Book of the Dead */ 91.  static void 92.  deadbook(book2) 93.  struct obj *book2; 94.  {  95.       if(invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) { 96.  	register struct obj *otmp; 97.  	register boolean arti1_primed = FALSE, arti2_primed = FALSE, 98.  			 arti_cursed = FALSE; 99.   100.  	if(book2->cursed) { 101. 	    pline("The runes appear scrambled.  You can't read them!"); 102. 	    return; 103. 	}  104.   105.  	if(!u.uhave.bell || !u.uhave.menorah) { 106. 	    pline("A chill runs down your spine."); 107. 	    if(!u.uhave.bell) You("hear a faint chime..."); 108. 	    if(!u.uhave.menorah) pline("Vlad's doppelganger is amused."); 109. 	    return; 110. 	}  111.   112.  	for(otmp = invent; otmp; otmp = otmp->nobj) { 113. 	    if(otmp->otyp == CANDELABRUM_OF_INVOCATION &&  114.  	       otmp->spe == 7 && otmp->lamplit) { 115. 		if(!otmp->cursed) arti1_primed = TRUE; 116. 		else arti_cursed = TRUE; 117. 	    }  118.  	    if(otmp->otyp == BELL_OF_OPENING &&  119.  	       (moves - otmp->age) < 5L) { /* you rang it recently */ 120. 		if(!otmp->cursed) arti2_primed = TRUE; 121. 		else arti_cursed = TRUE; 122. 	    }  123.  	}  124.   125.  	if(arti_cursed) { 126. 	    pline("The invocation fails!"); 127. 	    pline("At least one of your artifacts is cursed..."); 128. 	} else if(arti1_primed && arti2_primed) { 129. 	    mkinvokearea; 130. 	    u.uevent.invoked = 1; 131. 	} else {	/* at least one artifact not prepared properly */ 132. 	    You("have a feeling that something is amiss..."); 133. 	    goto raise_dead; 134. 	}  135.  	return; 136.     }  137.   138.      /* when not an invocation situation */ 139.     if(book2->cursed) 140. raise_dead: 141.     {  142.  	register struct monst *mtmp; 143. 	coord mm; 144.  145.  	You("raised the dead!"); 146. 	mm.x = u.ux; 147. 	mm.y = u.uy; 148. 	mkundead(&mm); 149. 	if(!rn2(4)) 150. 	    if(mtmp = makemon(&mons[PM_MASTER_LICH],u.ux,u.uy)) { 151. 		mtmp->mpeaceful = 0; 152. 		set_malign(mtmp); 153. 	    }  154.      } else if(book2->blessed) { 155. 	register struct monst *mtmp, *mtmp2; 156.  157.  	for(mtmp = fmon; mtmp; mtmp = mtmp2) { 158. 	    mtmp2 = mtmp->nmon;		/* tamedog changes chain */ 159. 	    if(is_undead(mtmp->data) && cansee(mtmp->mx, mtmp->my)) { 160. 		mtmp->mpeaceful = TRUE; 161. 		if(sgn(mtmp->data->maligntyp) == sgn(u.ualign.type)  162.  		   && distu(mtmp->mx, mtmp->my) < 4) 163. 		    if (mtmp->mtame) 164. 			mtmp->mtame++; 165. 		    else 166. 			(void) tamedog(mtmp, (struct obj *)0); 167. 		else mtmp->mflee = TRUE; 168. 	    }  169.  	}  170.      } else { 171. 	switch(rn2(3)) { 172. 	case 0: 173. 	    Your("ancestors are annoyed with you!"); 174. 	    break; 175. 	case 1: 176. 	    pline("The headstones in the cemetery begin to move!"); 177. 	    break; 178. 	default: 179. 	    pline("Oh my!  Your name appears in the book!"); 180. 	}  181.      }  182.      return; 183. }  184.   185.  STATIC_PTR 186. int 187. learn 188. {  189.  	register int	i; 190. 	register unsigned booktype; 191.  192.  	if (delay) {	/* not if (delay++), so at end delay == 0 */ 193. 		delay++; 194. 		return(1); /* still busy */ 195. 	}  196.  	exercise(A_WIS, TRUE);		/* you're studying. */ 197.  	booktype = book->otyp; 198. 	if(booktype == SPE_BOOK_OF_THE_DEAD) { 199. 	    deadbook(book); 200. 	    return(0); 201. 	}  202.   203.  	for (i = 0; i < MAXSPELL; i++)  { 204. 		if (spl_book[i].sp_id == booktype)  { 205. 			if (book->spestudied >= rn1(1,8-spl_book[i].sp_lev)) { 206. 			    pline("This spellbook is too faint to be read anymore."); 207. 			    book->otyp = booktype = SPE_BLANK_PAPER; 208. 			    makeknown((int)booktype); 209. 			}  210.  			else if (spl_book[i].sp_uses < 11-spl_book[i].sp_lev) { 211. 			    Your("knowledge of that spell is keener."); 212. 			    spl_book[i].sp_uses += rn1(1,9-spl_book[i].sp_lev); 213. 			    book->spestudied++; 214. 			    exercise(A_WIS, TRUE);	/* extra study */ 215. 			} else 216. 			    You("know that spell quite well already."); 217. 			break; 218. 		} else if (spl_book[i].sp_id == NO_SPELL)  { 219. 			spl_book[i].sp_id = booktype; 220. 			spl_book[i].sp_lev = objects[booktype].oc_level; 221. 			/* spells have 1 .. 9-level uses. */ 222.  			/* ie 1 or 2 uses w/ most potent */ 223. 			spl_book[i].sp_uses = rn1(1,9-spl_book[i].sp_lev); 224. 			book->spestudied++; 225. 			You("add the spell to your repertoire."); 226. 			makeknown((int)booktype); 227. 			break; 228. 		}  229.  	}  230.  	if (i == MAXSPELL) impossible("Too many spells memorized!"); 231.  232.  	if (book->cursed) {	/* maybe a demon cursed it */ 233. 		cursed_book(objects[booktype].oc_level); 234. 	}  235.          check_unpaid(book); 236. 	book = 0; 237. 	return(0); 238. }  239.   240.  int 241. study_book(spellbook) 242. register struct obj *spellbook; 243. {  244.  	register int	 booktype = spellbook->otyp; 245. 	register boolean confused = (Confusion != 0); 246.  247.  	if (delay && spellbook == book) 248. 		You("continue your efforts to memorize the spell."); 249. 	else { 250. 		switch(booktype)  { 251.  252.  /* blank spellbook */ 253. 	case SPE_BLANK_PAPER: 254. 		pline("This spellbook is all blank."); 255. 		makeknown(SPE_BLANK_PAPER); 256. 		return(1); 257. /* level 1 spells */ 258. 	case SPE_HEALING: 259. 	case SPE_DETECT_MONSTERS: 260. 	case SPE_FORCE_BOLT: 261. 	case SPE_LIGHT: 262. 	case SPE_SLEEP: 263. 	case SPE_KNOCK: 264. /* level 2 spells */ 265. 	case SPE_MAGIC_MISSILE: 266. 	case SPE_CONFUSE_MONSTER: 267. 	case SPE_SLOW_MONSTER: 268. 	case SPE_CURE_BLINDNESS: 269. 	case SPE_CREATE_MONSTER: 270. 	case SPE_DETECT_FOOD: 271. 	case SPE_WIZARD_LOCK: 272. 		delay = -objects[booktype].oc_delay; 273. 		break; 274. /* level 3 spells */ 275. 	case SPE_HASTE_SELF: 276. 	case SPE_CAUSE_FEAR: 277. 	case SPE_CURE_SICKNESS: 278. 	case SPE_DETECT_UNSEEN: 279. 	case SPE_EXTRA_HEALING: 280. 	case SPE_CHARM_MONSTER: 281. 	case SPE_CLAIRVOYANCE: 282. /* level 4 spells */ 283. 	case SPE_LEVITATION: 284. 	case SPE_RESTORE_ABILITY: 285. 	case SPE_INVISIBILITY: 286. 	case SPE_FIREBALL: 287. 	case SPE_DETECT_TREASURE: 288. 		delay = -(objects[booktype].oc_level - 1) * objects[booktype].oc_delay; 289. 		break; 290. /* level 5 spells */ 291. 	case SPE_REMOVE_CURSE: 292. 	case SPE_MAGIC_MAPPING: 293. 	case SPE_CONE_OF_COLD: 294. 	case SPE_IDENTIFY: 295. 	case SPE_DIG: 296. /* level 6 spells */ 297. 	case SPE_TURN_UNDEAD: 298. 	case SPE_POLYMORPH: 299. 	case SPE_CREATE_FAMILIAR: 300. 	case SPE_TELEPORT_AWAY: 301. 		delay = -objects[booktype].oc_level * objects[booktype].oc_delay; 302. 		break; 303. /* level 7 spells */ 304. 	case SPE_CANCELLATION: 305. 	case SPE_FINGER_OF_DEATH: 306. 	case SPE_BOOK_OF_THE_DEAD: 307. 		delay = -8 * objects[booktype].oc_delay; 308. 		break; 309. /* impossible */ 310. 	default: 311. 		impossible("Unknown spellbook, %d;", booktype); 312. 		return(0); 313. 	}  314.   315.  		/* Books are often wiser than their readers (Rus.) */ 316. 		if(!spellbook->blessed &&  317.  		        spellbook->otyp != SPE_BOOK_OF_THE_DEAD &&  318.  			(spellbook->cursed || 319. 			    rn2(20) > (ACURR(A_INT) + 4 + (int)(u.ulevel/2)  320.  					- 2*objects[booktype].oc_level))) { 321. 			cursed_book(objects[booktype].oc_level); 322. 			nomul(delay);			/* study time */ 323. 			delay = 0; 324. 			if(!rn2(3)) { 325. 				useup(spellbook); 326. 				pline("The spellbook crumbles to dust!"); 327. 			}  328.  			return(1); 329. 		}  330.  		else if(confused) { 331. 			if(!rn2(3) &&  332.  			    spellbook->otyp != SPE_BOOK_OF_THE_DEAD) { 333. 				useup(spellbook); 334. 				pline("Being confused you have difficulties in controlling your actions."); 335. 				display_nhwindow(WIN_MESSAGE, FALSE); 336. 				You("accidentally tear the spellbook to pieces."); 337. 			}  338.  			else 339. 				You("find yourself reading the first line over and over again."); 340. 			nomul(delay); 341. 			delay = 0; 342. 			return(1); 343. 		}  344.   345.  		You("begin to %s the runes.",  346.  		    spellbook->otyp == SPE_BOOK_OF_THE_DEAD ? "recite" :  347.  		    "memorize"); 348. 	}  349.   350.  	book = spellbook; 351. 	set_occupation(learn, "studying", 0); 352. 	return(1); 353. }  354.   355.  static int 356. getspell 357. {  358.  	register int	maxs, ilet, i;  359. char	 lets[BUFSZ], buf[BUFSZ], qbuf[QBUFSZ]; 360.  361.  	if (spl_book[0].sp_id == NO_SPELL)  { 362.  363.  		You("don't know any spells right now."); 364. 		return(0); 365. 	} else  { 366.  367.  	    for(maxs = 1; (maxs < MAXSPELL) && (spl_book[maxs].sp_id != NO_SPELL); maxs++); 368. 	    if (maxs >= MAXSPELL)  { 369.  370.  		impossible("Too many spells memorized."); 371. 		return(0); 372. 	    }  373.   374.  	    for(i = 0; (i < maxs) && (i < 26); buf[++i] = 0)  buf[i] = 'a' + i;  375. for(i = 26; (i < maxs) && (i < 52); buf[++i] = 0) buf[i] = 'A' + i - 26; 376.  377.  	    if (maxs == 1)  Strcpy(lets, "a"); 378. 	    else if (maxs < 27)  Sprintf(lets, "a-%c", 'a' + maxs - 1); 379. 	    else if (maxs == 27)  Sprintf(lets, "a-z A"); 380. 	    else Sprintf(lets, "a-z A-%c", 'A' + maxs - 27); 381. 	    for  { 382.  383.  		Sprintf(qbuf, "Cast which spell? [%s ?]", lets); 384. 		if ((ilet = yn_function(qbuf, NULL, '\0')) == '?') { 385. 			ilet = dospellmenu; 386. 			if(!ilet) 387. 			    continue; 388. 		}  389.  		if (index(quitchars, ilet)) 390. 			return(0); 391. 		else for(i = 0; buf[i] != 0; i++) 392. 		    if(ilet == buf[i])  return(++i); 393. 		You("don't know that spell."); 394. 	    }  395.  	}  396.  }  397.   398.  int 399. docast 400. {  401.  	register int	 spell; 402.  403.  	spell = getspell; 404. 	if (!spell) return(0); 405.  406.  	return(spelleffects(spell,FALSE)); 407. }  408.   409.  int 410. spelleffects(spell,atme) 411. register int spell; 412. boolean atme; 413. {  414.  	register int energy, damage; 415. 	boolean confused = (Confusion != 0); 416. 	struct obj *pseudo; 417.  418.  	/* note that trying to cast it decrements the # of uses,    */ 419. 	/* even if the mage does not have enough food/energy to use */ 420. 	/* the spell */ 421. 	switch (spelluses(spell)) { 422. 		case 0: 423. 		    pline ("Curdled magical energy twists through you..."); 424. 		    pline ("...you have overloaded and burned out this spell."); 425. 		    make_confused((long)spellev(spell) * 3, FALSE); 426. 		    return(0); 427. 		case 1: 428. 		    Your("nerves tingle warningly."); 429. 		    break; 430. 		case 2: 431. 		    pline ("This spell is starting to be over-used."); 432. 		    break; 433. 		default: 434. 		    break; 435. 	}  436.  	decrnuses(spell); 437. 	energy = spellev(spell) * 7 / 2 - 2;    /* 1 <= energy <= 22 */ 438. 	if (u.uhunger <= 100 && spell != SPE_DETECT_FOOD) { 439. 		You("are too hungry to cast that spell."); 440. 		return(0); 441. 	} else if (ACURR(A_STR) < 6)  { 442. 		You("lack the strength to cast spells."); 443. 		return(0); 444. 	} else if(check_capacity( 445. 		"Your concentration falters while carrying so much stuff.")) { 446. 	    return (1); 447. 	}  448.   449.  	if (u.uhave.amulet) { 450. 		You("feel the amulet draining your energy away."); 451. 		energy *= rnd(3); 452. 	}  453.  	if(energy > u.uen)  { 454. 		You("don't have enough energy to cast that spell."); 455. 		return(0); 456. 	} else { 457. 		if (spell != SPE_DETECT_FOOD) 458. 			morehungry(energy * 10); 459. 		u.uen -= energy; 460. 	}  461.  	flags.botl = 1; 462.  463.  	if (confused ||  464.  	    ((int)(ACURR(A_INT) + Luck) - 3 * spellev(spell)) < 0) { 465.  466.  		if (Hallucination) 467. 			pline("Far out... a light show!"); 468. 		else	pline("The air around you crackles as you goof up."); 469. 		return(0); 470. 	}  471.  	exercise(A_WIS, TRUE); 472. /*	pseudo is a temporary "false" object containing the spell stats. */ 473.  	pseudo = mksobj(spellid(spell), FALSE, FALSE); 474. 	pseudo->blessed = pseudo->cursed = 0; 475. 	pseudo->quan = 20L;			/* do not let useup get it */ 476. 	switch(pseudo->otyp)  { 477.  478.  /* These spells are all duplicates of wand effects */ 479. 	case SPE_FORCE_BOLT: 480. 	case SPE_SLEEP: 481. 	case SPE_MAGIC_MISSILE: 482. 	case SPE_KNOCK: 483. 	case SPE_SLOW_MONSTER: 484. 	case SPE_WIZARD_LOCK: 485. 	case SPE_FIREBALL: 486. 	case SPE_CONE_OF_COLD: 487. 	case SPE_DIG: 488. 	case SPE_TURN_UNDEAD: 489. 	case SPE_POLYMORPH: 490. 	case SPE_TELEPORT_AWAY: 491. 	case SPE_CANCELLATION: 492. 	case SPE_FINGER_OF_DEATH: 493. 	case SPE_LIGHT: 494. 	case SPE_DETECT_UNSEEN: 495. 		if (!(objects[pseudo->otyp].oc_dir == NODIR)) { 496. 			if (atme) u.dx = u.dy = u.dz = 0; 497. 			else (void) getdir(NULL); 498. 			if(!u.dx && !u.dy && !u.dz) { 499. 			    if((damage = zapyourself(pseudo))) 500. 				losehp(damage,  501.  		self_pronoun("zapped %sself with a spell", "him"),  502.  					NO_KILLER_PREFIX); 503. 			} else	weffects(pseudo); 504. 		} else weffects(pseudo); 505. 		break; 506. /* These are all duplicates of scroll effects */ 507. 	case SPE_CONFUSE_MONSTER: 508. 	case SPE_DETECT_FOOD: 509. 	case SPE_CAUSE_FEAR: 510. 	case SPE_CHARM_MONSTER: 511. 	case SPE_REMOVE_CURSE: 512. 	case SPE_MAGIC_MAPPING: 513. 	case SPE_CREATE_MONSTER: 514. 	case SPE_IDENTIFY: 515. 		(void) seffects(pseudo); 516. 		break; 517. 	case SPE_HASTE_SELF: 518. 	case SPE_DETECT_TREASURE: 519. 	case SPE_DETECT_MONSTERS: 520. 	case SPE_LEVITATION: 521. 	case SPE_RESTORE_ABILITY: 522. 	case SPE_INVISIBILITY: 523. 		(void) peffects(pseudo); 524. 		break; 525. 	case SPE_HEALING: 526. 		You("feel a bit better."); 527. 		healup(rnd(8), 0, FALSE, FALSE); 528. 		break; 529. 	case SPE_CURE_BLINDNESS: 530. 		healup(0, 0, FALSE, TRUE); 531. 		break; 532. 	case SPE_CURE_SICKNESS: 533. 		if (Sick) You("are no longer ill."); 534. 		healup(0, 0, TRUE, FALSE); 535. 		break; 536. 	case SPE_EXTRA_HEALING: 537. 		You("feel a fair bit better."); 538. 		healup(d(2,8)+2, 0, FALSE, FALSE); 539. 		break; 540. 	case SPE_CREATE_FAMILIAR: 541. 		make_familiar((struct obj *)0, u.ux, u.uy); 542. 		break; 543. 	case SPE_CLAIRVOYANCE: 544. 		do_vicinity_map; 545. 		break; 546. 	default: 547. 		impossible("Unknown spell %d attempted.", spell); 548. 		obfree(pseudo, (struct obj *)0); 549. 		return(0); 550. 	}  551.  	obfree(pseudo, (struct obj *)0);	/* now, get rid of it */ 552. 	return(1); 553. }  554.   555.  void 556. losespells { 557. 	register boolean confused = (Confusion != 0); 558. 	register int	 n, nzap, i;  559. 560. 	book = 0; 561. 	for(n = 0;(spl_book[n].sp_id != NO_SPELL) && (n < MAXSPELL); n++); 562. 	if (!n) return; 563. 	if (n < MAXSPELL) { 564. 		nzap = rnd(n); 565. 		if (nzap < n) nzap += confused; 566. 		for (i = 0; i < nzap; i++) { 567. 		    spl_book[n-i-1].sp_id = NO_SPELL; 568. 		    exercise(A_WIS, FALSE);	/* ouch! */ 569.  		}  570.  	} else impossible("Too many spells memorized!"); 571. 	return; 572. }  573.   574.  static char 575. spellet(spl) 576. int spl; 577. {  578.  	return (spl < 27) ? ('a' + spl - 1) : ('A' + spl - 27); 579. }  580.   581.  int 582. dovspell 583. {  584.      (void) dospellmenu; 585.     return 0; 586. }  587.   588.  static char 589. dospellmenu 590. {  591.  	winid tmpwin; 592. 	register int maxs, i;  593. char rval; 594. 	char     buf[BUFSZ]; 595.  596.  	if (spl_book[0].sp_id == NO_SPELL)  { 597.  598.  		You("don't know any spells right now."); 599. 		return 0; 600. 	}  601.   602.  	for(maxs = 1; (maxs < MAXSPELL) && (spl_book[maxs].sp_id != NO_SPELL); maxs++); 603. 	if (maxs >= MAXSPELL)  { 604.  605.  		impossible("Too many spells memorized."); 606. 		return 0; 607. 	}  608.  	tmpwin = create_nhwindow(NHW_MENU); 609. 	start_menu(tmpwin); 610. 	add_menu(tmpwin, 0, 0, "Currently known spells:"); 611. 	add_menu(tmpwin, 0, 0, ""); 612.  613.  	for(i = 1; i <= maxs; i++) { 614. 		Sprintf(buf, "%c %c %s (%d)",  615.  			spellet(i), (spelluses(i)) ? '-' : '*',  616.  			spellname(i), spellev(i)); 617. 		add_menu(tmpwin, spellet(i), 0, buf); 618.   	}  619.  	end_menu(tmpwin, '\0', "\033 ", NULL); 620. 	rval = select_menu(tmpwin); 621. 	destroy_nhwindow(tmpwin); 622.  623.  	return rval; 624. }  625.   626.  /*spell.c*/