Source:SLASH'EM 0.0.7E7F2/engrave.c

Below is the full text to engrave.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/engrave.c#line123 ]], for example.

The latest source code for vanilla NetHack is at Source code.

1.   /*	SCCS Id: @(#)engrave.c	3.4	2001/11/04	*/ 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.     5.    #include "hack.h"  6.    #include "lev.h"  7.    #include   8. 9.   STATIC_VAR NEARDATA struct engr *head_engr; 10.   11.   #ifdef OVLB 12.  /* random engravings */ 13.  static const char *random_mesg[] = { 14.  	"Elbereth", 15.  	/* trap engravings */ 16.  	"Vlad was here", "ad aerarium", 17.  	/* take-offs and other famous engravings */ 18.  	"Owlbreath", "Galadriel", 19.  	"Kilroy was here", 20.  	"A.S. ->", "<- A.S.", /* Journey to the Center of the Earth */ 21.  	"You won't get it up the steps", /* Adventure */ 22.  	"Lasciate ogni speranza o voi ch'entrate.", /* Inferno */ 23.  	"Well Come", /* Prisoner */ 24.  	"We apologize for the inconvenience.", /* So Long... */ 25.   	"See you next Wednesday", /* Thriller */ 26.  	"notary sojak", /* Smokey Stover */ 27.  	"For a good time call 8?7-5309", 28.  	"Please don't feed the animals.", /* Various zoos around the world */ 29.  	"Madam, in Eden, I'm Adam.", /* A palindrome */ 30.  	"Two thumbs up!", /* Siskel & Ebert */ 31.  	"Hello, World!", /* The First C Program */ 32.  #ifdef MAIL 33.  	"You've got mail!", /* AOL */ 34.  #endif 35.  	"As if!", /* Clueless */ 36.  	/* [Tom] added these */ 37.  	"Y?v?l s??ks!", /* just kidding... */ 38.   	"T?m ?as h?r?", 39.  	/* Tsanth added these */ 40.  	"Gazortenplatz", /* Tribute to David Fizz */ 41.  	"John 3:16", /* You see this everywhere; why not here? */ 42.   	"Exhale! Exhale! Exhale!", /* Prodigy */ 43.  	"All you need is love.", /* The Beatles */ 44.  	"Please don't feed the animals.", /* Various zoos around the world */ 45.  	"....TCELES B HSUP   A magic spell?", /* Final Fantasy I (US) */ 46.  	"Madam, in Eden, I'm Adam.", /* A palindrome */ 47.  	"Two thumbs up!", /* Siskel & Ebert */ 48.  	"Hello, World!", /* The First Program line */ 49.  	"Turn around.", /* Various people at various times in history */ 50.  	"You've got mail!", /* AOL */ 51.  	"UY WUZ HERE", /* :] */ 52.  	"Time flies when you're having fun.", /* Who said this first, anyway? */ 53.   	"As if!", /* Clueless */ 54.  	"How bizarre, how bizarre.", /* OMC */ 55.  	"Silly rabbit, Trix are for kids!", /* Trix */ 56.   	"I'll be back!", /* Terminator */ 57.   	"That is not dead which can eternal lie.", /* HPL */ 58.  };  59.    60.   char * 61.  random_engraving(outbuf) 62.  char *outbuf; 63.  {  64.   	const char *rumor; 65.   66.   	/* a random engraving may come from the "rumors" file, 67.  	   or from the list above */ 68.  	if (!rn2(4) || !(rumor = getrumor(0, outbuf, TRUE)) || !*rumor) 69.  	    Strcpy(outbuf, random_mesg[rn2(SIZE(random_mesg))]); 70.   71.   	wipeout_text(outbuf, (int)(strlen(outbuf) / 4), 0); 72.  	return outbuf; 73.  }  74.    75.   /* Partial rubouts for engraving characters. -3. */ 76.   static const struct { 77.  	char		wipefrom; 78.  	const char *	wipeto; 79.  } rubouts[] = { 80.  	{'A', "^"},     {'B', "Pb["},   {'C', "("},     {'D', "|)["}, 81.  	{'E', "|FL[_"}, {'F', "|-"},    {'G', "C("},    {'H', "|-"},  82.   	{'I', "|"},     {'K', "|<"},    {'L', "|_"},    {'M', "|"},  83.   	{'N', "|\\"},   {'O', "C("},    {'P', "F"},     {'Q', "C("},  84.   	{'R', "PF"},    {'T', "|"},     {'U', "J"},     {'V', "/\\"},  85.   	{'W', "V/\\"},  {'Z', "/"},  86.   	{'b', "|"},     {'d', "c|"},    {'e', "c"},     {'g', "c"},  87.   	{'h', "n"},     {'j', "i"},     {'k', "|"},     {'l', "|"},  88.   	{'m', "nr"},    {'n', "r"},     {'o', "c"},     {'q', "c"},  89.   	{'w', "v"},     {'y', "v"},  90.   	{':', "."},     {';', ","},  91.   	{'0', "C("},    {'1', "|"},     {'6', "o"},     {'7', "/"}, 92.  	{'8', "3o"} 93.  };  94.    95.   void 96.  wipeout_text(engr, cnt, seed) 97.  char *engr; 98.  int cnt; 99.  unsigned seed;		/* for semi-controlled randomization */ 100. {  101.  	char *s; 102. 	int i, j, nxt, use_rubout, lth = (int)strlen(engr); 103.  104.  	if (lth && cnt > 0) { 105. 	    while (cnt--) { 106. 		/* pick next character */ 107. 		if (!seed) { 108. 		    /* random */ 109. 		    nxt = rn2(lth); 110. 		    use_rubout = rn2(4); 111. 		} else { 112. 		    /* predictable; caller can reproduce the same sequence by  113. supplying the same arguments later, or a pseudo-random 114. 		       sequence by varying any of them */ 115. 		    nxt = seed % lth; 116. 		    seed *= 31,  seed %= (BUFSZ-1); 117. 		    use_rubout = seed & 3; 118. 		}  119.  		s = &engr[nxt]; 120. 		if (*s == ' ') continue; 121.  122.  		/* rub out unreadable & small punctuation marks */ 123. 		if (index("?.,'`-|_", *s)) { 124. 		    *s = ' '; 125. 		    continue; 126. 		}  127.   128.  		if (!use_rubout) 129. 		    i = SIZE(rubouts); 130. 		else 131. 		    for (i = 0; i < SIZE(rubouts); i++) 132. 			if (*s == rubouts[i].wipefrom) { 133. 			    /*  134.  			     * Pick one of the substitutes at random. 135. 			     */  136.  			    if (!seed) 137. 				j = rn2(strlen(rubouts[i].wipeto)); 138. 			    else { 139. 				seed *= 31,  seed %= (BUFSZ-1); 140. 				j = seed % (strlen(rubouts[i].wipeto)); 141. 			    }  142.  			    *s = rubouts[i].wipeto[j]; 143. 			    break; 144. 			}  145.   146.  		/* didn't pick rubout; use '?' for unreadable character */ 147. 		if (i == SIZE(rubouts)) *s = '?'; 148. 	    }  149.  	}  150.   151.  	/* trim trailing spaces */ 152. 	while (lth && engr[lth-1] == ' ') engr[--lth] = 0; 153. }  154.   155.  boolean 156. can_reach_floor 157. {  158.  	return (boolean)(!u.uswallow &&  159.  #ifdef STEED  160.  			/* Restricted/unskilled riders can't reach the floor */  161.  			!(u.usteed && P_SKILL(P_RIDING) < P_BASIC) &&  162.  #endif  163.  			 (!Levitation || 164. 			  Is_airlevel(&u.uz) || Is_waterlevel(&u.uz))); 165. }  166.  #endif /* OVLB */ 167. #ifdef OVL0 168.  169.  const char * 170. surface(x, y)  171. register int x, y; 172. { 173.  	register struct rm *lev = &levl[x][y]; 174.  175.  	if ((x == u.ux) && (y == u.uy) && u.uswallow &&  176.  		is_animal(u.ustuck->data)) 177. 	    return "maw"; 178. 	else if (IS_AIR(lev->typ) && Is_airlevel(&u.uz)) 179. 	    return "air"; 180. 	else if (is_pool(x,y)) 181. 	    return (Underwater && !Is_waterlevel(&u.uz)) ? "bottom" : "water"; 182. 	else if (is_ice(x,y)) 183. 	    return "ice"; 184. 	else if (is_lava(x,y)) 185. 	    return "lava"; 186. 	else if (lev->typ == DRAWBRIDGE_DOWN) 187. 	    return "bridge"; 188. 	else if(IS_ALTAR(levl[x][y].typ)) 189. 	    return "altar"; 190. 	else if(IS_GRAVE(levl[x][y].typ)) 191. 	    return "headstone"; 192. 	else if(IS_FOUNTAIN(levl[x][y].typ)) 193. 	    return "fountain"; 194. 	else if ((IS_ROOM(lev->typ) && !Is_earthlevel(&u.uz)) ||  195.  		 IS_WALL(lev->typ) || IS_DOOR(lev->typ) || lev->typ == SDOOR) 196. 	    return "floor"; 197. 	else 198. 	    return "ground"; 199. }  200.   201.  const char * 202. ceiling(x, y)  203. register int x, y; 204. { 205.  	register struct rm *lev = &levl[x][y]; 206. 	const char *what; 207.  208.  	/* other room types will no longer exist when we're interested -- 209. 	 * see check_special_room 210. 	 */  211.  	if (*in_rooms(x,y,VAULT)) 212. 	    what = "vault's ceiling"; 213. 	else if (*in_rooms(x,y,TEMPLE)) 214. 	    what = "temple's ceiling"; 215. 	else if (*in_rooms(x,y,SHOPBASE)) 216. 	    what = "shop's ceiling"; 217. 	else if (IS_AIR(lev->typ)) 218. 	    what = "sky"; 219. 	else if (Underwater) 220. 	    what = "water's surface"; 221. 	else if ((IS_ROOM(lev->typ) && !Is_earthlevel(&u.uz)) ||  222.  		 IS_WALL(lev->typ) || IS_DOOR(lev->typ) || lev->typ == SDOOR) 223. 	    what = "ceiling"; 224. 	else 225. 	    what = "rock above"; 226.  227.  	return what; 228. }  229.   230.  struct engr * 231. engr_at(x, y)  232. xchar x, y; 233. { 234.  	register struct engr *ep = head_engr; 235.  236.  	while(ep) { 237. 		if(x == ep->engr_x && y == ep->engr_y) 238. 			return(ep); 239. 		ep = ep->nxt_engr; 240. 	}  241.  	return((struct engr *) 0); 242. }  243.   244.  #ifdef ELBERETH 245. /* Decide whether a particular string is engraved at a specified 246.  * location; a case-insensitive substring match used. 247.  * Ignore headstones, in case the player names herself "Elbereth". 248.  */  249.  int 250. sengr_at(s, x, y)  251. const char *s; 252. 	xchar x, y;  253. { 254.  	register struct engr *ep = engr_at(x,y); 255.  256.  	return (ep && ep->engr_type != HEADSTONE &&  257.  		ep->engr_time <= moves && strstri(ep->engr_txt, s) != 0); 258. }  259.  #endif /* ELBERETH */ 260.  261.  #endif /* OVL0 */ 262. #ifdef OVL2 263.  264.  void 265. u_wipe_engr(cnt) 266. register int cnt; 267. {  268.  	if (can_reach_floor) 269. 		wipe_engr_at(u.ux, u.uy, cnt); 270. }  271.   272.  #endif /* OVL2 */ 273. #ifdef OVL1 274.  275.  void 276. wipe_engr_at(x,y,cnt) 277. register xchar x,y,cnt; 278. {  279.  	register struct engr *ep = engr_at(x,y); 280.  281.  	/* Headstones are indelible */ 282. 	if(ep && ep->engr_type != HEADSTONE){ 283. 	    if(ep->engr_type != BURN || is_ice(x,y)) { 284. 		if(ep->engr_type != DUST && ep->engr_type != ENGR_BLOOD) { 285. 			cnt = rn2(1 + 50/(cnt+1)) ? 0 : 1; 286.  		}  287.  		wipeout_text(ep->engr_txt, (int)cnt, 0); 288. 		while(ep->engr_txt[0] == ' ') 289. 			ep->engr_txt++; 290. 		if(!ep->engr_txt[0]) del_engr(ep); 291. 	    }  292.  	}  293.  }  294.   295.  #endif /* OVL1 */ 296. #ifdef OVL2 297.  298.  boolean 299. sense_engr_at(x,y,read_it) 300. register int x,y; 301. boolean read_it; /* Read any sensed engraving */ 302. {  303.  	register struct engr *ep = engr_at(x,y); 304. 	register int	sensed = 0; 305. 	char buf[BUFSZ]; 306. 	  307.  	/* Sensing an engraving does not require sight, 308. 	 * nor does it necessarily imply comprehension (literacy). 309. 	 */  310.  	if(ep && ep->engr_txt[0]) { 311. 	    switch(ep->engr_type) { 312. 	    case DUST: 313. 		if(!Blind) { 314. 			sensed = 1; 315. 			pline("%s is written here in the %s.", Something,  316.  				is_ice(x,y) ? "frost" : "dust"); 317. 		}  318.  		break; 319. 	    case ENGRAVE: 320. 	    case HEADSTONE: 321. 		if (!Blind || can_reach_floor) { 322. 			sensed = 1; 323. 			pline("%s is engraved here on the %s.",  324.  				Something,  325.  				surface(x,y)); 326. 		}  327.  		break; 328. 	    case BURN: 329. 		if (!Blind || can_reach_floor) { 330. 			sensed = 1; 331. 			pline("Some text has been %s into the %s here.",  332.  				is_ice(x,y) ? "melted" : "burned",  333.  				surface(x,y)); 334. 		}  335.  		break; 336. 	    case MARK: 337. 		if(!Blind) { 338. 			sensed = 1; 339. 			pline("There's some graffiti on the %s here.",  340.  				surface(x,y)); 341. 		}  342.  		break; 343. 	    case ENGR_BLOOD: 344. 		/* "It's a message!  Scrawled in blood!" 345. 		 * "What's it say?" 346. 		 * "It says... `See you next Wednesday.'" -- Thriller 347. 		 */  348.  		if(!Blind) { 349. 			sensed = 1; 350. 			You("see a message scrawled in blood here."); 351. 		}  352.  		break; 353. 	    default: 354. 		impossible("%s is written in a very strange way.",  355.  				Something); 356. 		sensed = 1; 357. 	    }  358.  	    if (sensed && !read_it &&  359.  			    flags.suppress_alert < FEATURE_NOTICE_VER(0,0,7)) { 360. 		pline("Use \"r.\" to read it."); 361. 	    } else if (sensed && read_it) { 362. 	    	char *et; 363. 	    	unsigned len, maxelen = BUFSZ - sizeof("You feel the words: \"\". "); 364. 	    	len = strlen(ep->engr_txt); 365. 	    	if (len > maxelen) { 366. 	    		(void)strncpy(buf,  ep->engr_txt, (int)maxelen); 367. 			buf[maxelen] = '\0'; 368. 			et = buf; 369. 		} else 370. 			et = ep->engr_txt; 371.  372.  		/* If you can engrave an 'x', you can "read" it --ALI */ 373. 		if (len != 1 || (!index(et, 'x') && !index(et, 'X'))) 374. 			u.uconduct.literate++; 375.  376.  		You("%s: \"%s\".",  377.  		      (Blind) ? "feel the words" : "read",  et); 378. 		if(flags.run > 1) nomul(0); 379. 		return TRUE; 380. 	    }  381.  	}  382.  	return FALSE; 383. }  384.   385.  #endif /* OVL2 */ 386. #ifdef OVLB 387.  388.  void 389. make_engr_at(x,y,s,e_time,e_type) 390. register int x,y; 391. register const char *s; 392. register long e_time; 393. register xchar e_type; 394. {  395.  	register struct engr *ep; 396.  397.  	if ((ep = engr_at(x,y)) != 0) 398. 	    del_engr(ep); 399. 	ep = newengr(strlen(s) + 1); 400. 	ep->nxt_engr = head_engr; 401. 	head_engr = ep; 402. 	ep->engr_x = x;  403. ep->engr_y = y; 404. ep->engr_txt = (char *)(ep + 1); 405. 	Strcpy(ep->engr_txt, s); 406. 	/* engraving Elbereth shows wisdom */ 407. 	if (!in_mklev && !strcmp(s, "Elbereth")) exercise(A_WIS, TRUE); 408. 	ep->engr_time = e_time; 409. 	ep->engr_type = e_type > 0 ? e_type : rnd(N_ENGRAVE-1); 410. 	ep->engr_lth = strlen(s) + 1; 411. }  412.   413.  /* delete any engraving at location  */ 414. void 415. del_engr_at(x, y)  416. int x, y; 417. { 418.  	register struct engr *ep = engr_at(x, y); 419.  420.  	if (ep) del_engr(ep); 421. }  422.   423.  /*  424.   *	freehand - returns true if player has a free hand 425.  */  426.  int 427. freehand 428. {  429.  	return(!uwep || !welded(uwep) ||  430.  	   (!bimanual(uwep) && (!uarms || !uarms->cursed))); 431. /*	if ((uwep && bimanual(uwep)) ||  432.  	    (uwep && uarms)) 433. 		return(0); 434. 	else 435. 		return(1);*/ 436. }  437.   438.  static NEARDATA const char styluses[] = 439. 	{ ALL_CLASSES, ALLOW_NONE, TOOL_CLASS, WEAPON_CLASS, WAND_CLASS, 440. 	  GEM_CLASS, RING_CLASS, 0 }; 441.  442.  /* Mohs' Hardness Scale: 443.  *  1 - Talc		 6 - Orthoclase 444.  *  2 - Gypsum		 7 - Quartz 445.  *  3 - Calcite		 8 - Topaz 446.  *  4 - Fluorite	 9 - Corundum 447.  *  5 - Apatite		10 - Diamond 448.  *  449.   * Since granite is a igneous rock hardness ~ 7, anything >= 8 should 450.  * probably be able to scratch the rock. 451.  * Devaluation of less hard gems is not easily possible because obj struct 452.  * does not contain individual oc_cost currently. 7/91 453.   *  454.   * steel     -	5-8.5	(usu. weapon) 455.  * diamond    - 10			* jade	     -	5-6	 (nephrite) 456.  * ruby       -  9	(corundum)	* turquoise  -	5-6 457.  * sapphire   -  9	(corundum)	* opal	     -	5-6 458.  * topaz      -  8			* glass      - ~5.5 459.  * emerald    -  7.5-8	(beryl)		* dilithium  -	4-5?? 460.  * aquamarine -  7.5-8	(beryl)		* iron	     -	4-5 461.  * garnet     -  7.25	(var. 6.5-8)	* fluorite   -	4 462.  * agate      -  7	(quartz)	* brass      -	3-4 463.  * amethyst   -  7	(quartz)	* gold	     -	2.5-3 464.  * jasper     -  7	(quartz)	* silver     -	2.5-3 465.  * onyx       -  7	(quartz)	* copper     -	2.5-3 466.  * moonstone  -  6	(orthoclase)	* amber      -	2-2.5 467.  */  468.   469.  /* return 1 if action took 1 (or more) moves, 0 if error or aborted */ 470. int 471. doengrave 472. {  473.  	boolean dengr = FALSE;	/* TRUE if we wipe out the current engraving */ 474. 	boolean doblind = FALSE;/* TRUE if engraving blinds the player */ 475. 	boolean doknown = FALSE;/* TRUE if we identify the stylus */ 476. 	boolean eow = FALSE;	/* TRUE if we are overwriting oep */ 477. 	boolean jello = FALSE;	/* TRUE if we are engraving in slime */ 478. 	boolean ptext = TRUE;	/* TRUE if we must prompt for engrave text */ 479. 	boolean teleengr =FALSE;/* TRUE if we move the old engraving */ 480. 	boolean zapwand = FALSE;/* TRUE if we remove a wand charge */ 481. 	xchar type = DUST;	/* Type of engraving made */ 482. 	char buf[BUFSZ];	/* Buffer for final/poly engraving text */ 483. 	char ebuf[BUFSZ];	/* Buffer for initial engraving text */ 484. 	char qbuf[QBUFSZ];	/* Buffer for query text */ 485. 	char post_engr_text[BUFSZ]; /* Text displayed after engraving prompt */ 486. 	const char *everb;	/* Present tense of engraving type */ 487. 	const char *eloc;	/* Where the engraving is (ie dust/floor/...) */ 488. 	char *sp;		/* Place holder for space count of engr text */ 489. 	int len;		/* # of nonspace chars of new engraving text */ 490. 	int maxelen;		/* Max allowable length of engraving text */ 491. 	struct engr *oep = engr_at(u.ux,u.uy); 492. 				/* The current engraving */ 493. 	struct obj *otmp;	/* Object selected with which to engrave */ 494. 	char *writer; 495.  496.  	multi = 0;		/* moves consumed */ 497. 	nomovemsg = (char *)0;	/* occupation end message */ 498.  499.  	buf[0] = (char)0; 500. 	ebuf[0] = (char)0; 501. 	post_engr_text[0] = (char)0; 502. 	maxelen = BUFSZ - 1; 503. 	if (is_demon(youmonst.data) || youmonst.data->mlet == S_VAMPIRE) 504. 	    type = ENGR_BLOOD; 505.  506.  	/* Can the adventurer engrave at all? */ 507.   508.  	if(u.uswallow) { 509. 		if (is_animal(u.ustuck->data)) { 510. 			pline("What would you write?  \"Jonah was here\"?"); 511. 			return(0); 512. 		} else if (is_whirly(u.ustuck->data)) { 513. 			You_cant("reach the %s.", surface(u.ux,u.uy)); 514. 			return(0); 515. 		} else 516. 			jello = TRUE; 517. 	} else if (is_lava(u.ux, u.uy)) { 518. 		You_cant("write on the lava!"); 519. 		return(0); 520. 	} else if (is_pool(u.ux,u.uy) || IS_FOUNTAIN(levl[u.ux][u.uy].typ)) { 521. 		You_cant("write on the water!"); 522. 		return(0); 523. 	}  524.  	if(Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)/* in bubble */) { 525. 		You_cant("write in thin air!"); 526. 		return(0); 527. 	}  528.  	if (cantwield(youmonst.data)) { 529. 		You_cant("even hold anything!"); 530. 		return(0); 531. 	}  532.  	if (check_capacity((char *)0)) return (0); 533.  534.  	/* One may write with finger, or weapon, or wand, or..., or...  535. * Edited by GAN 10/20/86 so as not to change weapon wielded. 536. 	 */  537.   538.  	otmp = getobj(styluses, "write with"); 539. 	if(!otmp) return(0);		/* otmp == zeroobj if fingers */ 540.  541.  	if (otmp == &zeroobj) writer = makeplural(body_part(FINGER)); 542. 	else writer = xname(otmp); 543.  544.  	/* There's no reason you should be able to write with a wand 545. 	 * while both your hands are tied up. 546. 	 */  547.  	if (!freehand && otmp != uwep && !otmp->owornmask) { 548. 		You("have no free %s to write with!", body_part(HAND)); 549. 		return(0); 550. 	}  551.   552.  	if (jello) { 553. 		You("tickle %s with your %s.", mon_nam(u.ustuck), writer); 554. 		Your("message dissolves..."); 555. 		return(0); 556. 	}  557.  	if (otmp->oclass != WAND_CLASS && !can_reach_floor) { 558. 		You_cant("reach the %s!", surface(u.ux,u.uy)); 559. 		return(0); 560. 	}  561.  	if (IS_ALTAR(levl[u.ux][u.uy].typ)) { 562. 		You("make a motion towards the altar with your %s.", writer); 563. 		altar_wrath(u.ux, u.uy); 564. 		return(0); 565. 	}  566.  	if (IS_GRAVE(levl[u.ux][u.uy].typ)) { 567. 	    if (otmp == &zeroobj) { /* using only finger */ 568. 		You("would only make a small smudge on the %s.",  569.  			surface(u.ux, u.uy)); 570. 		return(0); 571. 	    } else if (!levl[u.ux][u.uy].disturbed) { 572. 		You("disturb the undead!"); 573. 		levl[u.ux][u.uy].disturbed = 1; 574. 		(void) makemon(&mons[PM_GHOUL], u.ux, u.uy, NO_MM_FLAGS); 575. 		exercise(A_WIS, FALSE); 576. 		return(1); 577. 	    }  578.  	}  579.   580.  	/* SPFX for items */ 581.  582.  	switch (otmp->oclass) { 583. 	    default: 584. 	    case AMULET_CLASS: 585. 	    case CHAIN_CLASS: 586. 	    case POTION_CLASS: 587. 	    case COIN_CLASS: 588. 		break; 589.  590.  	    case RING_CLASS: 591. 		/* "diamond" rings and others should work */ 592. 	    case GEM_CLASS: 593. 		/* diamonds & other hard gems should work */ 594. 		if (objects[otmp->otyp].oc_tough) { 595. 			type = ENGRAVE; 596. 			break; 597. 		}  598.  		break; 599.  600.  	    case ARMOR_CLASS: 601. 		if (is_boots(otmp)) { 602. 			type = DUST; 603. 			break; 604. 		}  605.  		/* fall through */ 606. 	    /* Objects too large to engrave with */ 607. 	    case BALL_CLASS: 608. 	    case ROCK_CLASS: 609. 		You_cant("engrave with such a large object!"); 610. 		ptext = FALSE; 611. 		break; 612.  613.  	    /* Objects too silly to engrave with */ 614. 	    case FOOD_CLASS: 615. 	    case SCROLL_CLASS: 616. 	    case SPBOOK_CLASS: 617. 		Your("%s would get %s.", xname(otmp),  618.  			is_ice(u.ux,u.uy) ? "all frosty" : "too dirty"); 619. 		ptext = FALSE; 620. 		break; 621.  622.  	    case RANDOM_CLASS:	/* This should mean fingers */ 623. 		break; 624.  625.  	    /* The charge is removed from the wand before prompting for 626. 	     * the engraving text, because all kinds of setup decisions 627. 	     * and pre-engraving messages are based upon knowing what type 628. 	     * of engraving the wand is going to do. Also, the player 629. 	     * will have potentially seen "You wrest .." message, and 630. 	     * therefore will know they are using a charge. 631. 	     */  632.  	    case WAND_CLASS: 633. 		if (zappable(otmp)) { 634. 		    check_unpaid(otmp); 635. 		    zapwand = TRUE; 636. 		    if (Levitation) ptext = FALSE; 637.  638.  		    switch (otmp->otyp) { 639. 		    /* DUST wands */ 640. 		    default: 641. 			break; 642.  643.  			/* NODIR wands */ 644. 		    case WAN_LIGHT: 645. 		    case WAN_SECRET_DOOR_DETECTION: 646. 		    case WAN_CREATE_MONSTER: 647. 		    case WAN_CREATE_HORDE: 648. 		    case WAN_ENLIGHTENMENT: 649. 		    case WAN_WISHING: 650. 			zapnodir(otmp); 651. 			break; 652.  653.  			/* IMMEDIATE wands */ 654. 			/* If wand is "IMMEDIATE", remember to affect the 655. 			 * previous engraving even if turning to dust. 656. 			 */  657.  		    case WAN_STRIKING: 658. 			Strcpy(post_engr_text,  659.  			"The wand unsuccessfully fights your attempt to write!"  660.  			); 661. 			break; 662. 		    case WAN_SLOW_MONSTER: 663. 			if (!Blind) { 664. 			   Sprintf(post_engr_text,  665.  				   "The bugs on the %s slow down!",  666.  				   surface(u.ux, u.uy)); 667. 			}  668.  			break; 669. 		    case WAN_SPEED_MONSTER: 670. 			if (!Blind) { 671. 			   Sprintf(post_engr_text,  672.  				   "The bugs on the %s speed up!",  673.  				   surface(u.ux, u.uy)); 674. 			}  675.  			break; 676. 		    case WAN_HEALING: 677. 		    case WAN_EXTRA_HEALING: 678. 			if (!Blind) { 679. 			   Sprintf(post_engr_text,  680.  				   "The bugs on the %s look healthier!",  681.  				   surface(u.ux, u.uy)); 682. 			}  683.  			break; 684. 		    case WAN_FEAR: 685. 			if (!Blind) { 686. 			   Sprintf(post_engr_text,  687.  				   "The bugs on the %s run away!",  688.  				   surface(u.ux, u.uy)); 689. 			}  690.  			break; 691. 		    case WAN_POLYMORPH: 692. 			if(oep)  { 693. 			    if (!Blind) { 694. 				type = (xchar)0;	/* random */ 695. 				(void) random_engraving(buf); 696. 			    }  697.  			    dengr = TRUE; 698. 			}  699.  			break; 700. 		    case WAN_DRAINING:	/* KMH */ 701. 			if (oep) { 702. 			    /*  703.  			     * [ALI] Wand of draining give messages like 704. 			     * either polymorph or cancellation/make 705. 			     * invisible depending on whether the 706. 			     * old engraving is completely wiped or not. 707. 			     * Note: Blindness has slightly different 708. 			     * effect than with wand of polymorph. 709. 			     */  710.  			    u_wipe_engr(5); 711. 			    oep = engr_at(u.ux,u.uy); 712. 			    if (!Blind) { 713. 				if (!oep) 714. 				    pline_The("engraving on the %s vanishes!",  715.  				      surface(u.ux,u.uy)); 716. 				else { 717. 				    strcpy(buf, oep->engr_txt); 718. 				    dengr = TRUE; 719. 				}  720.  			    }  721.  			}  722.  			break; 723. 		    case WAN_NOTHING: 724. 		    case WAN_UNDEAD_TURNING: 725. 		    case WAN_OPENING: 726. 		    case WAN_LOCKING: 727. 		    case WAN_PROBING: 728. 			break; 729.  730.  			/* RAY wands */ 731. 		    case WAN_MAGIC_MISSILE: 732. 			ptext = TRUE; 733. 			if (!Blind) { 734. 			   Sprintf(post_engr_text,  735.  				   "The %s is riddled by bullet holes!",  736.  				   surface(u.ux, u.uy)); 737. 			}  738.  			break; 739.  740.  		    /* can't tell sleep from death - Eric Backus */ 741. 		    case WAN_SLEEP: 742. 		    case WAN_DEATH: 743. 			if (!Blind) { 744. 			   Sprintf(post_engr_text,  745.  				   "The bugs on the %s stop moving!",  746.  				   surface(u.ux, u.uy)); 747. 			}  748.  			break; 749.  750.  		    case WAN_COLD: 751. 			if (!Blind) 752. 			    Strcpy(post_engr_text,  753.  				"A few ice cubes drop from the wand."); 754. 			if(!oep || (oep->engr_type != BURN)) 755. 			    break; 756. 		    case WAN_CANCELLATION: 757. 		    case WAN_MAKE_INVISIBLE: 758. 			if (oep && oep->engr_type != HEADSTONE) { 759. 			    if (!Blind) 760. 				pline_The("engraving on the %s vanishes!",  761.  					surface(u.ux,u.uy)); 762. 			    dengr = TRUE; 763. 			}  764.  			break; 765. 		    case WAN_TELEPORTATION: 766. 			if (oep && oep->engr_type != HEADSTONE) { 767. 			    if (!Blind) 768. 				pline_The("engraving on the %s vanishes!",  769.  					surface(u.ux,u.uy)); 770. 			    teleengr = TRUE; 771. 			}  772.  			break; 773.  774.  		    /* type = ENGRAVE wands */ 775. 		    case WAN_DIGGING: 776. 			ptext = TRUE; 777. 			type  = ENGRAVE; 778. 			if(!objects[otmp->otyp].oc_name_known) { 779. 			    if (flags.verbose) 780. 				pline("This %s is a wand of digging!",  781.  				xname(otmp)); 782. 			    doknown = TRUE; 783. 			}  784.  			if (!Blind) 785. 			    Strcpy(post_engr_text,  786.  				IS_GRAVE(levl[u.ux][u.uy].typ) ?  787.  				"Chips fly out from the headstone." :  788.  				is_ice(u.ux,u.uy) ?  789.  				"Ice chips fly up from the ice surface!" :  790.  				"Gravel flies up from the floor."); 791. 			else 792. 			    Strcpy(post_engr_text, "You hear drilling!"); 793. 			break; 794.  795.  		    /* type = BURN wands */ 796. 		    case WAN_FIRE: 797. 			ptext = TRUE; 798. 			type  = BURN; 799. 			if(!objects[otmp->otyp].oc_name_known) { 800. 			if (flags.verbose) 801. 			    pline("This %s is a wand of fire!", xname(otmp)); 802. 			    doknown = TRUE; 803. 			}  804.  			Strcpy(post_engr_text,  805.  				Blind ? "You feel the wand heat up." :  806.  					"Flames fly from the wand."); 807. 			break; 808. 		    case WAN_FIREBALL: 809. 			ptext = TRUE; 810. 			type  = BURN; 811. 			if(!objects[otmp->otyp].oc_name_known) { 812. 			if (flags.verbose) 813. 			    pline("This %s is a wand of fireballs!", xname(otmp)); 814. 			    doknown = TRUE; 815. 			}  816.  			Strcpy(post_engr_text,  817.  				Blind ? "You feel the wand heat up." :  818.  					"Flames fly from the wand."); 819. 			break; 820. 		    case WAN_LIGHTNING: 821. 			ptext = TRUE; 822. 			type  = BURN; 823. 			if(!objects[otmp->otyp].oc_name_known) { 824. 			    if (flags.verbose) 825. 				pline("This %s is a wand of lightning!",  826.  					xname(otmp)); 827. 			    doknown = TRUE; 828. 			}  829.  			if (!Blind) { 830. 			    Strcpy(post_engr_text,  831.  				    "Lightning arcs from the wand."); 832. 			    doblind = TRUE; 833. 			} else 834. 			    Strcpy(post_engr_text, "You hear crackling!"); 835. 			break; 836.  837.  		    /* type = MARK wands */ 838. 		    /* type = ENGR_BLOOD wands */ 839. 		    }  840.  		} else /* end if zappable */ 841. 		    if (!can_reach_floor) { 842. 			You_cant("reach the %s!", surface(u.ux,u.uy)); 843. 			return(0); 844. 		    }  845.  		break; 846.  847.  	    case WEAPON_CLASS: 848. 		if(is_blade(otmp)) { 849. 		    if ((int)otmp->spe > -3) 850. 			type = ENGRAVE; 851. 		    else 852. 			Your("%s too dull for engraving.", aobjnam(otmp,"are")); 853. 		}  854.  		break; 855.  856.  	    case TOOL_CLASS: 857. 		if(otmp == ublindf) { 858. 		    pline(  859.  		"That is a bit difficult to engrave with, don't you think?"); 860. 		    return(0); 861. 		}  862.   863.  #ifdef LIGHTSABERS 864. 		if (is_lightsaber(otmp)) { 865. 		    if (otmp->lamplit) type = BURN; 866. 		    else Your("%s is deactivated!", aobjnam(otmp,"are")); 867. 		} else 868. #endif 869. 		switch (otmp->otyp)  { 870. 		    case MAGIC_MARKER: 871. 			if (otmp->spe <= 0) 872. 			    Your("marker has dried out."); 873. 			else 874. 			    type = MARK; 875. 			break; 876. 		    case TOWEL: 877. 			/* Can't really engrave with a towel */ 878. 			ptext = FALSE; 879. 			if (oep) 880. 			    if ((oep->engr_type == DUST ) ||  881.  				(oep->engr_type == ENGR_BLOOD) ||  882.  				(oep->engr_type == MARK )) { 883. 				if (!Blind) 884. 				    You("wipe out the message here."); 885. 				else 886. 				    Your("%s %s %s.", xname(otmp),  887.  					 otense(otmp, "get"),  888.  					 is_ice(u.ux,u.uy) ?  889.  					 "frosty" : "dusty"); 890. 				dengr = TRUE; 891. 			    } else 892. 				Your("%s can't wipe out this engraving.",  893.  				     xname(otmp)); 894. 			else 895. 			    Your("%s %s %s.", xname(otmp), otense(otmp, "get"),  896.  				  is_ice(u.ux,u.uy) ? "frosty" : "dusty"); 897. 			break; 898. 		    default: 899. 			break; 900. 		}  901.  		break; 902.  903.  	    case VENOM_CLASS: 904. #ifdef WIZARD 905. 		if (wizard) { 906. 		    pline("Writing a poison pen letter??"); 907. 		    break; 908. 		}  909.  #endif 910. 	    case ILLOBJ_CLASS: 911. 		impossible("You're engraving with an illegal object!"); 912. 		break; 913. 	}  914.   915.  	if (IS_GRAVE(levl[u.ux][u.uy].typ)) { 916. 	    if (type == ENGRAVE || type == 0) 917. 		type = HEADSTONE; 918. 	    else { 919. 		/* ensures the "cannot wipe out" case */ 920. 		type = DUST; 921. 		dengr = FALSE; 922. 		teleengr = FALSE; 923. 		buf[0] = (char)0; 924. 	    }  925.  	}  926.   927.  	/* End of implement setup */ 928.  929.  	/* Identify stylus */ 930. 	if (doknown) { 931. 	    makeknown(otmp->otyp); 932. 	    more_experienced(0,10); 933. 	}  934.   935.  	if (teleengr) { 936. 	    rloc_engr(oep); 937. 	    oep = (struct engr *)0; 938. 	}  939.   940.  	if (dengr) { 941. 	    del_engr(oep); 942. 	    oep = (struct engr *)0; 943. 	}  944.   945.  	/* Something has changed the engraving here */ 946. 	if (*buf) { 947. 	    make_engr_at(u.ux, u.uy, buf, moves, type); 948. 	    pline_The("engraving looks different now."); 949. 	    ptext = FALSE; 950. 	}  951.   952.  	if (zapwand && (otmp->spe < 0)) { 953. 	    pline("%s %sturns to dust.",  954.  		  The(xname(otmp)), Blind ? "" : "glows violently, then "); 955. 	    if (!IS_GRAVE(levl[u.ux][u.uy].typ)) 956. 		You("are not going to get anywhere trying to write in the %s with your dust.",  957.  		    is_ice(u.ux,u.uy) ? "frost" : "dust"); 958. 	    useup(otmp); 959. 	    ptext = FALSE; 960. 	}  961.   962.  	if (!ptext) {		/* Early exit for some implements. */ 963.  	    if (otmp->oclass == WAND_CLASS && !can_reach_floor) 964. 		You_cant("reach the %s!", surface(u.ux,u.uy)); 965. 	    return(1); 966. 	}  967.   968.  	/* Special effects should have deleted the current engraving (if  969.  	 * possible) by now. 970. 	 */  971.   972.  	if (oep) { 973. 	    register char c = 'n'; 974.  975.  	    /* Give player the choice to add to engraving. */ 976.   977.  	    if (type == HEADSTONE) { 978. 		/* no choice, only append */ 979. 		c = 'y'; 980. 	    } else if ( (type == oep->engr_type) && (!Blind || 981. 		 (oep->engr_type == BURN) || (oep->engr_type == ENGRAVE)) ) { 982. 		c = yn_function("Do you want to add to the current engraving?",  983.  				ynqchars, 'y'); 984. 		if (c == 'q') { 985. 		    pline(Never_mind); 986. 		    return(0); 987. 		}  988.  	    }  989.   990.  	    if (c == 'n' || Blind) { 991.  992.  		if( (oep->engr_type == DUST) || (oep->engr_type == ENGR_BLOOD) ||  993.  		    (oep->engr_type == MARK) ) { 994. 		    if (!Blind) { 995. 			You("wipe out the message that was %s here.",  996.  			    ((oep->engr_type == DUST)  ? "written in the dust" : 997. 			    ((oep->engr_type == ENGR_BLOOD) ? "scrawled in blood"   :  998.  							 "written"))); 999. 			del_engr(oep); 1000. 			oep = (struct engr *)0; 1001. 		   } else 1002. 		  /* Don't delete engr until after we *know* we're engraving */ 1003. 			eow = TRUE; 1004. 		} else 1005. 		   if ( (type == DUST) || (type == MARK) || (type == ENGR_BLOOD) ) { 1006. 			You( 1007. 			 "cannot wipe out the message that is %s the %s here.",  1008. 			 oep->engr_type == BURN ?  1009. 			   (is_ice(u.ux,u.uy) ? "melted into" : "burned into") : 1010. 			   "engraved in", surface(u.ux,u.uy)); 1011. 			return(1); 1012. 		   } else 1013. 			if ( (type != oep->engr_type) || (c == 'n') ) { 1014. 			   if (!Blind || can_reach_floor) 1015. 				You("will overwrite the current message."); 1016. 			   eow = TRUE; 1017. 			} 1018. 	    }  1019. 	}  1020.  1021. 	eloc = surface(u.ux,u.uy); 1022. 	switch(type){ 1023. 	   default: 1024. 		everb = (oep && !eow ? "add to the weird writing on" : 1025. 				       "write strangely on"); 1026. 		break; 1027. 	   case DUST: 1028. 		everb = (oep && !eow ? "add to the writing in" : 1029. 				       "write in"); 1030. 		eloc = (is_ice(u.ux,u.uy) ? "frost" : "dust"); 1031. 		break; 1032. 	   case HEADSTONE: 1033. 		everb = (oep && !eow ? "add to the epitaph on" : 1034. 				       "engrave on"); 1035. 		break; 1036. 	   case ENGRAVE: 1037. 		everb = (oep && !eow ? "add to the engraving in" : 1038. 				       "engrave in"); 1039. 		break; 1040. 	   case BURN: 1041. 		everb = (oep && !eow ? 1042. 			( is_ice(u.ux,u.uy) ? "add to the text melted into" : 1043. 					     "add to the text burned into") :  1044. 			( is_ice(u.ux,u.uy) ? "melt into" : "burn into")); 1045. 		break; 1046. 	   case MARK: 1047. 		everb = (oep && !eow ? "add to the graffiti on" : 1048. 				       "scribble on"); 1049. 		break; 1050. 	   case ENGR_BLOOD: 1051. 		everb = (oep && !eow ? "add to the scrawl on" : 1052. 				       "scrawl on"); 1053. 		break; 1054. 	} 1055.  1056. 	/* Tell adventurer what is going on */ 1057. 	if (otmp != &zeroobj) 1058. 	   You("%s the %s with %s.", everb, eloc, doname(otmp)); 1059. 	else 1060. 	   You("%s the %s with your %s.", everb, eloc,  1061. 		makeplural(body_part(FINGER))); 1062. 1063. 	/* Prompt for engraving! */ 1064. 	Sprintf(qbuf,"What do you want to %s the %s here?", everb, eloc); 1065. 	getlin(qbuf, ebuf); 1066. 1067. 	/* Count the actual # of chars engraved not including spaces */ 1068. 	len = strlen(ebuf); 1069. 	for (sp = ebuf; *sp; sp++) if (isspace(*sp)) len -= 1; 1070. 1071. 	if (len == 0 || index(ebuf, '\033')) { 1072. 	   if (zapwand) { 1073. 		if (!Blind) 1074. 		   pline("%s, then %s.",  1075. 			  Tobjnam(otmp, "glow"), otense(otmp, "fade")); 1076. 		return(1); 1077. 	   } else { 1078. 		pline(Never_mind); 1079. 		return(0); 1080. 	   }  1081. 	}  1082.  1083. 	/* A single `x' is the traditional signature of an illiterate person */ 1084. 	if (len != 1 || (!index(ebuf, 'x') && !index(ebuf, 'X'))) 1085. 	   u.uconduct.literate++; 1086. 1087. 	/* Mix up engraving if surface or state of mind is unsound. 1088. 	  Note: this won't add or remove any spaces. */ 1089. 	for (sp = ebuf; *sp; sp++) { 1090. 	   if (isspace(*sp)) continue; 1091. 	   if (((type == DUST || type == ENGR_BLOOD) && !rn2(25)) ||  1092. 		    (Blind && !rn2(11)) || (Confusion && !rn2(7)) ||  1093. 		    (Stunned && !rn2(4)) || (Hallucination && !rn2(2))) 1094. 		*sp = ' ' + rnd(96 - 2);	/* ASCII '!' thru '~' 1095. 						  (excludes ' ' and DEL) */ 1096. 	} 1097.  1098. 	/* Previous engraving is overwritten */ 1099. 	if (eow) { 1100. 	   del_engr(oep); 1101. 	   oep = (struct engr *)0; 1102. 	} 1103.  1104. 	/* Figure out how long it took to engrave, and if player has 1105. 	 * engraved too much. 1106. 	 */ 1107. 	switch(type){ 1108. 	   default: 1109. 		multi = -(len/10); 1110. 		if (multi) nomovemsg = "You finish your weird engraving."; 1111. 		break; 1112. 	   case DUST: 1113. 		multi = -(len/10); 1114. 		if (multi) nomovemsg = "You finish writing in the dust."; 1115. 		break; 1116. 	   case HEADSTONE: 1117. 	   case ENGRAVE: 1118. 		multi = -(len/10); 1119. 		if ((otmp->oclass == WEAPON_CLASS) && 1120. 		    ((otmp->otyp != ATHAME) || otmp->cursed)) { 1121. 		   multi = -len; 1122. 		   maxelen = ((otmp->spe + 3) * 2) + 1; 1123. 			/* -2 = 3, -1 = 5, 0 = 7, +1 = 9, +2 = 11 1124. 			 * Note: this does not allow a +0 anything (except  1125. 			 *	 an athame) to engrave "Elbereth" all at once. 1126. 			 *	 However, you could now engrave "Elb", then 1127. 			 *	 "ere", then "th". 1128. 			 */ 1129. 		    Your("%s dull.", aobjnam(otmp, "get")); 1130. 		   if (otmp->unpaid) { 1131. 			struct monst *shkp = shop_keeper(*u.ushops); 1132. 			if (shkp) { 1133. 			   You("damage it, you pay for it!"); 1134. 			   bill_dummy_object(otmp); 1135. 			} 1136. 		    }  1137. 		    if (len > maxelen) { 1138. 			multi = -maxelen; 1139. 			otmp->spe = -3; 1140. 		   } else if (len > 1) 1141. 			otmp->spe -= len >> 1; 1142. 		   else otmp->spe -= 1; /* Prevent infinite engraving */ 1143. 		} else 1144. 		   if ( (otmp->oclass == RING_CLASS) ||  1145. 			 (otmp->oclass == GEM_CLASS) ) 1146. 			multi = -len; 1147. 		if (multi) nomovemsg = "You finish engraving."; 1148. 		break; 1149. 	   case BURN: 1150. 		multi = -(len/10); 1151. 		if (multi) 1152. 		   nomovemsg = is_ice(u.ux,u.uy) ? 1153. 			"You finish melting your message into the ice.": 1154. 			"You finish burning your message into the floor."; 1155. 		break; 1156. 	   case MARK: 1157. 		multi = -(len/10); 1158. 		if ((otmp->oclass == TOOL_CLASS) && 1159. 		    (otmp->otyp == MAGIC_MARKER)) { 1160. 		   maxelen = (otmp->spe) * 2; /* one charge / 2 letters */ 1161. 		   if (len > maxelen) { 1162. 			Your("marker dries out."); 1163. 			otmp->spe = 0; 1164. 			multi = -(maxelen/10); 1165. 		   } else 1166. 			if (len > 1) otmp->spe -= len >> 1; 1167. 			else otmp->spe -= 1; /* Prevent infinite grafitti */ 1168. 		} 1169. 		if (multi) nomovemsg = "You finish defacing the dungeon."; 1170. 		break; 1171. 	   case ENGR_BLOOD: 1172. 		multi = -(len/10); 1173. 		if (multi) nomovemsg = "You finish scrawling."; 1174. 		break; 1175. 	} 1176.  1177. 	/* Chop engraving down to size if necessary */ 1178. 	if (len > maxelen) { 1179. 	   for (sp = ebuf; (maxelen && *sp); sp++) 1180. 		if (!isspace((int)*sp)) maxelen--; 1181. 	   if (!maxelen && *sp) { 1182. 		*sp = (char)0; 1183. 		if (multi) nomovemsg = "You cannot write any more."; 1184. 		You("only are able to write \"%s\"", ebuf); 1185. 	   }  1186. 	}  1187.  1188. 	/* Add to existing engraving */ 1189. 	if (oep) Strcpy(buf, oep->engr_txt); 1190. 1191. 	(void) strncat(buf, ebuf, (BUFSZ - (int)strlen(buf) - 1)); 1192. 1193. 	make_engr_at(u.ux, u.uy, buf, (moves - multi), type); 1194. 1195. 	if (post_engr_text[0]) pline(post_engr_text); 1196. 1197. 	if (doblind && !resists_blnd(&youmonst)) { 1198. 	   You("are blinded by the flash!"); 1199. 	   make_blinded((long)rnd(50),FALSE); 1200. 	   if (!Blind) Your(vision_clears); 1201. 	} 1202.  1203. 	return(1); 1204. } 1205.  1206. void 1207. save_engravings(fd, mode) 1208. int fd, mode; 1209. { 1210. 	register struct engr *ep = head_engr; 1211. 	register struct engr *ep2; 1212. 	unsigned no_more_engr = 0; 1213. 1214. 	while (ep) { 1215. 	   ep2 = ep->nxt_engr; 1216. 	   if (ep->engr_lth && ep->engr_txt[0] && perform_bwrite(mode)) { 1217. 		bwrite(fd, (genericptr_t)&(ep->engr_lth), sizeof(ep->engr_lth)); 1218. 		bwrite(fd, (genericptr_t)ep, sizeof(struct engr) + ep->engr_lth); 1219. 	   }  1220. 	    if (release_data(mode)) 1221. 		dealloc_engr(ep); 1222. 	   ep = ep2; 1223. 	} 1224. 	if (perform_bwrite(mode)) 1225. 	   bwrite(fd, (genericptr_t)&no_more_engr, sizeof no_more_engr); 1226. 	if (release_data(mode)) 1227. 	   head_engr = 0; 1228. } 1229.  1230. void 1231. rest_engravings(fd) 1232. int fd; 1233. { 1234. 	register struct engr *ep; 1235. 	unsigned lth; 1236. 1237. 	head_engr = 0; 1238. 	while(1) { 1239. 		mread(fd, (genericptr_t) &lth, sizeof(unsigned)); 1240. 		if(lth == 0) return; 1241. 		ep = newengr(lth); 1242. 		mread(fd, (genericptr_t) ep, sizeof(struct engr) + lth); 1243. 		ep->nxt_engr = head_engr; 1244. 		head_engr = ep; 1245. 		ep->engr_txt = (char *) (ep + 1);	/* Andreas Bormann */ 1246. 		/* mark as finished for bones levels -- no problem for 1247. 		 * normal levels as the player must have finished engraving 1248. 		 * to be able to move again */ 1249. 		ep->engr_time = moves; 1250. 	} 1251. }  1252.  1253. void 1254. del_engr(ep) 1255. register struct engr *ep; 1256. { 1257. 	if (ep == head_engr) { 1258. 		head_engr = ep->nxt_engr; 1259. 	} else { 1260. 		register struct engr *ept; 1261. 1262. 		for (ept = head_engr; ept; ept = ept->nxt_engr) 1263. 		   if (ept->nxt_engr == ep) { 1264. 			ept->nxt_engr = ep->nxt_engr; 1265. 			break; 1266. 		   }  1267. 		if (!ept) { 1268. 		   impossible("Error in del_engr?"); 1269. 		   return; 1270. 		} 1271. 	}  1272. 	dealloc_engr(ep); 1273. } 1274.  1275. /* randomly relocate an engraving */ 1276. void 1277. rloc_engr(ep) 1278. struct engr *ep; 1279. { 1280. 	int tx, ty, tryct = 200; 1281. 1282. 	do  { 1283. 	   if (--tryct < 0) return; 1284. 	   tx = rn1(COLNO-3,2); 1285. 	   ty = rn2(ROWNO); 1286. 	} while (engr_at(tx, ty) || 1287. 		!goodpos(tx, ty, (struct monst *)0, 0)); 1288. 1289. 	ep->engr_x = tx; 1290. 	ep->engr_y = ty; 1291. } 1292.  1293.  1294. /* Epitaphs for random headstones */ 1295. static const char *epitaphs[] = { 1296. 	"Rest in peace", 1297. 	"R.I.P.", 1298. 	"Rest In Pieces", 1299. 	"Note -- there are NO valuable items in this grave", 1300. 	"1994-1995. The Longest-Lived Hacker Ever", 1301. 	"The Grave of the Unknown Hacker", 1302. 	"We weren't sure who this was, but we buried him here anyway", 1303. 	"Sparky -- he was a very good dog", 1304. 	"Beware of Electric Third Rail", 1305. 	"Made in Taiwan", 1306. 	"Og friend. Og good dude. Og died. Og now food", 1307. 	"Beetlejuice Beetlejuice Beetlejuice", 1308. 	"Look out below!", 1309. 	"Please don't dig me up. I'm perfectly happy down here. -- Resident", 1310. 	"Postman, please note forwarding address: Gehennom, Asmodeus's Fortress, fifth lemure on the left", 1311. 	"Mary had a little lamb/Its fleece was white as snow/When Mary was in trouble/The lamb was first to go", 1312. 	"Be careful, or this could happen to you!", 1313. 	"Soon you'll join this fellow in hell! -- the Wizard of Yendor", 1314. 	"Caution! This grave contains toxic waste", 1315. 	"Sum quod eris", 1316. 	"Here lies an Atheist, all dressed up and no place to go", 1317. 	"Here lies Ezekiel, age 102. The good die young.", 1318. 	"Here lies my wife: Here let her lie! Now she's at rest and so am I.", 1319. 	"Here lies Johnny Yeast. Pardon me for not rising.", 1320. 	"He always lied while on the earth and now he's lying in it", 1321. 	"I made an ash of myself", 1322. 	"Soon ripe. Soon rotten. Soon gone. But not forgotten.", 1323. 	"Here lies the body of Jonathan Blake. Stepped on the gas instead of the brake.", 1324. 	"Go away!", 1325. 	/* From SLASH'EM */ 1326. 	"This old man, he played one, he played knick-knack on my thumb." 1327. }; 1328.  1329. /* Create a headstone at the given location. 1330. * The caller is responsible for newsym(x, y). 1331. */  1332. void 1333. make_grave(x, y, str) 1334. int x, y; 1335. const char *str; 1336. { 1337. 	/* Can we put a grave here? */ 1338. 	if ((levl[x][y].typ != ROOM && levl[x][y].typ != GRAVE) || t_at(x,y)) return; 1339. 1340. 	/* Make the grave */ 1341. 	levl[x][y].typ = GRAVE; 1342. 1343. 	/* Engrave the headstone */ 1344. 	if (!str) str = epitaphs[rn2(SIZE(epitaphs))]; 1345. 	del_engr_at(x, y); 1346. 	make_engr_at(x, y, str, 0L, HEADSTONE); 1347. 	return; 1348. } 1349.  1350.  1351. #endif /* OVLB */ 1352. 1353. /*engrave.c*/