Source:NetHack 3.3.0/engrave.c

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

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

1.   /*	SCCS Id: @(#)engrave.c	3.3	1999/08/16	*/ 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.  };  37.    38.   char * 39.  random_engraving(outbuf) 40.  char *outbuf; 41.  {  42.   	const char *rumor; 43.   44.   	/* a random engraving may come from the "rumors" file, 45.  	   or from the list above */ 46.  	if (!rn2(4) || !(rumor = getrumor(0, outbuf)) || !*rumor) 47.  	    Strcpy(outbuf, random_mesg[rn2(SIZE(random_mesg))]); 48.   49.   	wipeout_text(outbuf, (int)(strlen(outbuf) / 4), 0); 50.  	return outbuf; 51.  }  52.    53.   /* Partial rubouts for engraving characters. -3. */ 54.   static const struct { 55.  	char		wipefrom; 56.  	const char *	wipeto; 57.  } rubouts[] = { 58.  	{'A', "^"},     {'B', "Pb["},   {'C', "("},     {'D', "|)["}, 59.  	{'E', "|FL[_"}, {'F', "|-"},    {'G', "C("},    {'H', "|-"},  60.   	{'I', "|"},     {'K', "|<"},    {'L', "|_"},    {'M', "|"},  61.   	{'N', "|\\"},   {'O', "C("},    {'P', "F"},     {'Q', "C("},  62.   	{'R', "PF"},    {'T', "|"},     {'U', "J"},     {'V', "/\\"},  63.   	{'W', "V/\\"},  {'Z', "/"},  64.   	{'b', "|"},     {'d', "c|"},    {'e', "c"},     {'g', "c"},  65.   	{'h', "n"},     {'j', "i"},     {'k', "|"},     {'l', "|"},  66.   	{'m', "nr"},    {'n', "r"},     {'o', "c"},     {'q', "c"},  67.   	{'w', "v"},     {'y', "v"},  68.   	{':', "."},     {';', ","},  69.   	{'0', "C("},    {'1', "|"},     {'6', "o"},     {'7', "/"}, 70.  	{'8', "3o"} 71.  };  72.    73.   void 74.  wipeout_text(engr, cnt, seed) 75.  char *engr; 76.  int cnt; 77.  unsigned seed;		/* for semi-controlled randomization */ 78.  {  79.   	char *s; 80.  	int i, j, nxt, use_rubout, lth = (int)strlen(engr); 81.   82.   	if (lth && cnt > 0) { 83.  	    while (cnt--) { 84.  		/* pick next character */ 85.  		if (!seed) { 86.  		    /* random */ 87.  		    nxt = rn2(lth); 88.  		    use_rubout = rn2(4); 89.  		} else { 90.  		    /* predictable; caller can reproduce the same sequence by  91. supplying the same arguments later, or a pseudo-random 92.  		       sequence by varying any of them */ 93.  		    nxt = seed % lth; 94.  		    seed *= 31,  seed %= (BUFSZ-1); 95.  		    use_rubout = seed & 3; 96.  		}  97.   		s = &engr[nxt]; 98.  		if (*s == ' ') continue; 99.   100.  		/* rub out unreadable & small punctuation marks */ 101. 		if (index("?.,'`-|_", *s)) { 102. 		    *s = ' '; 103. 		    continue; 104. 		}  105.   106.  		if (!use_rubout) 107. 		    i = SIZE(rubouts); 108. 		else 109. 		    for (i = 0; i < SIZE(rubouts); i++) 110. 			if (*s == rubouts[i].wipefrom) { 111. 			    /*  112.  			     * Pick one of the substitutes at random. 113. 			     */  114.  			    if (!seed) 115. 				j = rn2(strlen(rubouts[i].wipeto)); 116. 			    else { 117. 				seed *= 31,  seed %= (BUFSZ-1); 118. 				j = seed % (strlen(rubouts[i].wipeto)); 119. 			    }  120.  			    *s = rubouts[i].wipeto[j]; 121. 			    break; 122. 			}  123.   124.  		/* didn't pick rubout; use '?' for unreadable character */ 125. 		if (i == SIZE(rubouts)) *s = '?'; 126. 	    }  127.  	}  128.   129.  	/* trim trailing spaces */ 130. 	while (lth && engr[lth-1] == ' ') engr[--lth] = 0; 131. }  132.   133.  boolean 134. can_reach_floor 135. {  136.  	return (boolean)(!u.uswallow &&  137.  #ifdef STEED  138.  			/* Restricted/unskilled riders can't reach the floor */  139.  			!(u.usteed && P_SKILL(P_RIDING) < P_BASIC) &&  140.  #endif  141.  			 (!Levitation || 142. 			  Is_airlevel(&u.uz) || Is_waterlevel(&u.uz))); 143. }  144.  #endif /* OVLB */ 145. #ifdef OVL0 146.  147.  const char * 148. surface(x, y)  149. register int x, y; 150. { 151.  	register struct rm *lev = &levl[x][y]; 152.  153.  	if ((x == u.ux) && (y == u.uy) && u.uswallow &&  154.  		is_animal(u.ustuck->data)) 155. 	    return "maw"; 156. 	else if (IS_AIR(lev->typ)) 157. 	    return "air"; 158. 	else if (is_pool(x,y)) 159. 	    return "water"; 160. 	else if (is_ice(x,y)) 161. 	    return "ice"; 162. 	else if (is_lava(x,y)) 163. 	    return "lava"; 164. 	else if (lev->typ == DRAWBRIDGE_DOWN) 165. 	    return "bridge"; 166. 	else if(IS_ALTAR(levl[x][y].typ)) 167. 	    return "altar"; 168. 	else if ((IS_ROOM(lev->typ) && !Is_earthlevel(&u.uz)) ||  169.  		 IS_WALL(lev->typ) || IS_DOOR(lev->typ) || lev->typ == SDOOR) 170. 	    return "floor"; 171. 	else 172. 	    return "ground"; 173. }  174.   175.  const char * 176. ceiling(x, y)  177. register int x, y; 178. { 179.  	register struct rm *lev = &levl[x][y]; 180. 	const char *what; 181.  182.  	/* other room types will no longer exist when we're interested -- 183. 	 * see check_special_room 184. 	 */  185.  	if (*in_rooms(x,y,VAULT)) 186. 	    what = "vault's ceiling"; 187. 	else if (*in_rooms(x,y,TEMPLE)) 188. 	    what = "temple's ceiling"; 189. 	else if (*in_rooms(x,y,SHOPBASE)) 190. 	    what = "shop's ceiling"; 191. 	else if (IS_AIR(lev->typ)) 192. 	    what = "sky"; 193. 	else if (Underwater) 194. 	    what = "water's surface"; 195. 	else if ((IS_ROOM(lev->typ) && !Is_earthlevel(&u.uz)) ||  196.  		 IS_WALL(lev->typ) || IS_DOOR(lev->typ) || lev->typ == SDOOR) 197. 	    what = "ceiling"; 198. 	else 199. 	    what = "rock above"; 200.  201.  	return what; 202. }  203.   204.  struct engr * 205. engr_at(x, y)  206. xchar x, y; 207. { 208.  	register struct engr *ep = head_engr; 209.  210.  	while(ep) { 211. 		if(x == ep->engr_x && y == ep->engr_y) 212. 			return(ep); 213. 		ep = ep->nxt_engr; 214. 	}  215.  	return((struct engr *) 0); 216. }  217.   218.  #ifdef ELBERETH 219. /* decide whether a particular string is engraved at a specified location; 220.    a case-insensitive substring match used */ 221. int 222. sengr_at(s, x, y)  223. const char *s; 224. 	xchar x, y;  225. { 226.  	register struct engr *ep = engr_at(x,y); 227.  228.  	return (ep && ep->engr_time <= moves && strstri(ep->engr_txt, s) != 0); 229. }  230.  #endif /* ELBERETH */ 231.  232.  #endif /* OVL0 */ 233. #ifdef OVL2 234.  235.  void 236. u_wipe_engr(cnt) 237. register int cnt; 238. {  239.  	if (can_reach_floor) 240. 		wipe_engr_at(u.ux, u.uy, cnt); 241. }  242.   243.  #endif /* OVL2 */ 244. #ifdef OVL1 245.  246.  void 247. wipe_engr_at(x,y,cnt) 248. register xchar x,y,cnt; 249. {  250.  	register struct engr *ep = engr_at(x,y); 251.  252.  	if(ep){ 253. 	    if(ep->engr_type != BURN || is_ice(x,y)) { 254. 		if(ep->engr_type != DUST && ep->engr_type != BLOOD) { 255. 			cnt = rn2(1 + 50/(cnt+1)) ? 0 : 1; 256.  		}  257.  		wipeout_text(ep->engr_txt, (int)cnt, 0); 258. 		while(ep->engr_txt[0] == ' ') 259. 			ep->engr_txt++; 260. 		if(!ep->engr_txt[0]) del_engr(ep); 261. 	    }  262.  	}  263.  }  264.   265.  #endif /* OVL1 */ 266. #ifdef OVL2 267.  268.  void 269. read_engr_at(x,y) 270. register int x,y; 271. {  272.  	register struct engr *ep = engr_at(x,y); 273. 	register int	sensed = 0; 274.  275.  	if(ep && ep->engr_txt[0]) { 276. 	    switch(ep->engr_type) { 277. 	    case DUST: 278. 		if(!Blind) { 279. 			sensed = 1; 280. 			pline("%s is written here in the %s.", Something,  281.  				is_ice(x,y) ? "frost" : "dust"); 282. 		}  283.  		break; 284. 	    case ENGRAVE: 285. 		if (!Blind || can_reach_floor) { 286. 			sensed = 1; 287. 			pline("%s is engraved here on the %s.",  288.  				Something,  289.  				surface(x,y)); 290. 		}  291.  		break; 292. 	    case BURN: 293. 		if (!Blind || can_reach_floor) { 294. 			sensed = 1; 295. 			pline("Some text has been %s into the %s here.",  296.  				is_ice(x,y) ? "melted" : "burned",  297.  				surface(x,y)); 298. 		}  299.  		break; 300. 	    case MARK: 301. 		if(!Blind) { 302. 			sensed = 1; 303. 			pline("There's some graffiti on the %s here.",  304.  				surface(x,y)); 305. 		}  306.  		break; 307. 	    case BLOOD: 308. 		/* "It's a message!  Scrawled in blood!" 309. 		 * "What's it say?" 310. 		 * "It says... `See you next Wednesday.'" -- Thriller 311. 		 */  312.  		if(!Blind) { 313. 			sensed = 1; 314. 			You("see a message scrawled in blood here."); 315. 		}  316.  		break; 317. 	    default: 318. 		impossible("%s is written in a very strange way.",  319.  				Something); 320. 		sensed = 1; 321. 	    }  322.  	    if (sensed) { 323. 		You("%s: \"%s\".",  324.  		      (Blind) ? "feel the words" : "read",  ep->engr_txt); 325. 		if(flags.run > 1) nomul(0); 326. 	    }  327.  	}  328.  }  329.   330.  #endif /* OVL2 */ 331. #ifdef OVLB 332.  333.  void 334. make_engr_at(x,y,s,e_time,e_type) 335. register int x,y; 336. register const char *s; 337. register long e_time; 338. register xchar e_type; 339. {  340.  	register struct engr *ep; 341.  342.  	if ((ep = engr_at(x,y)) != 0) 343. 	    del_engr(ep); 344. 	ep = newengr(strlen(s) + 1); 345. 	ep->nxt_engr = head_engr; 346. 	head_engr = ep; 347. 	ep->engr_x = x;  348. ep->engr_y = y; 349. ep->engr_txt = (char *)(ep + 1); 350. 	Strcpy(ep->engr_txt, s); 351. 	if(strcmp(s, "Elbereth")) exercise(A_WIS, TRUE); 352. 	ep->engr_time = e_time; 353. 	ep->engr_type = e_type > 0 ? e_type : rnd(N_ENGRAVE); 354. 	ep->engr_lth = strlen(s) + 1; 355. }  356.   357.  /* delete any engraving at location  */ 358. void 359. del_engr_at(x, y)  360. int x, y; 361. { 362.  	register struct engr *ep = engr_at(x, y); 363.  364.  	if (ep) del_engr(ep); 365. }  366.   367.  /*  368.   *	freehand - returns true if player has a free hand 369.  */  370.  int 371. freehand 372. {  373.  	return(!uwep || !welded(uwep) ||  374.  	   (!bimanual(uwep) && (!uarms || !uarms->cursed))); 375. /*	if ((uwep && bimanual(uwep)) ||  376.  	    (uwep && uarms)) 377. 		return(0); 378. 	else 379. 		return(1);*/ 380. }  381.   382.  static NEARDATA const char styluses[] = 383. 	{ ALL_CLASSES, ALLOW_NONE, TOOL_CLASS, WEAPON_CLASS, WAND_CLASS, 384. 	  GEM_CLASS, RING_CLASS, 0 }; 385.  386.  /* Mohs' Hardness Scale: 387.  *  1 - Talc		 6 - Orthoclase 388.  *  2 - Gypsum		 7 - Quartz 389.  *  3 - Calcite		 8 - Topaz 390.  *  4 - Fluorite	 9 - Corundum 391.  *  5 - Apatite		10 - Diamond 392.  *  393.   * Since granite is a igneous rock hardness ~ 7, anything >= 8 should 394.  * probably be able to scratch the rock. 395.  * Devaluation of less hard gems is not easily possible because obj struct 396.  * does not contain individual oc_cost currently. 7/91 397.   *  398.   * steel     -	5-8.5	(usu. weapon) 399.  * diamond    - 10			* jade	     -	5-6	 (nephrite) 400.  * ruby       -  9	(corundum)	* turquoise  -	5-6 401.  * sapphire   -  9	(corundum)	* opal	     -	5-6 402.  * topaz      -  8			* glass      - ~5.5 403.  * emerald    -  7.5-8	(beryl)		* dilithium  -	4-5?? 404.  * aquamarine -  7.5-8	(beryl)		* iron	     -	4-5 405.  * garnet     -  7.25	(var. 6.5-8)	* fluorite   -	4 406.  * agate      -  7	(quartz)	* brass      -	3-4 407.  * amethyst   -  7	(quartz)	* gold	     -	2.5-3 408.  * jasper     -  7	(quartz)	* silver     -	2.5-3 409.  * onyx       -  7	(quartz)	* copper     -	2.5-3 410.  * moonstone  -  6	(orthoclase)	* amber      -	2-2.5 411.  */  412.   413.  /* return 1 if action took 1 (or more) moves, 0 if error or aborted */ 414. int 415. doengrave 416. {  417.  	boolean dengr = FALSE;	/* TRUE if we wipe out the current engraving */ 418. 	boolean doblind = FALSE;/* TRUE if engraving blinds the player */ 419. 	boolean doknown = FALSE;/* TRUE if we identify the stylus */ 420. 	boolean eow = FALSE;	/* TRUE if we are overwriting oep */ 421. 	boolean jello = FALSE;	/* TRUE if we are engraving in slime */ 422. 	boolean ptext = TRUE;	/* TRUE if we must prompt for engrave text */ 423. 	boolean teleengr =FALSE;/* TRUE if we move the old engraving */ 424. 	boolean zapwand = FALSE;/* TRUE if we remove a wand charge */ 425. 	xchar type = DUST;	/* Type of engraving made */ 426. 	char buf[BUFSZ];	/* Buffer for final/poly engraving text */ 427. 	char ebuf[BUFSZ];	/* Buffer for initial engraving text */ 428. 	char qbuf[QBUFSZ];	/* Buffer for query text */ 429. 	char post_engr_text[BUFSZ]; /* Text displayed after engraving prompt */ 430. 	const char *everb;	/* Present tense of engraving type */ 431. 	const char *eloc;	/* Where the engraving is (ie dust/floor/...) */ 432. 	register char *sp;	/* Place holder for space count of engr text */ 433. 	register int len;	/* # of nonspace chars of new engraving text */ 434. 	register int maxelen;	/* Max allowable length of new engraving text */ 435. 	register int spct;	/* # of spaces in new engraving text */ 436. 	register struct engr *oep = engr_at(u.ux,u.uy); 437. 				/* The current engraving */ 438. 	register struct obj *otmp; /* Object selected with which to engrave */ 439. 	char *writer; 440.  441.   442.  	multi = 0;		/* moves consumed */ 443. 	nomovemsg = (char *)0;	/* occupation end message */ 444.  445.  	buf[0] = (char)0; 446. 	ebuf[0] = (char)0; 447. 	post_engr_text[0] = (char)0; 448. 	maxelen = BUFSZ - 1; 449.  450.  	/* Can the adventurer engrave at all? */ 451.   452.  	if(u.uswallow) { 453. 		if (is_animal(u.ustuck->data)) { 454. 			pline("What would you write?  \"Jonah was here\"?"); 455. 			return(0); 456. 		} else if (is_whirly(u.ustuck->data)) { 457. 			You_cant("reach the %s.", surface(u.ux,u.uy)); 458. 			return(0); 459. 		} else 460. 			jello = TRUE; 461. 	} else if (is_lava(u.ux, u.uy)) { 462. 		You_cant("write on the lava!"); 463. 		return(0); 464. 	} else if (is_pool(u.ux,u.uy) || IS_FOUNTAIN(levl[u.ux][u.uy].typ)) { 465. 		You_cant("write on the water!"); 466. 		return(0); 467. 	}  468.  	if(Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)/* in bubble */) { 469. 		You_cant("write in thin air!"); 470. 		return(0); 471. 	}  472.  	if (cantwield(youmonst.data)) { 473. 		You_cant("even hold anything!"); 474. 		return(0); 475. 	}  476.  	if (check_capacity((char *)0)) return (0); 477.  478.  	/* One may write with finger, or weapon, or wand, or..., or...  479. * Edited by GAN 10/20/86 so as not to change weapon wielded. 480. 	 */  481.   482.  	otmp = getobj(styluses, "write with"); 483. 	if(!otmp) return(0);		/* otmp == zeroobj if fingers */ 484.  485.  	if (otmp == &zeroobj) writer = makeplural(body_part(FINGER)); 486. 	else writer = xname(otmp); 487.  488.  	/* There's no reason you should be able to write with a wand 489. 	 * while both your hands are tied up. 490. 	 */  491.  	if (!freehand && otmp != uwep && !otmp->owornmask) { 492. 		You("have no free %s to write with!", body_part(HAND)); 493. 		return(0); 494. 	}  495.   496.  	if (jello) { 497. 		You("tickle %s with your %s.", mon_nam(u.ustuck), writer); 498. 		Your("message dissolves..."); 499. 		return(0); 500. 	}  501.  	if (otmp->oclass != WAND_CLASS && !can_reach_floor) { 502. 		You_cant("reach the %s!", surface(u.ux,u.uy)); 503. 		return(0); 504. 	}  505.  	if (IS_ALTAR(levl[u.ux][u.uy].typ)) { 506. 		You("make a motion towards the altar with your %s.", writer); 507. 		altar_wrath(u.ux, u.uy); 508. 		return(0); 509. 	}  510.   511.  	/* SPFX for items */ 512.  513.  	switch (otmp->oclass) { 514. 	    default: 515. 	    case AMULET_CLASS: 516. 	    case CHAIN_CLASS: 517. 	    case POTION_CLASS: 518. 	    case GOLD_CLASS: 519. 		break; 520.  521.  	    case RING_CLASS: 522. 		/* "diamond" rings and others should work */ 523. 	    case GEM_CLASS: 524. 		/* diamonds & other hard gems should work */ 525. 		if (objects[otmp->otyp].oc_tough) { 526. 			type = ENGRAVE; 527. 			break; 528. 		}  529.  		break; 530.  531.  	    case ARMOR_CLASS: 532. 		if (is_boots(otmp)) { 533. 			type = DUST; 534. 			break; 535. 		}  536.  		/* fall through */ 537. 	    /* Objects too large to engrave with */ 538. 	    case BALL_CLASS: 539. 	    case ROCK_CLASS: 540. 		You_cant("engrave with such a large object!"); 541. 		ptext = FALSE; 542. 		break; 543.  544.  	    /* Objects too silly to engrave with */ 545. 	    case FOOD_CLASS: 546. 	    case SCROLL_CLASS: 547. 	    case SPBOOK_CLASS: 548. 		Your("%s would get %s.", xname(otmp),  549.  			is_ice(u.ux,u.uy) ? "all frosty" : "too dirty"); 550. 		ptext = FALSE; 551. 		break; 552.  553.  	    case RANDOM_CLASS:	/* This should mean fingers */ 554. 		break; 555.  556.  	    /* The charge is removed from the wand before prompting for 557. 	     * the engraving text, because all kinds of setup decisions 558. 	     * and pre-engraving messages are based upon knowing what type 559. 	     * of engraving the wand is going to do. Also, the player 560. 	     * will have potentially seen "You wrest .." message, and 561. 	     * therefore will know they are using a charge. 562. 	     */  563.  	    case WAND_CLASS: 564. 		if (zappable(otmp)) { 565. 		    check_unpaid(otmp); 566. 		    zapwand = TRUE; 567. 		    if (Levitation) ptext = FALSE; 568.  569.  		    switch (otmp->otyp) { 570. 		    /* DUST wands */ 571. 		    default: 572. 			break; 573.  574.  			/* NODIR wands */ 575. 		    case WAN_LIGHT: 576. 		    case WAN_SECRET_DOOR_DETECTION: 577. 		    case WAN_CREATE_MONSTER: 578. 		    case WAN_WISHING: 579. 		    case WAN_ENLIGHTENMENT: 580. 			zapnodir(otmp); 581. 			break; 582.  583.  			/* IMMEDIATE wands */ 584. 			/* If wand is "IMMEDIATE", remember to affect the 585. 			 * previous engraving even if turning to dust. 586. 			 */  587.  		    case WAN_STRIKING: 588. 			Strcpy(post_engr_text,  589.  			"The wand unsuccessfully fights your attempt to write!"  590.  			); 591. 			break; 592. 		    case WAN_SLOW_MONSTER: 593. 			if (!Blind) { 594. 			   Sprintf(post_engr_text,  595.  				   "The bugs on the %s slow down!",  596.  				   surface(u.ux, u.uy)); 597. 			}  598.  			break; 599. 		    case WAN_SPEED_MONSTER: 600. 			if (!Blind) { 601. 			   Sprintf(post_engr_text,  602.  				   "The bugs on the %s speed up!",  603.  				   surface(u.ux, u.uy)); 604. 			}  605.  			break; 606. 		    case WAN_POLYMORPH: 607. 			if(oep)  { 608. 			    if (!Blind) { 609. 				type = (xchar)0;	/* random */ 610. 				(void) random_engraving(buf); 611. 			    }  612.  			    dengr = TRUE; 613. 			}  614.  			break; 615. 		    case WAN_NOTHING: 616. 		    case WAN_UNDEAD_TURNING: 617. 		    case WAN_OPENING: 618. 		    case WAN_LOCKING: 619. 		    case WAN_PROBING: 620. 			break; 621.  622.  			/* RAY wands */ 623. 		    case WAN_MAGIC_MISSILE: 624. 			ptext = TRUE; 625. 			if (!Blind) { 626. 			   Sprintf(post_engr_text,  627.  				   "The %s is riddled by bullet holes!",  628.  				   surface(u.ux, u.uy)); 629. 			}  630.  			break; 631.  632.  		    /* can't tell sleep from death - Eric Backus */ 633. 		    case WAN_SLEEP: 634. 		    case WAN_DEATH: 635. 			if (!Blind) { 636. 			   Sprintf(post_engr_text,  637.  				   "The bugs on the %s stop moving!",  638.  				   surface(u.ux, u.uy)); 639. 			}  640.  			break; 641.  642.  		    case WAN_COLD: 643. 			if (!Blind) 644. 			    Strcpy(post_engr_text,  645.  				"A few ice cubes drop from the wand."); 646. 			if(!oep || (oep->engr_type != BURN)) 647. 			    break; 648. 		    case WAN_CANCELLATION: 649. 		    case WAN_MAKE_INVISIBLE: 650. 			if(oep) { 651. 			    if (!Blind) 652. 				pline_The("engraving on the %s vanishes!",  653.  					surface(u.ux,u.uy)); 654. 			    dengr = TRUE; 655. 			}  656.  			break; 657. 		    case WAN_TELEPORTATION: 658. 			if (oep) { 659. 			    if (!Blind) 660. 				pline_The("engraving on the %s vanishes!",  661.  					surface(u.ux,u.uy)); 662. 			    teleengr = TRUE; 663. 			}  664.  			break; 665.  666.  		    /* type = ENGRAVE wands */ 667. 		    case WAN_DIGGING: 668. 			ptext = TRUE; 669. 			type  = ENGRAVE; 670. 			if(!objects[otmp->otyp].oc_name_known) { 671. 			    if (flags.verbose) 672. 				pline("This %s is a wand of digging!",  673.  				xname(otmp)); 674. 			    doknown = TRUE; 675. 			}  676.  			if (!Blind) 677. 			    Strcpy(post_engr_text,  678.  				is_ice(u.ux,u.uy) ?  679.  				"Ice chips fly up from the ice surface!" :  680.  				"Gravel flies up from the floor."); 681. 			else 682. 			    Strcpy(post_engr_text, "You hear drilling!"); 683. 			break; 684.  685.  		    /* type = BURN wands */ 686. 		    case WAN_FIRE: 687. 			ptext = TRUE; 688. 			type  = BURN; 689. 			if(!objects[otmp->otyp].oc_name_known) { 690. 			if (flags.verbose) 691. 			    pline("This %s is a wand of fire!", xname(otmp)); 692. 			    doknown = TRUE; 693. 			}  694.  			Strcpy(post_engr_text,  695.  				Blind ? "You feel the wand heat up." :  696.  					"Flames fly from the wand."); 697. 			break; 698. 		    case WAN_LIGHTNING: 699. 			ptext = TRUE; 700. 			type  = BURN; 701. 			if(!objects[otmp->otyp].oc_name_known) { 702. 			    if (flags.verbose) 703. 				pline("This %s is a wand of lightning!",  704.  					xname(otmp)); 705. 			    doknown = TRUE; 706. 			}  707.  			if (!Blind) { 708. 			    Strcpy(post_engr_text,  709.  				    "Lightning arcs from the wand."); 710. 			    doblind = TRUE; 711. 			} else 712. 			    Strcpy(post_engr_text, "You hear crackling!"); 713. 			break; 714.  715.  		    /* type = MARK wands */ 716. 		    /* type = BLOOD wands */ 717. 		    }  718.  		} else /* end if zappable */ 719. 		    if (!can_reach_floor) { 720. 			You_cant("reach the %s!", surface(u.ux,u.uy)); 721. 			return(0); 722. 		    }  723.  		break; 724.  725.  	    case WEAPON_CLASS: 726. 		if(is_blade(otmp)) 727. 		    if ((int)otmp->spe > -3) 728. 			type = ENGRAVE; 729. 		    else 730. 			Your("%s too dull for engraving.", aobjnam(otmp,"are")); 731. 		break; 732.  733.  	    case TOOL_CLASS: 734. 		if(otmp == ublindf) { 735. 		    pline(  736.  		"That is a bit difficult to engrave with, don't you think?"); 737. 		    return(0); 738. 		}  739.  		switch (otmp->otyp)  { 740. 		    case MAGIC_MARKER: 741. 			if (otmp->spe <= 0) 742. 			    Your("marker has dried out."); 743. 			else 744. 			    type = MARK; 745. 			break; 746. 		    case TOWEL: 747. 			/* Can't really engrave with a towel */ 748. 			ptext = FALSE; 749. 			if (oep) 750. 			    if ((oep->engr_type == DUST ) ||  751.  				(oep->engr_type == BLOOD) ||  752.  				(oep->engr_type == MARK )) { 753. 				if (!Blind) 754. 				    You("wipe out the message here."); 755. 				else 756. 				    Your("%s gets %s.", xname(otmp),  757.  					  is_ice(u.ux,u.uy) ?  758.  					  "frosty" : "dusty"); 759. 				dengr = TRUE; 760. 			    } else 761. 				Your("%s can't wipe out this engraving.",  762.  				     xname(otmp)); 763. 			else 764. 			    Your("%s gets %s.", xname(otmp),  765.  				  is_ice(u.ux,u.uy) ? "frosty" : "dusty"); 766. 			break; 767. 		    default: 768. 			break; 769. 		}  770.  		break; 771.  772.  	    case VENOM_CLASS: 773. #ifdef WIZARD 774. 		if (wizard) { 775. 		    pline("Writing a poison pen letter??"); 776. 		    break; 777. 		}  778.  #endif 779. 	    case ILLOBJ_CLASS: 780. 		impossible("You're engraving with an illegal object!"); 781. 		break; 782. 	}  783.   784.  	/* End of implement setup */ 785.  786.  	/* Identify stylus */ 787. 	if (doknown) { 788. 	    makeknown(otmp->otyp); 789. 	    more_experienced(0,10); 790. 	}  791.   792.  	if (teleengr) { 793. 	    rloc_engr(oep); 794. 	    oep = (struct engr *)0; 795. 	}  796.   797.  	if (dengr) { 798. 	    del_engr(oep); 799. 	    oep = (struct engr *)0; 800. 	}  801.   802.  	/* Something has changed the engraving here */ 803. 	if (*buf) { 804. 	    make_engr_at(u.ux, u.uy, buf, moves, type); 805. 	    pline_The("engraving now reads: \"%s\".", buf); 806. 	    ptext = FALSE; 807. 	}  808.   809.  	if (zapwand && (otmp->spe < 0)) { 810. 	    pline("%s %sturns to dust.",  811.  		  The(xname(otmp)), Blind ? "" : "glows violently, then "); 812.  You("are not going to get anywhere trying to write in the %s with your dust.",  813.  		is_ice(u.ux,u.uy) ? "frost" : "dust"); 814. 	    useup(otmp); 815. 	    ptext = FALSE; 816. 	}  817.   818.  	if (!ptext) {		/* Early exit for some implements. */ 819.  	    if (otmp->oclass == WAND_CLASS && !can_reach_floor) 820. 		You_cant("reach the %s!", surface(u.ux,u.uy)); 821. 	    return(1); 822. 	}  823.   824.  	/* Special effects should have deleted the current engraving (if  825.  	 * possible) by now. 826. 	 */  827.   828.  	if (oep) { 829. 	    register char c = 'n'; 830.  831.  	    /* Give player the choice to add to engraving. */ 832.   833.  	    if ( (type == oep->engr_type) && (!Blind || 834. 		 (oep->engr_type == BURN) || (oep->engr_type == ENGRAVE)) ) { 835. 		c = yn_function("Do you want to add to the current engraving?",  836.  				ynqchars, 'y'); 837. 		if (c == 'q') { 838. 		    pline("Never mind."); 839. 		    return(0); 840. 		}  841.  	    }  842.   843.  	    if (c == 'n' || Blind) { 844.  845.  		if( (oep->engr_type == DUST) || (oep->engr_type == BLOOD) ||  846.  		    (oep->engr_type == MARK) ) { 847. 		    if (!Blind) { 848. 			You("wipe out the message that was %s here.",  849.  			    ((oep->engr_type == DUST)  ? "written in the dust" : 850. 			    ((oep->engr_type == BLOOD) ? "scrawled in blood"   :  851.  							 "written"))); 852. 			del_engr(oep); 853. 			oep = (struct engr *)0; 854. 		    } else 855. 		   /* Don't delete engr until after we *know* we're engraving */ 856. 			eow = TRUE; 857. 		} else 858. 		    if ( (type == DUST) || (type == MARK) || (type == BLOOD) ) { 859. 			You(  860.  			 "cannot wipe out the message that is %s the %s here.",  861.  			 oep->engr_type == BURN ?  862.  			   (is_ice(u.ux,u.uy) ? "melted into" : "burned into") : 863.  			   "engraved in", surface(u.ux,u.uy)); 864. 			return(1); 865. 		    } else 866. 			if ( (type != oep->engr_type) || (c == 'n') ) { 867. 			    if (!Blind || can_reach_floor) 868. 				You("will overwrite the current message."); 869. 			    eow = TRUE; 870. 			}  871.  	}  872.  	}  873.   874.  	eloc = surface(u.ux,u.uy); 875. 	switch(type){ 876. 	    default: 877. 		everb = (oep && !eow ? "add to the weird writing on" :  878.  				       "write strangely on"); 879. 		break; 880. 	    case DUST: 881. 		everb = (oep && !eow ? "add to the writing in" :  882.  				       "write in"); 883. 		eloc = is_ice(u.ux,u.uy) ? "frost" : "dust"; 884. 		break; 885. 	    case ENGRAVE: 886. 		everb = (oep && !eow ? "add to the engraving in" :  887.  				       "engrave in"); 888. 		break; 889. 	    case BURN: 890. 		everb = (oep && !eow ?  891.  			( is_ice(u.ux,u.uy) ? "add to the text melted into" : 892. 					      "add to the text burned into") :  893.  			( is_ice(u.ux,u.uy) ? "melt into" : "burn into")); 894. 		break; 895. 	    case MARK: 896. 		everb = (oep && !eow ? "add to the graffiti on" :  897.  				       "scribble on"); 898. 		break; 899. 	    case BLOOD: 900. 		everb = (oep && !eow ? "add to the scrawl on" :  901.  				       "scrawl on"); 902. 		break; 903. 	}  904.   905.  	/* Tell adventurer what is going on */ 906. 	if (otmp != &zeroobj) 907. 	    You("%s the %s with %s.", everb, eloc, doname(otmp)); 908. 	else 909. 	    You("%s the %s with your %s.", everb, eloc,  910.  		makeplural(body_part(FINGER))); 911.  912.  	/* Prompt for engraving! */ 913.  	Sprintf(qbuf,"What do you want to %s the %s here?", everb, eloc); 914. 	getlin(qbuf, ebuf); 915.  916.  	/* Mix up engraving if surface or state of mind is unsound. */ 917.  	/* Original kludge by stewr 870708. modified by njm 910722. */ 918.  	for (sp = ebuf; *sp; sp++) 919. 	    if ( ((type == DUST || type == BLOOD) && !rn2(25)) ||  920.  		 (Blind   && !rn2(9)) || (Confusion     && !rn2(12)) ||  921.  		 (Stunned && !rn2(4)) || (Hallucination && !rn2(1)) ) 922. 		 *sp = '!' + rn2(93); /* ASCII-code only */ 923.  924.  	/* Count the actual # of chars engraved not including spaces */ 925. 	len = strlen(ebuf); 926.  927.  	for (sp = ebuf, spct = 0; *sp; sp++) if (isspace(*sp)) spct++; 928.  929.  	if ( (len == spct) || index(ebuf, '\033') ) { 930. 	    if (zapwand) { 931. 		if (!Blind) 932. 		    pline("%s glows, then fades.", The(xname(otmp))); 933. 		return(1); 934. 	    } else { 935. 		pline("Never mind."); 936. 		return(0); 937. 	    }  938.  	}  939.   940.  	len -= spct; 941.  942.  	/* Previous engraving is overwritten */ 943. 	if (eow) { 944. 	    del_engr(oep); 945. 	    oep = (struct engr *)0; 946. 	}  947.   948.  	/* Figure out how long it took to engrave, and if player has 949. 	 * engraved too much. 950. 	 */  951.  	switch(type){ 952. 	    default: 953. 		multi = -(len/10); 954. 		if (multi) nomovemsg = "You finish your weird engraving."; 955. 		break; 956. 	    case DUST: 957. 		multi = -(len/10); 958. 		if (multi) nomovemsg = "You finish writing in the dust."; 959. 		break; 960. 	    case ENGRAVE: 961. 		multi = -(len/10); 962. 		if ((otmp->oclass == WEAPON_CLASS) &&  963.  		    ((otmp->otyp != ATHAME) || otmp->cursed)) { 964. 		    multi = -len; 965. 		    maxelen = ((otmp->spe + 3) * 2) + 1; 966. 			/* -2 = 3, -1 = 5, 0 = 7, +1 = 9, +2 = 11  967.  			 * Note: this does not allow a +0 anything (except  968.  			 *	 an athame) to engrave "Elbereth" all at once. 969. 			 *	 However, you could now engrave "Elb", then 970. 			 *	 "ere", then "th". 971. 			 */  972.  		    Your("%s dull.", aobjnam(otmp, "get")); 973. 		    if (len > maxelen) { 974. 			multi = -maxelen; 975. 			otmp->spe = -3; 976. 		    } else 977. 			if (len > 1) otmp->spe -= len >> 1; 978. 			else otmp->spe -= 1; /* Prevent infinite engraving */ 979. 		} else 980. 		    if ( (otmp->oclass == RING_CLASS) ||  981.  			 (otmp->oclass == GEM_CLASS) ) 982. 			multi = -len; 983. 		if (multi) nomovemsg = "You finish engraving."; 984. 		break; 985. 	    case BURN: 986. 		multi = -(len/10); 987. 		if (multi) 988. 		    nomovemsg = is_ice(u.ux,u.uy) ? 989. 			"You finish melting your message into the ice.": 990. 			"You finish burning your message into the floor."; 991. 		break; 992. 	    case MARK: 993. 		multi = -(len/10); 994. 		if ((otmp->oclass == TOOL_CLASS) &&  995.  		    (otmp->otyp == MAGIC_MARKER)) { 996. 		    maxelen = (otmp->spe) * 2; /* one charge / 2 letters */ 997. 		    if (len > maxelen) { 998. 			Your("marker dries out."); 999. 			otmp->spe = 0; 1000. 			multi = -(maxelen/10); 1001. 		   } else 1002. 			if (len > 1) otmp->spe -= len >> 1; 1003. 			else otmp->spe -= 1; /* Prevent infinite grafitti */ 1004. 		} 1005. 		if (multi) nomovemsg = "You finish defacing the dungeon."; 1006. 		break; 1007. 	   case BLOOD: 1008. 		multi = -(len/10); 1009. 		if (multi) nomovemsg = "You finish scrawling."; 1010. 		break; 1011. 	} 1012.  1013. 	/* Chop engraving down to size if necessary */ 1014. 	if (len > maxelen) { 1015. 	   for (sp = ebuf; (maxelen && *sp); sp++) 1016. 		if (!isspace(*sp)) maxelen--; 1017. 	   if (!maxelen && *sp) { 1018. 		*sp = (char)0; 1019. 		if (multi) nomovemsg = "You cannot write any more."; 1020. 		You("only are able to write \"%s\"", ebuf); 1021. 	   }  1022. 	}  1023.  1024. 	/* Add to existing engraving */ 1025. 	if (oep) Strcpy(buf, oep->engr_txt); 1026. 1027. 	(void) strncat(buf, ebuf, (BUFSZ - (int)strlen(buf) - 1)); 1028. 1029. 	make_engr_at(u.ux, u.uy, buf, (moves - multi), type); 1030. 1031. 	if (post_engr_text[0]) pline(post_engr_text); 1032. 1033. 	if (doblind && !resists_blnd(&youmonst)) { 1034. 	   You("are blinded by the flash!"); 1035. 	   make_blinded((long)rnd(50),FALSE); 1036. 	} 1037.  1038. 	u.uconduct.literate++; 1039. 1040. 	return(1); 1041. } 1042.  1043. void 1044. save_engravings(fd, mode) 1045. int fd, mode; 1046. { 1047. 	register struct engr *ep = head_engr; 1048. 	register struct engr *ep2; 1049. 	unsigned no_more_engr = 0; 1050. 1051. 	while (ep) { 1052. 	   ep2 = ep->nxt_engr; 1053. 	   if (ep->engr_lth && ep->engr_txt[0] && perform_bwrite(mode)) { 1054. 		bwrite(fd, (genericptr_t)&(ep->engr_lth), sizeof(ep->engr_lth)); 1055. 		bwrite(fd, (genericptr_t)ep, sizeof(struct engr) + ep->engr_lth); 1056. 	   }  1057. 	    if (release_data(mode)) 1058. 		dealloc_engr(ep); 1059. 	   ep = ep2; 1060. 	} 1061. 	if (perform_bwrite(mode)) 1062. 	   bwrite(fd, (genericptr_t)&no_more_engr, sizeof no_more_engr); 1063. 	if (release_data(mode)) 1064. 	   head_engr = 0; 1065. } 1066.  1067. void 1068. rest_engravings(fd) 1069. int fd; 1070. { 1071. 	register struct engr *ep; 1072. 	unsigned lth; 1073. 1074. 	head_engr = 0; 1075. 	while(1) { 1076. 		mread(fd, (genericptr_t) &lth, sizeof(unsigned)); 1077. 		if(lth == 0) return; 1078. 		ep = newengr(lth); 1079. 		mread(fd, (genericptr_t) ep, sizeof(struct engr) + lth); 1080. 		ep->nxt_engr = head_engr; 1081. 		head_engr = ep; 1082. 		ep->engr_txt = (char *) (ep + 1);	/* Andreas Bormann */ 1083. 		/* mark as finished for bones levels -- no problem for 1084. 		 * normal levels as the player must have finished engraving 1085. 		 * to be able to move again */ 1086. 		ep->engr_time = moves; 1087. 	} 1088. }  1089.  1090. void 1091. del_engr(ep) 1092. register struct engr *ep; 1093. { 1094. 	if (ep == head_engr) { 1095. 		head_engr = ep->nxt_engr; 1096. 	} else { 1097. 		register struct engr *ept; 1098. 1099. 		for (ept = head_engr; ept; ept = ept->nxt_engr) 1100. 		   if (ept->nxt_engr == ep) { 1101. 			ept->nxt_engr = ep->nxt_engr; 1102. 			break; 1103. 		   }  1104. 		if (!ept) { 1105. 		   impossible("Error in del_engr?"); 1106. 		   return; 1107. 		} 1108. 	}  1109. 	dealloc_engr(ep); 1110. } 1111.  1112. /* randomly relocate an engraving */ 1113. void 1114. rloc_engr(ep) 1115. struct engr *ep; 1116. { 1117. 	int tx, ty, tryct = 200; 1118. 1119. 	do  { 1120. 	   if (--tryct < 0) return; 1121. 	   tx = rn1(COLNO-3,2); 1122. 	   ty = rn2(ROWNO); 1123. 	} while (engr_at(tx, ty) || 1124. 		!goodpos(tx, ty, (struct monst *)0)); 1125. 1126. 	ep->engr_x = tx; 1127. 	ep->engr_y = ty; 1128. } 1129.  1130. #endif /* OVLB */ 1131. 1132. /*engrave.c*/