Source:NetHack 3.3.0/read.c

Below is the full text to read.c from the source code of NetHack 3.3.0. To link to a particular line, write [[NetHack 3.3.0/read.c#line123 ]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

1.   /*	SCCS Id: @(#)read.c	3.3	1999/11/29	*/ 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.     5.    #include "hack.h"  6. 7.   /* KMH -- Copied from pray.c; this really belongs in a header file */ 8.   #define DEVOUT 14 9.   #define STRIDENT 4 10.   11.   #define Your_Own_Role(mndx) \ 12.  	((mndx) == urole.malenum || \  13.   	 (urole.femalenum != NON_PM && (mndx) == urole.femalenum)) 14.  #define Your_Own_Race(mndx) \ 15.  	((mndx) == urace.malenum || \  16.   	 (urace.femalenum != NON_PM && (mndx) == urace.femalenum)) 17.   18.   #ifdef OVLB 19.   20.   /* elven armor vibrates warningly when enchanted beyond a limit */ 21.  #define is_elven_armor(optr)	((optr)->otyp == ELVEN_LEATHER_HELM\  22.   				|| (optr)->otyp == ELVEN_MITHRIL_COAT\  23.   				|| (optr)->otyp == ELVEN_CLOAK\  24.   				|| (optr)->otyp == ELVEN_SHIELD\  25.   				|| (optr)->otyp == ELVEN_BOOTS) 26.   27.   boolean	known; 28.   29.   static NEARDATA const char readable[] = 30.  		   { ALL_CLASSES, SCROLL_CLASS, SPBOOK_CLASS, 0 }; 31.  static const char all_count[] = { ALLOW_COUNT, ALL_CLASSES, 0 }; 32.   33.   static void FDECL(read_grave, (int)); 34.  static void FDECL(wand_explode, (struct obj *)); 35.  static void NDECL(do_class_genocide); 36.  static void FDECL(stripspe,(struct obj *)); 37.  static void FDECL(p_glow1,(struct obj *)); 38.  static void FDECL(p_glow2,(struct obj *,const char *)); 39.  static void FDECL(randomize,(int *, int)); 40.  static void FDECL(forget_single_object, (int)); 41.  static void FDECL(forget, (int)); 42.   43.   STATIC_PTR void FDECL(set_lit, (int,int,genericptr_t)); 44.   45.   int 46.  doread 47.  {  48.   	register struct obj *scroll; 49.  	register boolean confused; 50.   51.    52.   	if (IS_GRAVE(levl[u.ux][u.uy].typ) && !Levitation) { 53.  	    if(yn("Read the headstone?") == 'y') { 54.  	    	/* KMH, conduct */ 55.  	    	u.uconduct.literate++; 56.  	    	read_grave(u.ux + u.uy + urole.name.m[0]); 57.  	    	return 1; 58.  	    }  59.   	}  60.    61.   	known = FALSE; 62.  	if(check_capacity((char *)0)) return (0); 63.  	scroll = getobj(readable, "read"); 64.  	if(!scroll) return(0); 65.   66.   	/* outrumor has its own blindness check */ 67.  	if(scroll->otyp == FORTUNE_COOKIE) { 68.  	    if(flags.verbose) 69.  		You("break up the cookie and throw away the pieces."); 70.  	    outrumor(bcsign(scroll), BY_COOKIE); 71.  	    if (!Blind) u.uconduct.literate++; 72.  	    useup(scroll); 73.  	    return(1); 74.  #ifdef TOURIST 75.  	} else if (scroll->otyp == T_SHIRT) { 76.  	    char buf[BUFSZ]; 77.  	    int erosion; 78.   79.   	    if (Blind) { 80.  		You_cant("feel any Braille writing."); 81.  		return 0; 82.  	    }  83.   	    u.uconduct.literate++; 84.  	    if(flags.verbose) 85.  		pline("It reads:"); 86.  	    Sprintf(buf,  "I explored the Dungeons of Doom, %s.",  87.   		    Hallucination ?  88.   			(scroll == uarmu ? 89.  			    /* (force these two to have identical length) */ 90.  			    "and never did any laundry..." : 91.   			    "and couldn't find my way out") :  92.   			"but all I got was this lousy T-shirt"); 93.  	    erosion = greatest_erosion(scroll); 94.  	    if (erosion) 95.  		wipeout_text(buf,  96.   			(int)(strlen(buf) * erosion / (2*MAX_ERODE)),  97.   			     scroll->o_id ^ (unsigned)u.ubirthday); 98.  	    pline("\"%s\"", buf); 99.  	    return 1; 100. #endif	/* TOURIST */ 101. 	} else if (scroll->oclass != SCROLL_CLASS  102.  		&& scroll->oclass != SPBOOK_CLASS) { 103. 	    pline(silly_thing_to, "read"); 104. 	    return(0); 105. 	} else if (Blind) { 106. 	    const char *what = 0; 107. 	    if (scroll->oclass == SPBOOK_CLASS) 108. 		what = "mystic runes"; 109. 	    else if (!scroll->dknown) 110. 		what = "formula on the scroll"; 111. 	    if (what) { 112. 		pline("Being blind, you cannot read the %s.", what); 113. 		return(0); 114. 	    }  115.  	}  116.   117.  	/* KMH, conduct */ 118. 	if (scroll->otyp != SPE_BOOK_OF_THE_DEAD) 119. 	    u.uconduct.literate++; 120.  121.  	confused = (Confusion != 0); 122. #ifdef MAIL 123. 	if (scroll->otyp == SCR_MAIL) confused = FALSE; 124. #endif 125. 	if(scroll->oclass == SPBOOK_CLASS) { 126. 	    if(confused) { 127. 		You("cannot grasp the meaning of this tome."); 128. 		return(0); 129. 	    } else 130. 		return(study_book(scroll)); 131. 	}  132.  	scroll->in_use = TRUE;	/* scroll, not spellbook, now being read */ 133. 	if(scroll->otyp != SCR_BLANK_PAPER) { 134. 	  if(Blind) 135. 	    pline("As you pronounce the formula on it, the scroll disappears."); 136. 	  else 137. 	    pline("As you read the scroll, it disappears."); 138. 	  if(confused) { 139. 	    if (Hallucination) 140. 		pline("Being so trippy, you screw up..."); 141. 	    else 142. 		pline("Being confused, you mispronounce the magic words..."); 143. 	  }  144.  	}  145.  	if(!seffects(scroll))  { 146. 		if(!objects[scroll->otyp].oc_name_known) { 147. 		    if(known) { 148. 			makeknown(scroll->otyp); 149. 			more_experienced(0,10); 150. 		    } else if(!objects[scroll->otyp].oc_uname) 151. 			docall(scroll); 152. 		}  153.  		if(scroll->otyp != SCR_BLANK_PAPER) 154. 			useup(scroll); 155. 		else scroll->in_use = FALSE; 156. 	}  157.  	return(1); 158. }  159.   160.  static void 161. read_grave (inscription) 162. 	int inscription; 163. {  164.  	const char *epitaph; 165.  166.   167.  #define EPITAPHS 25 168. 	switch (inscription % EPITAPHS) { 169. 		case 0: epitaph = "Note -- there are NO valuable items in this grave."; 170. 		break; 171. 		case 1: epitaph = "1994-1995. The Longest-Lived Hacker Ever."; 172. 		break; 173. 		case 2: epitaph = "The Grave of the Unknown Hacker."; 174. 		break; 175. 		case 3: 176. 		case 4: 177. 		case 5: epitaph = "R.I.P."; 178. 		break; 179. 		case 6: epitaph = "Rest In Pieces."; 180. 		break; 181. 		case 7: epitaph = "We weren't sure who this was, but we buried him here anyway."; 182. 		break; 183. 		case 8: epitaph = "Sparky -- he was a very good dog."; 184. 		break; 185. 		case 9: epitaph = "Beware of Electric Third Rail."; 186. 		break; 187. 		case 10: epitaph = "Made in Taiwan."; 188. 		break; 189. 		case 11: epitaph = "Og friend. Og good dude. Og died. Og now food."; 190. 		break; 191. 		case 12: epitaph = "Beetlejuice Beetlejuice Beetlejuice"; 192. 		break; 193. 		case 13: epitaph = "Look out below!"; 194. 		break; 195. 		case 14: epitaph = "Please don't dig me up. I'm perfectly happy down here. -- Resident"; 196. 		break; 197. 		case 15: epitaph = "Postman, please note forwarding address: Gehennom, Asmodeus's Fortress, fifth lemure on the left."; 198. 		break; 199. 		case 16: epitaph = "This old man, he played one, he played knick-knack on my thumb."; 200. 		break; 201. 		case 17: epitaph = "Mary had a little lamb, its fleece was white as snow. When Mary was in trouble here, the lamb was first to go."; 202. 		break; 203. 		case 18: epitaph = "Be careful, or this could happen to you! -- occupant"; 204. 		break; 205. 		case 19: epitaph = "Soon you'll join this fellow in hell! -- the Wizard of Yendor"; 206. 		break; 207. 		case 20: epitaph = "Caution! This grave contains toxic waste."; 208. 		break; 209. 		case 21: epitaph = "Go away!"; 210. 		break; 211. 		case 22: epitaph = "Saved by the bell."; 212. 		break; 213. 		case 23: 214. 		case 24: 215. 		default: 216. 		pline("It is blank..."); 217. 		return; 218. 	}  219.  	/* Headstones are engraved, so you can read them while blind */ 220. 	pline("It reads:"); 221. 	pline(epitaph); 222. }  223.   224.   225.  static void 226. stripspe(obj) 227. register struct obj *obj; 228. {  229.  	if (obj->blessed) pline(nothing_happens); 230. 	else { 231. 		if (obj->spe > 0) { 232. 		    obj->spe = 0; 233. 		    if (obj->otyp == OIL_LAMP || obj->otyp == BRASS_LANTERN) 234. 			obj->age = 0; 235. 		    Your("%s vibrates briefly.",xname(obj)); 236. 		} else pline(nothing_happens); 237. 	}  238.  }  239.   240.  static void 241. p_glow1(otmp) 242. register struct obj	*otmp; 243. {  244.  	Your("%s %s briefly.", xname(otmp),  245.  		Blind ? "vibrates" : "glows"); 246. }  247.   248.  static void 249. p_glow2(otmp,color) 250. register struct obj	*otmp; 251. register const char *color; 252. {  253.  	Your("%s %s%s for a moment.",  254.  		xname(otmp),  255.  		Blind ? "vibrates" : "glows ",  256.  		Blind ? (const char *)"" : hcolor(color)); 257. }  258.   259.  /* Is the object chargeable? For purposes of inventory display; it is */ 260. /* possible to be able to charge things for which this returns FALSE. */ 261.  boolean 262. is_chargeable(obj) 263. struct obj *obj; 264. {  265.  	if (obj->oclass == WAND_CLASS) return TRUE; 266. 	/* known && !uname is possible after amnesia/mind flayer */ 267. 	if (obj->oclass == RING_CLASS) 268. 	    return (boolean)(objects[obj->otyp].oc_charged &&  269.  			(obj->known || objects[obj->otyp].oc_uname)); 270. 	if (is_weptool(obj))	/* specific check before general tools */ 271. 	    return FALSE; 272. 	if (obj->oclass == TOOL_CLASS) 273. 	    return (boolean)(objects[obj->otyp].oc_charged); 274. 	return FALSE; /* why are weapons/armor considered charged anyway? */ 275.  }  276.   277.  /*  278.   * recharge an object; curse_bless is -1 if the recharging implement 279.  * was cursed, +1 if blessed, 0 otherwise. 280.  */  281.  void 282. recharge(obj, curse_bless) 283. struct obj *obj; 284. int curse_bless; 285. {  286.  	register int n;  287. boolean is_cursed, is_blessed; 288.  289.  	is_cursed = curse_bless < 0; 290. 	is_blessed = curse_bless > 0; 291.  292.  	if (obj->oclass == WAND_CLASS) { 293. 	    /* undo any prior cancellation, even when is_cursed */ 294. 	    if (obj->spe == -1) obj->spe = 0; 295.  296.  	    /*  297.  	     * Recharging might cause wands to explode. 298. 	     *	v = number of previous recharges 299. 	     *	      v = percentage chance to explode on this attempt 300. 	     *		      v = cumulative odds for exploding 301. 	     *	0 :   0       0  302.  	     *	1 :   0.29    0.29  303.  	     *	2 :   2.33    2.62  304.  	     *	3 :   7.87   10.28  305.  	     *	4 :  18.66   27.02  306.  	     *	5 :  36.44   53.62  307.  	     *	6 :  62.97   82.83  308.  	     *	7 : 100     100  309.  	     */  310.  	    n = (int)obj->recharged; 311. 	    if (n > 0 && (obj->otyp == WAN_WISHING || 312. 		    (n * n * n > rn2(7*7*7)))) {	/* recharge_limit */ 313. 		wand_explode(obj); 314. 		return; 315. 	    }  316.  	    /* didn't explode, so increment the recharge count */ 317. 	    obj->recharged = (unsigned)(n + 1); 318.  319.  	    /* now handle the actual recharging */ 320. 	    if (is_cursed) { 321. 		stripspe(obj); 322. 	    } else { 323. 		int lim = (obj->otyp == WAN_WISHING) ? 3 : 324.  			(objects[obj->otyp].oc_dir != NODIR) ? 8 : 15; 325.   326.  		n = (lim == 3) ? 3 : rn1(5, lim + 1 - 5); 327. 		if (!is_blessed) n = rnd(n); 328.  329.  		if (obj->spe < n) obj->spe = n;  330. else obj->spe++; 331. 		if (obj->otyp == WAN_WISHING && obj->spe > 3) { 332. 		    wand_explode(obj); 333. 		    return; 334. 		}  335.  		if (obj->spe >= lim) p_glow2(obj,blue); 336. 		else p_glow1(obj); 337. 	    }  338.   339.  	} else if (obj->oclass == RING_CLASS &&  340.  					objects[obj->otyp].oc_charged) { 341. 	    /* charging does not affect ring's curse/bless status */ 342. 	    int s = is_blessed ? rnd(3) : is_cursed ? -rnd(2) : 1; 343. 	    boolean is_on = (obj == uleft || obj == uright); 344.  345.  	    /* destruction depends on current state, not adjustment */ 346. 	    if (obj->spe > rn2(7) || obj->spe <= -5) { 347. 		Your("%s pulsates momentarily, then explodes!",  348.  		     xname(obj)); 349. 		if (is_on) Ring_gone(obj); 350. 		s = rnd(3 * abs(obj->spe));	/* amount of damage */ 351. 		useup(obj); 352. 		losehp(s, "exploding ring", KILLED_BY_AN); 353. 	    } else { 354. 		long mask = is_on ? (obj == uleft ? LEFT_RING : 355.  				     RIGHT_RING) : 0L; 356. 		Your("%s spins %sclockwise for a moment.",  357.  		     xname(obj), s < 0 ? "counter" : ""); 358. 		/* cause attributes and/or properties to be updated */ 359. 		if (is_on) Ring_off(obj); 360. 		obj->spe += s;	/* update the ring while it's off */ 361. 		if (is_on) setworn(obj, mask), Ring_on(obj); 362. 		/* oartifact: if a touch-sensitive artifact ring is  363. ever created the above will need to be revised */ 364. 	    }  365.   366.  	} else if (obj->oclass == TOOL_CLASS) { 367. 	    int rechrg = (int)obj->recharged; 368.  369.  	    if (objects[obj->otyp].oc_charged) { 370. 		/* tools don't have a limit, but the counter used does */ 371. 		if (rechrg < 7)	/* recharge_limit */ 372. 		    obj->recharged++; 373. 	    }  374.  	    switch(obj->otyp) { 375. 	    case BELL_OF_OPENING: 376. 		if (is_cursed) stripspe(obj); 377. 		else if (is_blessed) obj->spe += rnd(3); 378. 		else obj->spe += 1; 379. 		if (obj->spe > 5) obj->spe = 5; 380. 		break; 381. 	    case MAGIC_MARKER: 382. 	    case TINNING_KIT: 383. #ifdef TOURIST 384. 	    case EXPENSIVE_CAMERA: 385. #endif 386. 		if (is_cursed) stripspe(obj); 387. 		else if (rechrg && obj->otyp == MAGIC_MARKER) {	/* previously recharged */ 388. 		    obj->recharged = 1;	/* override increment done above */ 389. 		    if (obj->spe < 3) 390. 			Your("marker seems permanently dried out."); 391. 		    else 392. 			pline(nothing_happens); 393. 		} else if (is_blessed) { 394. 		    n = rn1(10,16);		/* 10..25 */ 395. 		    if (obj->spe + n <= 50) 396. 			obj->spe = 50; 397. 		    else if (obj->spe + n <= 75) 398. 			obj->spe = 75; 399. 		    else { 400. 		    	int chrg = (int)obj->spe; 401. 			if ((chrg + n) > 127) 402. 				obj->spe = 127; 403. 			else 404. 				obj->spe += n;  405. } 406.  		    p_glow2(obj,blue); 407. 		} else { 408. 		    n = rn1(5,10);		/* 5..15 */ 409. 		    if (obj->spe + n <= 50) 410. 			obj->spe = 50; 411. 		    else { 412. 		    	int chrg = (int)obj->spe; 413. 			if ((chrg + n) > 127) 414. 				obj->spe = 127; 415. 			else 416. 				obj->spe += n;  417. } 418.  		    p_glow2(obj,White); 419. 		}  420.  		break; 421. 	    case OIL_LAMP: 422. 	    case BRASS_LANTERN: 423. 		if (is_cursed) { 424. 		    stripspe(obj); 425. 		    if (obj->lamplit) { 426. 			if (!Blind) 427. 			    pline("%s goes out!", The(xname(obj))); 428. 			end_burn(obj, TRUE); 429. 		    }  430.  		} else if (is_blessed) { 431. 		    obj->spe = 1; 432. 		    obj->age = 1500; 433. 		    p_glow2(obj,blue); 434. 		} else { 435. 		    obj->spe = 1; 436. 		    obj->age += 750; 437. 		    if (obj->age > 1500) obj->age = 1500; 438. 		    p_glow1(obj); 439. 		}  440.  		break; 441. 	    case CRYSTAL_BALL: 442. 		if (is_cursed) stripspe(obj); 443. 		else if (is_blessed) { 444. 		    obj->spe = 6; 445. 		    p_glow2(obj,blue); 446. 		} else { 447. 		    if (obj->spe < 5) { 448. 			obj->spe++; 449. 			p_glow1(obj); 450. 		    } else pline(nothing_happens); 451. 		}  452.  		break; 453. 	    case HORN_OF_PLENTY: 454. 	    case BAG_OF_TRICKS: 455. 	    case CAN_OF_GREASE: 456. 		if (is_cursed) stripspe(obj); 457. 		else if (is_blessed) { 458. 		    if (obj->spe <= 10) 459. 			obj->spe += rn1(10, 6); 460. 		    else obj->spe += rn1(5, 6); 461. 		    p_glow2(obj,blue); 462. 		} else { 463. 		    obj->spe += rnd(5); 464. 		    p_glow1(obj); 465. 		}  466.  		break; 467. 	    case MAGIC_FLUTE: 468. 	    case MAGIC_HARP: 469. 	    case FROST_HORN: 470. 	    case FIRE_HORN: 471. 	    case DRUM_OF_EARTHQUAKE: 472. 		if (is_cursed) { 473. 		    stripspe(obj); 474. 		} else if (is_blessed) { 475. 		    obj->spe += d(2,4); 476. 		    p_glow2(obj,blue); 477. 		} else { 478. 		    obj->spe += rnd(4); 479. 		    p_glow1(obj); 480. 		}  481.  		break; 482. 	    default: 483. 		goto not_chargable; 484. 		/*NOTREACHED*/ 485. 		break; 486. 	    } /* switch */ 487.  488.  	} else { 489.  not_chargable: 490. 	    You("have a feeling of loss."); 491. 	}  492.  }  493.   494.   495.  /* Forget known information about this object class. */ 496.  static void 497. forget_single_object(obj_id) 498. 	int obj_id; 499. {  500.  	objects[obj_id].oc_name_known = 0; 501. 	objects[obj_id].oc_pre_discovered = 0;	/* a discovery when relearned */ 502. 	if (objects[obj_id].oc_uname) { 503. 	    /* this only works if oc_name_known is false */ 504. 	    undiscover_object(obj_id); 505.  506.  	    free((genericptr_t)objects[obj_id].oc_uname); 507. 	    objects[obj_id].oc_uname = 0; 508. 	}  509.  	/* clear & free object names from matching inventory items too? */ 510.  }  511.   512.   513.  #if 0	/* here if anyone wants it.... */ 514.  /* Forget everything known about a particular object class. */ 515.  static void 516. forget_objclass(oclass) 517. 	int oclass; 518. {  519.  	int i;  520. 521. 	for (i=bases[oclass];  522.  		i < NUM_OBJECTS && objects[i].oc_class==oclass; i++) 523. 	    forget_single_object(i); 524. }  525.  #endif 526.  527.   528.  /* randomize the given list of numbers  0 <= i < count */ 529. static void 530. randomize(indices, count) 531. 	int *indices; 532. 	int count; 533. {  534.  	int i, iswap, temp; 535.  536.  	for (i = count - 1; i > 0; i--) { 537. 	    if ((iswap = rn2(i + 1)) == i) continue; 538. 	    temp = indices[i]; 539. 	    indices[i] = indices[iswap]; 540. 	    indices[iswap] = temp; 541. 	}  542.  }  543.   544.   545.  /* Forget % of known objects. */ 546.  void 547. forget_objects(percent) 548. 	int percent; 549. {  550.  	int i, count; 551. 	int indices[NUM_OBJECTS]; 552.  553.  	if (percent == 0) return; 554. 	if (percent <= 0 || percent > 100) { 555. 	    impossible("forget_objects: bad percent %d", percent); 556. 	    return; 557. 	}  558.   559.  	for (count = 0, i = 1; i < NUM_OBJECTS; i++) 560. 	    if (OBJ_DESCR(objects[i]) &&  561.  		    (objects[i].oc_name_known || objects[i].oc_uname)) 562. 		indices[count++] = i;  563. 564. 	randomize(indices, count); 565.  566.  	/* forget first % of randomized indices */ 567. 	count = ((count * percent) + 50) / 100; 568. 	for (i = 0; i < count; i++) 569. 	    forget_single_object(indices[i]); 570. }  571.   572.   573.  /* Forget some or all of map (depends on parameters). */ 574.  void 575. forget_map(howmuch) 576. 	int howmuch; 577. {  578.  	register int zx, zy; 579.  580.  	known = TRUE; 581. 	for(zx = 0; zx < COLNO; zx++) for(zy = 0; zy < ROWNO; zy++) 582. 	    if (howmuch & ALL_MAP || rn2(7)) { 583. 		/* Zonk all memory of this location. */ 584.  		levl[zx][zy].seenv = 0; 585. 		levl[zx][zy].waslit = 0; 586. 		levl[zx][zy].glyph = cmap_to_glyph(S_stone); 587. 	    }  588.  }  589.   590.  /* Forget all traps on the level. */ 591.  void 592. forget_traps 593. {  594.  	register struct trap *trap; 595.  596.  	/* forget all traps (except the one the hero is in :-) */ 597. 	for (trap = ftrap; trap; trap = trap->ntrap) 598. 	    if ((trap->tx != u.ux || trap->ty != u.uy) && (trap->ttyp != HOLE)) 599. 		trap->tseen = 0; 600. }  601.   602.  /*  603.   * Forget given % of all levels that the hero has visited and not forgotten, 604.  * except this one. 605.  */  606.  void 607. forget_levels(percent) 608. 	int percent; 609. {  610.  	int i, count; 611. 	xchar  maxl, this_lev; 612. 	int indices[MAXLINFO]; 613.  614.  	if (percent == 0) return; 615.  616.  	if (percent <= 0 || percent > 100) { 617. 	    impossible("forget_levels: bad percent %d", percent); 618. 	    return; 619. 	}  620.   621.  	this_lev = ledger_no(&u.uz); 622. 	maxl = maxledgerno; 623.  624.  	/* count & save indices of non-forgotten visited levels */ 625. 	for (count = 0, i = 0; i <= maxl; i++) 626. 	    if ((level_info[i].flags & VISITED) &&  627.  			!(level_info[i].flags & FORGOTTEN) && i != this_lev) 628. 		indices[count++] = i;  629. 630. 	randomize(indices, count); 631.  632.  	/* forget first % of randomized indices */ 633. 	count = ((count * percent) + 50) / 100; 634. 	for (i = 0; i < count; i++) { 635. 	    level_info[indices[i]].flags |= FORGOTTEN; 636. 	}  637.  }  638.   639.  /*  640.   * Forget some things (e.g. after reading a scroll of amnesia). When called, 641.  * the following are always forgotten: 642.  *  643.   *	- felt ball & chain 644.  *	- traps 645.  *	- part (6 out of 7) of the map 646.  *  647.   * Other things are subject to flags: 648.  *  649.   *	howmuch & ALL_MAP	= forget whole map 650.  *	howmuch & ALL_SPELLS	= forget all spells 651.  */  652.  static void 653. forget(howmuch) 654. int howmuch; 655. {  656.   657.  	if (Punished) u.bc_felt = 0;	/* forget felt ball&chain */ 658.  659.  	forget_map(howmuch); 660. 	forget_traps; 661.  662.  	/* 1 in 3 chance of forgetting some levels */ 663. 	if (!rn2(3)) forget_levels(rn2(25)); 664.  665.  	/* 1 in 3 chance of forgeting some objects */ 666. 	if (!rn2(3)) forget_objects(rn2(25)); 667.  668.  	if (howmuch & ALL_SPELLS) losespells; 669. 	/*  670.  	 * Make sure that what was seen is restored correctly. To do this, 671. 	 * we need to go blind for an instant --- turn off the display, 672. 	 * then restart it. All this work is needed to correctly handle 673. 	 * walls which are stone on one side and wall on the other. Turning 674. 	 * off the seen bits above will make the wall revert to stone,  but 675. 	 * there are cases where we don't want this to happen. The easiest 676. 	 * thing to do is to run it through the vision system again, which 677. 	 * is always correct. 678. 	 */  679.  	docrt;		/* this correctly will reset vision */ 680. }  681.   682.  int 683. seffects(sobj) 684. register struct obj	*sobj; 685. {  686.  	register int cval; 687. 	register boolean confused = (Confusion != 0); 688. 	register struct obj *otmp; 689.  690.  	if (objects[sobj->otyp].oc_magic) 691. 		exercise(A_WIS, TRUE);		/* just for trying */ 692. 	switch(sobj->otyp) { 693. #ifdef MAIL 694. 	case SCR_MAIL: 695. 		known = TRUE; 696. 		if (sobj->spe) 697. 		    pline("This seems to be junk mail addressed to the finder of the Eye of Larn."); 698. 		/* note to the puzzled: the game Larn actually sends you junk 699. 		 * mail if you win! 700. 		 */  701.  		else readmail(sobj); 702. 		break; 703. #endif 704. 	case SCR_ENCHANT_ARMOR: 705. 	    {  706.  		register schar s;  707. boolean special_armor; 708.  709.  		otmp = some_armor(&youmonst); 710. 		if(!otmp) { 711. 			strange_feeling(sobj,  712.  					!Blind ? "Your skin glows then fades." :  713.  					"Your skin feels warm for a moment."); 714. 			exercise(A_CON, !sobj->cursed); 715. 			exercise(A_STR, !sobj->cursed); 716. 			return(1); 717. 		}  718.  		if(confused) { 719. 			otmp->oerodeproof = !(sobj->cursed); 720. 			if(Blind) { 721. 			    otmp->rknown = FALSE; 722. 			    Your("%s feels warm for a moment.",  723.  				xname(otmp)); 724. 			} else { 725. 			    otmp->rknown = TRUE; 726. 			    Your("%s is covered by a %s %s %s!",  727.  				xname(otmp),  728.  				sobj->cursed ? "mottled" : "shimmering",  729.  				hcolor(sobj->cursed ? Black : golden), 730.  				sobj->cursed ? "glow" :  731.  				  (is_shield(otmp) ? "layer" : "shield")); 732. 			}  733.  			if (otmp->oerodeproof && (otmp->oeroded || otmp->oeroded2)) { 734. 			    otmp->oeroded = otmp->oeroded2 = 0; 735. 			    Your("%s %ss good as new!",  736.  				 xname(otmp), Blind ? "feel" : "look"); 737. 			}  738.  			break; 739. 		}  740.  		special_armor = is_elven_armor(otmp) || 741. 				(Role_if(PM_WIZARD) && otmp->otyp == CORNUTHAUM); 742. 		/* KMH -- catch underflow */ 743. 		s = sobj->cursed ? -otmp->spe : otmp->spe; 744. 		if (s > (special_armor ? 5 : 3) && rn2(s)) { 745. 		Your("%s violently %s%s for a while, then evaporates.",  746.  			    xname(otmp),  747.  			    Blind ? "vibrates" : "glows ",  748.  			    Blind ? nul : hcolor(sobj->cursed ? Black : silver)); 749. 			if(is_cloak(otmp)) (void) Cloak_off; 750. 			if(is_boots(otmp)) (void) Boots_off; 751. 			if(is_helmet(otmp)) (void) Helmet_off; 752. 			if(is_gloves(otmp)) (void) Gloves_off; 753. 			if(is_shield(otmp)) (void) Shield_off; 754. 			if(otmp == uarm) (void) Armor_gone; 755. 			useup(otmp); 756. 			break; 757. 		}  758.  		s = sobj->cursed ? -1 : 759.  		    otmp->spe >= 9 ? (rn2(otmp->spe) == 0) : 760. 		    sobj->blessed ? rnd(3-otmp->spe/3) : 1; 761. 		if (s >= 0 && otmp->otyp >= GRAY_DRAGON_SCALES &&  762.  					otmp->otyp <= YELLOW_DRAGON_SCALES) { 763. 			/* dragon scales get turned into dragon scale mail */ 764. 			Your("%s merges and hardens!", xname(otmp)); 765. 			setworn((struct obj *)0, W_ARM); 766. 			/* assumes same order */ 767. 			otmp->otyp = GRAY_DRAGON_SCALE_MAIL + 768. 						otmp->otyp - GRAY_DRAGON_SCALES; 769. 			otmp->cursed = 0; 770. 			if (sobj->blessed) { 771. 				otmp->spe++; 772. 				otmp->blessed = 1; 773. 			}  774.  			otmp->known = 1; 775. 			setworn(otmp, W_ARM); 776. 			break; 777. 		}  778.  		Your("%s %s%s%s for a %s.",  779.  			xname(otmp),  780.  		        s == 0 ? "violently " : nul,  781.  			Blind ? "vibrates" : "glows ",  782.  			Blind ? nul : hcolor(sobj->cursed ? Black : silver), 783.  			  (s*s>1) ? "while" : "moment"); 784. 		otmp->cursed = sobj->cursed; 785. 		if (!otmp->blessed || sobj->cursed) 786. 			otmp->blessed = sobj->blessed; 787. 		if (s) { 788. 			otmp->spe += s;  789. adj_abon(otmp, s); 790. 			known = otmp->known; 791. 		}  792.   793.  		if ((otmp->spe > (special_armor ? 5 : 3)) &&  794.  		    (special_armor || !rn2(7))) 795. 			Your("%s suddenly vibrates %s.",  796.  				xname(otmp),  797.  				Blind ? "again" : "unexpectedly"); 798. 		break; 799. 	    }  800.  	case SCR_DESTROY_ARMOR: 801. 	    {  802.  		otmp = some_armor(&youmonst); 803. 		if(confused) { 804. 			if(!otmp) { 805. 				strange_feeling(sobj,"Your bones itch."); 806. 				exercise(A_STR, FALSE); 807. 				exercise(A_CON, FALSE); 808. 				return(1); 809. 			}  810.  			otmp->oerodeproof = sobj->cursed; 811. 			p_glow2(otmp,purple); 812. 			break; 813. 		}  814.  		if(!sobj->cursed || !otmp || !otmp->cursed) { 815. 		    if(!destroy_arm(otmp)) { 816. 			strange_feeling(sobj,"Your skin itches."); 817. 			exercise(A_STR, FALSE); 818. 			exercise(A_CON, FALSE); 819. 			return(1); 820. 		    } else 821. 			known = TRUE; 822. 		} else {	/* armor and scroll both cursed */ 823. 		    Your("%s vibrates.", xname(otmp)); 824. 		    if (otmp->spe >= -6) otmp->spe--; 825. 		    make_stunned(HStun + rn1(10, 10), TRUE); 826. 		}  827.  	    }  828.  	    break; 829. 	case SCR_CONFUSE_MONSTER: 830. 	case SPE_CONFUSE_MONSTER: 831. 		if(youmonst.data->mlet != S_HUMAN || sobj->cursed) { 832. 			if(!HConfusion) You_feel("confused."); 833. 			make_confused(HConfusion + rnd(100),FALSE); 834. 		} else  if(confused) { 835. 		    if(!sobj->blessed) { 836. 			Your("%s begin to %s%s.",  837.  			    makeplural(body_part(HAND)),  838.  			    Blind ? "tingle" : "glow ",  839.  			    Blind ? nul : hcolor(purple)); 840. 			make_confused(HConfusion + rnd(100),FALSE); 841. 		    } else { 842. 			pline("A %s%s surrounds your %s.",  843.  			    Blind ? nul : hcolor(red),  844.  			    Blind ? "faint buzz" : " glow",  845.  			    body_part(HEAD)); 846. 			make_confused(0L,TRUE); 847. 		    }  848.  		} else { 849. 		    if (!sobj->blessed) { 850. 			Your("%s%s %s%s.",  851.  			makeplural(body_part(HAND)),  852.  			Blind ? "" : " begin to glow",  853.  			Blind ? (const char *)"tingle" : hcolor(red),  854.  			u.umconf ? " even more" : ""); 855. 			u.umconf++; 856. 		    } else { 857. 			if (Blind) 858. 			    Your("%s tingle %s sharply.",  859.  				makeplural(body_part(HAND)),  860.  				u.umconf ? "even more" : "very"); 861. 			else 862. 			    Your("%s glow a%s brilliant %s.",  863.  				makeplural(body_part(HAND)),  864.  				u.umconf ? "n even more" : "",  865.  				hcolor(red)); 866. 			u.umconf += rn1(8, 2); 867. 		    }  868.  		}  869.  		break; 870. 	case SCR_SCARE_MONSTER: 871. 	case SPE_CAUSE_FEAR: 872. 	    {	register int ct = 0; 873. 		register struct monst *mtmp; 874.  875.  		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 876. 		    if(cansee(mtmp->mx,mtmp->my)) { 877. 			if(confused || sobj->cursed) { 878. 			    mtmp->mflee = mtmp->mfrozen = mtmp->msleeping = 0; 879. 			    mtmp->mcanmove = 1; 880. 			} else 881. 			    if (! resist(mtmp, sobj->oclass, 0, NOTELL)) 882. 				mtmp->mflee = 1; 883. 			if(!mtmp->mtame) ct++;	/* pets don't laugh at you */ 884. 		    }  885.  		if(!ct) 886. 		      You_hear("%s in the distance.",  887.  			       (confused || sobj->cursed) ? "sad wailing" :  888.  							"maniacal laughter"); 889. 		else if(sobj->otyp == SCR_SCARE_MONSTER) 890. 			You_hear("%s close by.",  891.  				  (confused || sobj->cursed) ? "sad wailing" :  892.  						 "maniacal laughter"); 893. 		break; 894. 	    }  895.  	case SCR_BLANK_PAPER: 896. 	    if (Blind) 897. 		You("don't remember there being any magic words on this scroll."); 898. 	    else 899. 		pline("This scroll seems to be blank."); 900. 	    known = TRUE; 901. 	    break; 902. 	case SCR_REMOVE_CURSE: 903. 	case SPE_REMOVE_CURSE: 904. 	    {	register struct obj *obj; 905. 		if(confused) 906. 		    if (Hallucination) 907. 			You_feel("the power of the Force against you!"); 908. 		    else 909. 			You_feel("like you need some help."); 910. 		else 911. 		    if (Hallucination) 912. 			You_feel("in touch with the Universal Oneness."); 913. 		    else 914. 			You_feel("like someone is helping you."); 915.  916.  		if(sobj->cursed) pline_The("scroll disintegrates."); 917. 		else { 918. 		    for(obj = invent; obj ; obj = obj->nobj) 919. 			if(sobj->blessed || obj->owornmask ||  920.  			   (obj->otyp == LOADSTONE)) { 921. 			    if(confused) blessorcurse(obj, 2); 922. 			    else uncurse(obj); 923. 			}  924.  		}  925.  		if(Punished && !confused) unpunish; 926. 		break; 927. 	    }  928.  	case SCR_CREATE_MONSTER: 929. 	case SPE_CREATE_MONSTER: 930. 	    if (create_critters(1 + ((confused || sobj->cursed) ? 12 : 0) + 931. 				((sobj->blessed || rn2(73)) ? 0 : rnd(4)), 932. 			confused ? &mons[PM_ACID_BLOB] : (struct permonst *)0)) 933. 		known = TRUE; 934. 	    /* no need to flush monsters; we ask for identification only if the 935. 	     * monsters are not visible 936. 	     */  937.  	    break; 938. 	case SCR_ENCHANT_WEAPON: 939. 		if(uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep))  940.  			&& confused) { 941. 		/* oclass check added 10/25/86 GAN */ 942. 			uwep->oerodeproof = !(sobj->cursed); 943. 			if (Blind) { 944. 			    uwep->rknown = FALSE; 945. 			    Your("weapon feels warm for a moment."); 946. 			} else { 947. 			    uwep->rknown = TRUE; 948. 			    Your("%s covered by a %s %s %s!",  949.  				aobjnam(uwep, "are"),  950.  				sobj->cursed ? "mottled" : "shimmering",  951.  				hcolor(sobj->cursed ? purple : golden), 952.  				sobj->cursed ? "glow" : "shield"); 953. 			}  954.  			if (uwep->oerodeproof && (uwep->oeroded || uwep->oeroded2)) { 955. 			    uwep->oeroded = uwep->oeroded2 = 0; 956. 			    Your("%s good as new!",  957.  				 aobjnam(uwep, Blind ? "feel" : "look")); 958. 			}  959.  		} else return !chwepon(sobj,  960.  				       sobj->cursed ? -1 :  961.  				       !uwep ? 1 :  962.  				       uwep->spe >= 9 ? (rn2(uwep->spe) == 0) :  963.  				       sobj->blessed ? rnd(3-uwep->spe/3) : 1); 964. 		break; 965. 	case SCR_TAMING: 966. 	case SPE_CHARM_MONSTER: 967. 	    {	register int i,j; 968. 		register int bd = confused ? 5 : 1; 969.  		register struct monst *mtmp; 970.  971.  		for(i = -bd; i <= bd; i++) for(j = -bd; j <= bd; j++) 972. 		if(isok(u.ux+i, u.uy+j) && (mtmp = m_at(u.ux+i, u.uy+j))) { 973. 		    if(sobj->cursed) { 974. 			setmangry(mtmp); 975. 		    } else { 976. 			if (mtmp->isshk) 977. 			    make_happy_shk(mtmp, FALSE); 978. 			else if (!resist(mtmp, sobj->oclass, 0, NOTELL)) 979. 			    (void) tamedog(mtmp, (struct obj *) 0); 980. 		    }  981.  		}  982.  		break; 983. 	    }  984.  	case SCR_GENOCIDE: 985. 		You("have found a scroll of genocide!"); 986. 		known = TRUE; 987. 		if (sobj->blessed) do_class_genocide; 988. 		else do_genocide(!sobj->cursed | (2 * !!Confusion)); 989. 		break; 990. 	case SCR_LIGHT: 991. 		if(!Blind) known = TRUE; 992. 		litroom(!confused && !sobj->cursed, sobj); 993. 		break; 994. 	case SCR_TELEPORTATION: 995. 		if(confused || sobj->cursed) level_tele; 996. 		else { 997. 			if (sobj->blessed && !Teleport_control) { 998. 				known = TRUE; 999. 				if (yn("Do you wish to teleport?")=='n') 1000. 					break; 1001. 			} 1002. 			tele; 1003. 			if(Teleport_control || !couldsee(u.ux0, u.uy0) || 1004. 			   (distu(u.ux0, u.uy0) >= 16)) 1005. 				known = TRUE; 1006. 		} 1007. 		break; 1008. 	case SCR_GOLD_DETECTION: 1009. 		if (confused || sobj->cursed) return(trap_detect(sobj)); 1010. 		else return(gold_detect(sobj)); 1011. 	case SCR_FOOD_DETECTION: 1012. 	case SPE_DETECT_FOOD: 1013. 		if (food_detect(sobj)) 1014. 			return(1);	/* nothing detected */ 1015. 		break; 1016. 	case SPE_IDENTIFY: 1017. 		cval = rn2(5); 1018. 		goto id; 1019. 	case SCR_IDENTIFY: 1020. 		/* known = TRUE; */ 1021. 		if(confused) 1022. 			You("identify this as an identify scroll."); 1023. 		else 1024. 			pline("This is an identify scroll."); 1025. 		if (sobj->blessed || (!sobj->cursed && !rn2(5))) { 1026. 			cval = rn2(5); 1027. 			/* Note: if rn2(5)==0, identify all items */ 1028. 			if (cval == 1 && sobj->blessed && Luck > 0) ++cval; 1029. 		} else	cval = 1; 1030. 		useup(sobj); 1031. 		makeknown(SCR_IDENTIFY); 1032. 	id: 1033. 		if(invent && !confused) { 1034. 		   identify_pack(cval); 1035. 		} 1036. 		return(1); 1037. 	case SCR_CHARGING: 1038. 		if (confused) { 1039. 		   You_feel("charged up!"); 1040. 		   if (u.uen < u.uenmax) 1041. 			u.uen = u.uenmax; 1042. 		   else 1043. 			u.uen = (u.uenmax += d(5,4)); 1044. 		   flags.botl = 1; 1045. 		   break; 1046. 		} 1047. 		known = TRUE; 1048. 		pline("This is a charging scroll."); 1049. 		otmp = getobj(all_count, "charge"); 1050. 		if (!otmp) break; 1051. 		recharge(otmp, sobj->cursed ? -1 : (sobj->blessed ? 1 : 0)); 1052. 		break; 1053. 	case SCR_MAGIC_MAPPING: 1054. 		if (level.flags.nommap) { 1055. 		   Your("mind is filled with crazy lines!"); 1056. 		   if (Hallucination) 1057. 			pline("Wow! Modern art."); 1058. 		   else 1059. 			Your("head spins in bewilderment."); 1060. 		   make_confused(HConfusion + rnd(30), FALSE); 1061. 		   break; 1062. 		} 1063. 		if (sobj->blessed) { 1064. 		   register int x, y;  1065. 1066. 		   for (x = 1; x < COLNO; x++) 1067. 		   	for (y = 0; y < ROWNO; y++) 1068. 		   	    if (levl[x][y].typ == SDOOR) 1069. 		   	    	cvt_sdoor_to_door(&levl[x][y]); 1070. 		   /* do_mapping already reveals secret passages */ 1071. 		} 1072. 		known = TRUE; 1073. 	case SPE_MAGIC_MAPPING: 1074. 		if (level.flags.nommap) { 1075. 		   Your("head spins as something blocks the spell!"); 1076. 		   make_confused(HConfusion + rnd(30), FALSE); 1077. 		   break; 1078. 		} 1079. 		pline("A map coalesces in your mind!"); 1080. 		cval = (sobj->cursed && !confused); 1081. 		if(cval) HConfusion = 1;	/* to screw up map */ 1082. 		do_mapping; 1083. 		if(cval) { 1084. 		   HConfusion = 0;		/* restore */ 1085. 		   pline("Unfortunately, you can't grasp the details."); 1086. 		} 1087. 		break; 1088. 	case SCR_AMNESIA: 1089. 		known = TRUE; 1090. 		forget(	(!sobj->blessed ? ALL_SPELLS : 0) | 1091. 			(!confused || sobj->cursed ? ALL_MAP : 0) ); 1092. 		if (Hallucination) /* Ommmmmm! */ 1093. 			Your("mind releases itself from mundane concerns."); 1094. 		else if (!strncmpi(plname, "Maud", 4)) 1095. 			pline("As your mind turns inward on itself, you forget everything else."); 1096. 		else if (rn2(2)) 1097. 			pline("Who was that Maud person anyway?"); 1098. 		else 1099. 			pline("Thinking of Maud you forget everything else."); 1100. 		exercise(A_WIS, FALSE); 1101. 		break; 1102. 	case SCR_FIRE: 1103. 		/* 1104. 		 * Note: Modifications have been made as of 3.0 to allow for 1105. 		 * some damage under all potential cases. 1106. 		 */ 1107. 		cval = bcsign(sobj); 1108. 		useup(sobj); 1109. 		makeknown(SCR_FIRE); 1110. 		if(confused) { 1111. 		   if(Fire_resistance) { 1112. 			shieldeff(u.ux, u.uy); 1113. 			if(!Blind) 1114. 			   pline("Oh, look, what a pretty fire in your %s.",  1115. 				makeplural(body_part(HAND))); 1116. 			else You_feel("a pleasant warmth in your %s.", 1117. 				makeplural(body_part(HAND))); 1118. 		   } else { 1119. 			pline_The("scroll catches fire and you burn your %s.", 1120. 				makeplural(body_part(HAND))); 1121. 			losehp(1, "scroll of fire", KILLED_BY_AN); 1122. 		   }  1123. 		    return(1); 1124. 		} 1125. 		if (Underwater) 1126. 			pline_The("water around you vaporizes violently!"); 1127. 		else { 1128. 		   pline_The("scroll erupts in a tower of flame!"); 1129. 		   burn_away_slime; 1130. 		} 1131. 		explode(u.ux, u.uy, 11, (2*(rn1(3, 3) + 2 * cval) + 1)/3,  1132. 							SCROLL_CLASS); 1133. 		return(1); 1134. 	case SCR_EARTH: 1135. 	   /* TODO: handle steeds */ 1136. 	   if (  1137. #ifdef REINCARNATION  1138. 		!Is_rogue_level(&u.uz) &&  1139. #endif  1140. 	    	 (!In_endgame(&u.uz) || Is_earthlevel(&u.uz))) { 1141. 	   	register int x, y;  1142. 1143. 	   	/* Identify the scroll */ 1144. 	   	pline_The("%s rumbles %s you!", ceiling(u.ux,u.uy),  1145. 	    			sobj->blessed ? "around" : "above"); 1146. 	   	known = 1; 1147. 1148. 	    	/* Loop through the surrounding squares */ 1149. 	   	if (!sobj->cursed) for (x = u.ux-1; x <= u.ux+1; x++) { 1150. 	   	    for (y = u.uy-1; y <= u.uy+1; y++) { 1151. 1152. 	    	    	/* Is this a suitable spot? */ 1153. 	    	    	if (isok(x, y) && !closed_door(x, y) &&  1154. 	    	    			!IS_ROCK(levl[x][y].typ) &&  1155. 	    	    			!IS_AIR(levl[x][y].typ) &&  1156. 					(x != u.ux || y != u.uy)) { 1157. 			   register struct obj *otmp2; 1158. 			   register struct monst *mtmp; 1159. 1160. 	    	    	    /* Make the object(s) */ 1161. 	   	    	    otmp2 = mksobj(confused ? ROCK : BOULDER,  1162. 	    	    	    		FALSE, FALSE); 1163. 	   	    	    if (!otmp2) continue;  /* Shouldn't happen */ 1164. 	   	    	    otmp2->quan = confused ? rn1(5,2) : 1; 1165. 	   	    	    otmp2->owt = weight(otmp2); 1166. 1167. 	    	    	    /* Find the monster here (won't be player) */ 1168. 	   	    	    mtmp = m_at(x, y); 1169. 	   	    	    if (mtmp && !amorphous(mtmp->data) &&  1170. 	    	    	    		!passes_walls(mtmp->data) &&  1171. 	    	    	    		!noncorporeal(mtmp->data) &&  1172. 	    	    	    		!unsolid(mtmp->data)) { 1173. 				struct obj *helmet = which_armor(mtmp, W_ARMH); 1174. 				int mdmg; 1175. 1176. 				if (cansee(mtmp->mx, mtmp->my)) { 1177. 				   pline("%s is hit by %s!", Monnam(mtmp),  1178. 	    	    	    			doname(otmp2)); 1179. 				   if (mtmp->minvis && !canspotmon(mtmp)) 1180. 					map_invisible(mtmp->mx, mtmp->my); 1181. 				} 1182. 	    	    	    	mdmg = dmgval(otmp2, mtmp) * otmp2->quan; 1183. 				if (helmet) { 1184. 				   if(is_metallic(helmet)) { 1185. 					if (canspotmon(mtmp)) 1186. 					   pline("Fortunately, %s is wearing a hard helmet.", mon_nam(mtmp)); 1187. 					else if (flags.soundok) 1188. 					   You_hear("a clanging sound."); 1189. 					if (mdmg > 2) mdmg = 2; 1190. 				   } else { 1191. 					if (canspotmon(mtmp)) 1192. 					   pline("%s's %s does not protect %s.",  1193. 						Monnam(mtmp), xname(uarmh),  1194. 						him[pronoun_gender(mtmp)]); 1195. 				   }  1196. 				}  1197. 	    	    	    	mtmp->mhp -= mdmg; 1198. 	   	    	    	if (mtmp->mhp <= 0) 1199. 	   	    	    	    xkilled(mtmp, 1); 1200. 	   	    	    }  1201. 	    	    	    /* Drop the rock/boulder to the floor */ 1202. 	   	    	    if (!flooreffects(otmp2, x, y, "fall")) { 1203. 	   	    	    	place_object(otmp2, x, y); 1204. 	   	    	    	stackobj(otmp2); 1205. 	   	    	    	newsym(x, y);  /* map the rock */ 1206. 	   	    	    }  1207. 	    	    	}  1208. 		    }  1209. 		}  1210. 		/* Attack the player */ 1211. 		if (!sobj->blessed) { 1212. 		   int dmg; 1213. 		   struct obj *otmp2; 1214. 1215. 		    /* Okay, _you_ write this without repeating the code */ 1216. 		   otmp2 = mksobj(confused ? ROCK : BOULDER,  1217. 				FALSE, FALSE); 1218. 		   if (!otmp2) break; 1219. 		   otmp2->quan = confused ? rn1(5,2) : 1; 1220. 		   otmp2->owt = weight(otmp2); 1221. 		   if (!amorphous(youmonst.data) &&  1222. 				!Passes_walls &&  1223. 				!noncorporeal(youmonst.data) &&  1224. 				!unsolid(youmonst.data)) { 1225. 			You("are hit by %s!", doname(otmp2)); 1226. 			dmg = dmgval(otmp2, &youmonst) * otmp2->quan; 1227. 			if (uarmh && !sobj->cursed) { 1228. 			   if(is_metallic(uarmh)) { 1229. 				pline("Fortunately, you are wearing a hard helmet."); 1230. 				if (dmg > 2) dmg = 2; 1231. 			   } else if (flags.verbose) { 1232. 				Your("%s does not protect you.", 1233. 						xname(uarmh)); 1234. 			   }  1235. 			}  1236. 		    } else 1237. 			dmg = 0; 1238. 		   /* Must be before the losehp, for bones files */ 1239. 		   if (!flooreffects(otmp2, u.ux, u.uy, "fall")) { 1240. 			place_object(otmp2, u.ux, u.uy); 1241. 			stackobj(otmp2); 1242. 			newsym(u.ux, u.uy); 1243. 		   }  1244. 		    if (dmg) losehp(dmg, "scroll of earth", KILLED_BY_AN); 1245. 		} 1246. 	    }  1247. 	    break; 1248. 	case SCR_PUNISHMENT: 1249. 		known = TRUE; 1250. 		if(confused || sobj->blessed) { 1251. 			You_feel("guilty."); 1252. 			break; 1253. 		} 1254. 		punish(sobj); 1255. 		break; 1256. 	case SCR_STINKING_CLOUD: { 1257. 	       coord cc; 1258. 		pline("Where ?"); 1259. 		cc.x = u.ux; 1260. 		cc.y = u.uy; 1261. 		if (getpos(&cc, TRUE, "the desired position") < 0) /* force valid */ 1262. 		   return 0;	/* abort */ 1263. 		if (!cansee(cc.x, cc.y) || distu(cc.x, cc.y) >= 32) 1264. 		   return 0; 1265. 		known = TRUE; 1266. 		(void) create_gas_cloud(cc.x, cc.y, 3, 10); 1267. 		break; 1268. 	} 1269. 	default: 1270. 		impossible("What weird effect is this? (%u)", sobj->otyp); 1271. 	} 1272. 	return(0); 1273. } 1274.  1275. static void 1276. wand_explode(obj) 1277. register struct obj *obj; 1278. { 1279.     obj->in_use = TRUE;	/* in case losehp is fatal */ 1280.    Your("%s vibrates violently, and explodes!",xname(obj)); 1281.    nhbell; 1282.    losehp(rnd(2*(u.uhpmax+1)/3), "exploding wand", KILLED_BY_AN); 1283.    useup(obj); 1284.    exercise(A_STR, FALSE); 1285. } 1286.  1287. /*  1288.  * Low-level lit-field update routine. 1289. */  1290. STATIC_PTR void 1291. set_lit(x,y,val) 1292. int x, y; 1293. genericptr_t val; 1294. { 1295. 	if (val) 1296. 	   levl[x][y].lit = 1; 1297. 	else { 1298. 	   levl[x][y].lit = 0; 1299. 	   snuff_light_source(x, y); 1300. 	} 1301. }  1302.  1303. void 1304. litroom(on,obj) 1305. register boolean on; 1306. struct obj *obj; 1307. { 1308. 	char is_lit;	/* value is irrelevant; we use its address 1309. 			  as a `not null' flag for set_lit */ 1310. 1311. 	/* first produce the text (provided you're not blind) */ 1312. 	if(!on) { 1313. 		register struct obj *otmp; 1314. 1315. 		if (!Blind) { 1316. 		   if(u.uswallow) { 1317. 			pline("It seems even darker in here than before."); 1318. 			return; 1319. 		   }  1320. 		    You("are surrounded by darkness!"); 1321. 		} 1322.  1323. 		/* the magic douses lamps, et al, too */ 1324. 		for(otmp = invent; otmp; otmp = otmp->nobj) 1325. 		   if (otmp->lamplit) 1326. 			(void) snuff_lit(otmp); 1327. 		if (Blind) goto do_it; 1328. 	} else { 1329. 		if (Blind) goto do_it; 1330. 		if(u.uswallow){ 1331. 			if (is_animal(u.ustuck->data)) 1332. 				pline("%s stomach is lit.", 1333. 				         s_suffix(Monnam(u.ustuck))); 1334. 			else 1335. 				if (is_whirly(u.ustuck->data)) 1336. 					pline("%s shines briefly.", 1337. 					      Monnam(u.ustuck)); 1338. 				else 1339. 					pline("%s glistens.", Monnam(u.ustuck)); 1340. 			return; 1341. 		} 1342. 		pline("A lit field surrounds you!"); 1343. 	} 1344.  1345. do_it: 1346. 	/* No-op in water - can only see the adjacent squares and that's it! */ 1347. 	if (Underwater || Is_waterlevel(&u.uz)) return; 1348. 	/* 1349. 	 *  If we are darkening the room and the hero is punished but not 1350. 	 * blind, then we have to pick up and replace the ball and chain so  1351. * that we don't remember them if they are out of sight. 1352. 	 */ 1353. 	if (Punished && !on && !Blind) 1354. 	   move_bc(1, 0, uball->ox, uball->oy, uchain->ox, uchain->oy); 1355. 1356. #ifdef REINCARNATION 1357. 	if (Is_rogue_level(&u.uz)) { 1358. 	   /* Can't use do_clear_area because MAX_RADIUS is too small */ 1359. 	   /* rogue lighting must light the entire room */ 1360. 	   int rnum = levl[u.ux][u.uy].roomno - ROOMOFFSET; 1361. 	   int rx, ry; 1362. 	   if(rnum >= 0) { 1363. 		for(rx = rooms[rnum].lx-1; rx <= rooms[rnum].hx+1; rx++) 1364. 		   for(ry = rooms[rnum].ly-1; ry <= rooms[rnum].hy+1; ry++) 1365. 			set_lit(rx, ry, 1366. 				(genericptr_t)(on ? &is_lit : (char *)0)); 1367. 		rooms[rnum].rlit = on; 1368. 	   }  1369. 	    /* hallways remain dark on the rogue level */ 1370. 	} else 1371. #endif 1372. 	   do_clear_area(u.ux,u.uy,  1373. 		(obj && obj->oclass==SCROLL_CLASS && obj->blessed) ? 9 : 5,  1374. 		set_lit, (genericptr_t)(on ? &is_lit : (char *)0)); 1375. 1376. 	/*  1377. 	 *  If we are not blind, then force a redraw on all positions in sight 1378. 	 * by temporarily blinding the hero. The vision recalculation will 1379. 	 * correctly update all previously seen positions *and* correctly 1380. 	 * set the waslit bit [could be messed up from above]. 1381. 	 */ 1382. 	if (!Blind) { 1383. 	   vision_recalc(2); 1384. 1385. 	    /* replace ball&chain */ 1386. 	   if (Punished && !on) 1387. 		move_bc(0, 0, uball->ox, uball->oy, uchain->ox, uchain->oy); 1388. 	} 1389.  1390. 	vision_full_recalc = 1;	/* delayed vision recalculation */ 1391. } 1392.  1393. static void 1394. do_class_genocide 1395. { 1396. 	register int i, j, immunecnt, gonecnt, goodcnt, class; 1397. 	char buf[BUFSZ]; 1398. 	boolean gameover = FALSE;	/* true iff killed self */ 1399. 1400. 	for(j=0; ; j++) { 1401. 		if (j >= 5) { 1402. 			pline(thats_enough_tries); 1403. 			return; 1404. 		} 1405. 		do { 1406. 		   getlin("What class of monsters do you wish to genocide?",  1407. 			buf); 1408. 		   (void)mungspaces(buf); 1409. 		} while (buf[0]=='\033' || !buf[0]); 1410. 		if (strlen(buf) == 1) { 1411. 		   if (buf[0] == ILLOBJ_SYM) 1412. 			buf[0] = def_monsyms[S_MIMIC]; 1413. 		   class = def_char_to_monclass(buf[0]); 1414. 		} else { 1415. 		   char buf2[BUFSZ]; 1416. 1417. 		    class = 0; 1418. 		   Strcpy(buf2, makesingular(buf)); 1419. 		   Strcpy(buf, buf2); 1420. 		} 1421. 		immunecnt = gonecnt = goodcnt = 0; 1422. 		for (i = LOW_PM; i < NUMMONS; i++) { 1423. 		   if (class == 0 &&  1424. 			    strstri(monexplain[(int)mons[i].mlet], buf) != 0) 1425. 			class = mons[i].mlet; 1426. 		   if (mons[i].mlet == class) { 1427. 			if (!(mons[i].geno & G_GENO)) immunecnt++; 1428. 			else if(mvitals[i].mvflags & G_GENOD) gonecnt++; 1429. 			else goodcnt++; 1430. 		   }  1431. 		}  1432. 		/*  1433. 		 * TODO[?]: If user's input doesn't match any class 1434. 		 *	   description, check individual species names. 1435. 		 */ 1436. 		if (!goodcnt && class != mons[urole.malenum].mlet &&  1437. 				class != mons[urace.malenum].mlet) { 1438. 			if (gonecnt) 1439. 	pline("All such monsters are already nonexistent."); 1440. 			else if (immunecnt || 1441. 				(buf[0] == DEF_INVISIBLE && buf[1] == '\0')) 1442. 	You("aren't permitted to genocide such monsters."); 1443. 			else 1444. #ifdef WIZARD	/* to aid in topology testing; remove pesky monsters */ 1445. 			 if (wizard && buf[0] == '*') { 1446. 			   register struct monst *mtmp, *mtmp2; 1447. 1448. 			    gonecnt = 0; 1449. 			   for (mtmp = fmon; mtmp; mtmp = mtmp2) { 1450. 				mtmp2 = mtmp->nmon; 1451. 				mongone(mtmp); 1452. 				gonecnt++; 1453. 			   }  1454. 	pline("Eliminated %d monster%s.", gonecnt, plur(gonecnt)); 1455. 			   return; 1456. 			} else 1457. #endif 1458. 	pline("That symbol does not represent any monster."); 1459. 			continue; 1460. 		} 1461.  1462. 		for (i = LOW_PM; i < NUMMONS; i++) { 1463. 		   if(mons[i].mlet == class) { 1464. 			char nam[BUFSZ]; 1465. 1466. 			Strcpy(nam, makeplural(mons[i].mname)); 1467. 			if (Your_Own_Role(i) || Your_Own_Race(i) || 1468. 				((mons[i].geno & G_GENO) 1469. 				&& !(mvitals[i].mvflags & G_GENOD))) { 1470. 			/* This check must be first since player monsters might 1471. 			 * have G_GENOD or !G_GENO. 1472. 			 */ 1473. 			    mvitals[i].mvflags |= (G_GENOD|G_NOCORPSE); 1474. 			   reset_rndmonst(i); 1475. 			   kill_genocided_monsters; 1476. 			   update_inventory;		/* eggs & tins */ 1477. 			   pline("Wiped out all %s.", nam); 1478. 			   if (Upolyd && i == u.umonnum && !Unchanging) rehumanize; 1479. 			   /* Self-genocide if it matches either your race or role */ 1480. 			   /* Assumption: male and female forms share the same letter */ 1481. 			   if (i == urole.malenum || i == urace.malenum) { 1482. 				u.uhp = -1; 1483. 				killer_format = KILLED_BY_AN; 1484. 				killer = "scroll of genocide"; 1485. 				if (Upolyd) 1486. 				   You_feel("dead inside."); 1487. 				else 1488. 				   gameover = TRUE; 1489. 			   }  1490. 			} else if (mvitals[i].mvflags & G_GENOD) { 1491. 			   if (!gameover) 1492. 				pline("All %s are already nonexistent.", nam); 1493. 			} else if (!gameover) { 1494. 			 /* suppress feedback about quest beings except 1495. 			    for those applicable to our own role */ 1496. 			 if ((mons[i].msound != MS_LEADER || 1497. 			      quest_info(MS_LEADER) == i)  1498. 			   && (mons[i].msound != MS_NEMESIS || 1499. 			      quest_info(MS_NEMESIS) == i)  1500. 			   && (mons[i].msound != MS_GUARDIAN || 1501. 			      quest_info(MS_GUARDIAN) == i)  1502. 			/* non-leader/nemesis/guardian role-specific monster */  1503. 			   && (i != PM_NINJA ||		/* nuisance */ 1504. 			      Role_if(PM_SAMURAI))) { 1505. 				boolean named, uniq; 1506. 1507. 				named = type_is_pname(&mons[i]) ? TRUE : FALSE; 1508. 				uniq = (mons[i].geno & G_UNIQ) ? TRUE : FALSE; 1509. 				/* one special case */ 1510. 				if (i == PM_HIGH_PRIEST) uniq = FALSE; 1511. 1512. 				You("aren't permitted to genocide %s%s.",  1513. 				    (uniq && !named) ? "the " : "",  1514. 				    (uniq || named) ? mons[i].mname : nam); 1515. 			   }  1516. 			}  1517. 		    }  1518. 		}  1519. 		if (gameover) done(GENOCIDED); 1520. 		return; 1521. 	} 1522. }  1523.  1524. #define REALLY 1 1525. #define PLAYER 2 1526. void 1527. do_genocide(how) 1528. int how; 1529. /* 0 = no genocide; create monsters (cursed scroll) */ 1530. /* 1 = normal genocide */ 1531. /* 3 = forced genocide of player */ 1532. { 1533. 	char buf[BUFSZ]; 1534. 	register int	i, killplayer = 0; 1535. 	register int mndx; 1536. 	register struct permonst *ptr; 1537. 	const char *which; 1538. 1539. 	if (how & PLAYER) { 1540. 		mndx = u.umonster;	/* non-polymorphed mon num */ 1541. 		ptr = &mons[mndx]; 1542. 		Strcpy(buf, ptr->mname); 1543. 		killplayer++; 1544. 	} else { 1545. 	   for(i = 0; ; i++) { 1546. 		if(i >= 5) { 1547. 		   pline(thats_enough_tries); 1548. 		   return; 1549. 		} 1550. 		getlin("What monster do you want to genocide? [type the name]",  1551. 			buf); 1552. 1553. 		mndx = name_to_mon(buf); 1554. 		if (mndx == NON_PM || (mvitals[mndx].mvflags & G_GENOD)) { 1555. 			pline("Such creatures %s exist in this world.", 1556. 			      (mndx == NON_PM) ? "do not" : "no longer"); 1557. 			continue; 1558. 		} 1559. 		ptr = &mons[mndx]; 1560. 		if (Your_Own_Role(mndx) || Your_Own_Race(mndx)) { 1561. 			killplayer++; 1562. 			break; 1563. 		} 1564. 		if (is_human(ptr)) adjalign(-sgn(u.ualign.type)); 1565. 		if (is_demon(ptr)) adjalign(sgn(u.ualign.type)); 1566. 1567. 		if(!(ptr->geno & G_GENO)) { 1568. 			if(flags.soundok) { 1569. 	/* fixme: unconditional "caverns" will be silly in some circumstances */ 1570. 			   if(flags.verbose) 1571. 			pline("A thunderous voice booms through the caverns:"); 1572. 			   verbalize("No, mortal!  That will not be done."); 1573. 			} 1574. 			continue; 1575. 		} 1576. 		/* KMH -- Unchanging prevents rehumanization */ 1577. 		if (Unchanging && ptr == youmonst.data) 1578. 		   killplayer++; 1579. 		break; 1580. 	   }  1581. 	}  1582.  1583. 	which = "all "; 1584. 	if (Hallucination) { 1585. 	   if (Upolyd) 1586. 		Strcpy(buf,youmonst.data->mname); 1587. 	   else { 1588. 		Strcpy(buf, (flags.female && urole.name.f) ? 1589. 				urole.name.f : urole.name.m); 1590. 		buf[0] = lowc(buf[0]); 1591. 	   }  1592. 	} else { 1593. 	   Strcpy(buf, ptr->mname); /* make sure we have standard singular */ 1594. 	   if ((ptr->geno & G_UNIQ) && ptr != &mons[PM_HIGH_PRIEST]) 1595. 		which = !type_is_pname(ptr) ? "the " : ""; 1596. 	} 1597. 	if (how & REALLY) { 1598. 	   /* setting no-corpse affects wishing and random tin generation */ 1599. 	   mvitals[mndx].mvflags |= (G_GENOD | G_NOCORPSE); 1600. 	   pline("Wiped out %s%s.", which,  1601. 		  (*which != 'a') ? buf : makeplural(buf)); 1602. 1603. 	    if (killplayer) { 1604. 		/* might need to wipe out dual role */ 1605. 		if (urole.femalenum != NON_PM && mndx == urole.malenum) 1606. 		   mvitals[urole.femalenum].mvflags |= (G_GENOD | G_NOCORPSE); 1607. 		if (urole.femalenum != NON_PM && mndx == urole.femalenum) 1608. 		   mvitals[urole.malenum].mvflags |= (G_GENOD | G_NOCORPSE); 1609. 		if (urace.femalenum != NON_PM && mndx == urace.malenum) 1610. 		   mvitals[urace.femalenum].mvflags |= (G_GENOD | G_NOCORPSE); 1611. 		if (urace.femalenum != NON_PM && mndx == urace.femalenum) 1612. 		   mvitals[urace.malenum].mvflags |= (G_GENOD | G_NOCORPSE); 1613. 1614. 		u.uhp = -1; 1615. 		killer_format = KILLED_BY_AN; 1616. 		if (how & PLAYER) 1617. 			killer = "genocidal confusion"; 1618. 		else /* selected player deliberately, not confused */ 1619. 			killer = "scroll of genocide"; 1620. 1621. 	/* Polymorphed characters will die as soon as they're rehumanized. */ 1622. 	/* KMH -- Unchanging prevents rehumanization */ 1623. 		if (Upolyd && ptr != youmonst.data) You_feel("dead inside."); 1624. 		else 1625. 			done(GENOCIDED); 1626. 	   } else if (ptr == youmonst.data) { 1627. 		rehumanize; 1628. 	   }  1629. 	    reset_rndmonst(mndx); 1630. 	   kill_genocided_monsters; 1631. 	   update_inventory;	/* in case identified eggs were affected */ 1632. 	} else { 1633. 	   int cnt = 0; 1634. 1635. 	    if (!(mons[mndx].geno & G_UNIQ) &&  1636. 		    !(mvitals[mndx].mvflags & (G_GENOD | G_EXTINCT))) 1637. 		for (i = rn1(3, 4); i > 0; i--) { 1638. 		   if (!makemon(ptr, u.ux, u.uy, NO_MINVENT)) 1639. 			break;	/* couldn't make one */ 1640. 		   ++cnt; 1641. 		   if (mvitals[mndx].mvflags & G_EXTINCT) 1642. 			break;	/* just made last one */ 1643. 		} 1644. 	    if (cnt) 1645. 		pline("Sent in some %s.", makeplural(buf)); 1646. 	   else 1647. 		pline(nothing_happens); 1648. 	} 1649. }  1650.  1651. void 1652. punish(sobj) 1653. register struct obj	*sobj; 1654. { 1655. 	/* KMH -- Punishment is still okay when you are riding */ 1656. 	You("are being punished for your misbehavior!"); 1657. 	if(Punished){ 1658. 		Your("iron ball gets heavier."); 1659. 		uball->owt += 160 * (1 + sobj->cursed); 1660. 		return; 1661. 	} 1662. 	if (amorphous(youmonst.data) || is_whirly(youmonst.data) || unsolid(youmonst.data)) { 1663. 		pline("A ball and chain appears, then falls away."); 1664. 		dropy(mkobj(BALL_CLASS, TRUE)); 1665. 		return; 1666. 	} 1667. 	setworn(mkobj(CHAIN_CLASS, TRUE), W_CHAIN); 1668. 	setworn(mkobj(BALL_CLASS, TRUE), W_BALL); 1669. 	uball->spe = 1;		/* special ball (see save) */ 1670. 1671. 	/*  1672. 	 *  Place ball & chain if not swallowed. If swallowed, the ball & 1673. 	 * chain variables will be set at the next call to placebc. 1674. 	 */ 1675. 	if (!u.uswallow) { 1676. 	   placebc; 1677. 	   if (Blind) set_bc(1);	/* set up ball and chain variables */ 1678. 	   newsym(u.ux,u.uy);		/* see ball&chain if can't see self */ 1679. 	} 1680. }  1681.  1682. void 1683. unpunish 1684. {	   /* remove the ball and chain */ 1685. 	struct obj *savechain = uchain; 1686. 1687. 	obj_extract_self(uchain); 1688. 	newsym(uchain->ox,uchain->oy); 1689. 	setworn((struct obj *)0, W_CHAIN); 1690. 	dealloc_obj(savechain); 1691. 	uball->spe = 0; 1692. 	setworn((struct obj *)0, W_BALL); 1693. } 1694.  1695. /* some creatures have special data structures that only make sense in their 1696. * normal locations -- if the player tries to create one elsewhere, or to revive 1697. * one, the disoriented creature becomes a zombie 1698. */  1699. boolean 1700. cant_create(mtype, revival) 1701. int *mtype; 1702. boolean revival; 1703. { 1704.  1705. 	/* SHOPKEEPERS can be revived now */ 1706. 	if (*mtype==PM_GUARD || (*mtype==PM_SHOPKEEPER && !revival) 1707. 	     || *mtype==PM_ALIGNED_PRIEST || *mtype==PM_ANGEL) { 1708. 		*mtype = PM_HUMAN_ZOMBIE; 1709. 		return TRUE; 1710. 	} else if (*mtype==PM_LONG_WORM_TAIL) {	/* for create_particular */ 1711. 		*mtype = PM_LONG_WORM; 1712. 		return TRUE; 1713. 	} 1714. 	return FALSE; 1715. } 1716.  1717. #ifdef WIZARD 1718. boolean 1719. create_particular 1720. { 1721. 	char buf[BUFSZ]; 1722. 	int which, tries = 0; 1723. 1724. 	do { 1725. 	   getlin("Create what kind of monster? [type the name]", buf); 1726. 	   if (buf[0] == '\033') return FALSE; 1727. 	   which = name_to_mon(buf); 1728. 	   if (which < LOW_PM) pline("I've never heard of such monsters."); 1729. 	   else break; 1730. 	} while (++tries < 5); 1731. 	if (tries == 5) pline(thats_enough_tries); 1732. 	else { 1733. 	   (void) cant_create(&which, FALSE); 1734. 	   return((boolean)(makemon(&mons[which],  1735. 				u.ux, u.uy, NO_MM_FLAGS) != 0)); 1736. 	} 1737. 	return FALSE; 1738. } 1739. #endif /* WIZARD */ 1740. 1741. #endif /* OVLB */ 1742. 1743. /*read.c*/