Source:NetHack 3.1.0/engrave.c

Below is the full text to engrave.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.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.1	92/02/25	*/ 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 struct engr NEARDATA *head_engr; 10.   11.   STATIC_DCL void FDECL(del_engr, (struct engr *)); 12.   13.   #ifdef OVLB 14.  /* random engravings */ 15.  const char *random_mesg[] = { 16.  	"Elbereth", "ad ae?ar um", 17.  	"?la? ?as he??", 18.  	/* take-offs and other famous engravings */ 19.  	"Owlbreath", "?ala??iel", 20.  	"?ilroy wa? h?re", 21.  	"A.S. ->", "<- A.S.", /* Journey to the Center of the Earth */ 22.  	"Y?u won t get i? up ?he ste?s", /* Adventure */ 23.  	"Lasc?ate o?ni sp?ranz? o vo? c?'en?rate", /* Inferno */ 24.  	"Well Come", /* Prisoner */ 25.  	"W? ap?l???ze for t?e inc?nve??e?ce", /* So Long... */ 26.   	"S?e you n?xt Wed?esd?y", /* Thriller */ 27.  	"Fo? a ?ood time c?ll 8?7-53?9", 28.  };  29.    30.   const char * 31.  random_engraving 32.  {  33.   	char *rumor, *s; 34.   35.   /* a random engraving may come from the "rumors" file, or from the 36.     list above */ 37.  	rumor = getrumor(0); 38.  	if (rn2(4) && *rumor) { 39.  		for (s = rumor; *s; s++) 40.  			if (!rn2(7) && *s != ' ') *s = '?'; 41.  		if (s[-1] == '.') s[-1] = 0; 42.  		return (const char *)rumor; 43.  	}  44.   	else 45.  		return random_mesg[rn2(SIZE(random_mesg))]; 46.  }  47.   #endif /* OVLB */ 48.  #ifdef OVL0 49.   50.   struct engr * 51.  engr_at(x,y) register xchar x,y; { 52.  register struct engr *ep = head_engr; 53.  	while(ep) { 54.  		if(x == ep->engr_x && y == ep->engr_y) 55.  			return(ep); 56.  		ep = ep->nxt_engr; 57.  	}  58.   	return((struct engr *) 0); 59.  }  60.    61.   #ifdef ELBERETH 62.  int 63.  sengr_at(s,x,y) 64.  	register const char *s; 65.  	register xchar x,y; 66.  {  67.   	register struct engr *ep = engr_at(x,y); 68.  	register char *t; 69.  	register int n;  70. 71.  	if(ep && ep->engr_time <= moves) { 72.  		t = ep->engr_txt; 73.  /*  74.   		if(!strcmp(s,t)) return(1); 75.  */  76.   		n = strlen(s); 77.  		while(*t) { 78.  			if(!strncmp(s,t,n)) return(1); 79.  			t++; 80.  		}  81.   	}  82.   	return(0); 83.  }  84.   #endif 85.   86.   #endif /* OVL0 */ 87.  #ifdef OVL2 88.   89.   void 90.  u_wipe_engr(cnt) 91.  register int cnt; 92.  {  93.   	if(!u.uswallow && !Levitation) 94.  		wipe_engr_at(u.ux, u.uy, cnt); 95.  }  96.    97.   #endif /* OVL2 */ 98.  #ifdef OVL1 99.   100.  void 101. wipe_engr_at(x,y,cnt) register xchar x,y,cnt; { 102. register struct engr *ep = engr_at(x,y); 103. register int lth,pos; 104. char ch; 105. 	if(ep){ 106. 	    if(ep->engr_type != BURN) { 107. 		if(ep->engr_type != DUST && ep->engr_type != BLOOD) { 108. 			cnt = rn2(1 + 50/(cnt+1)) ? 0 : 1; 109.  		}  110.  		lth = strlen(ep->engr_txt); 111. 		if(lth && cnt > 0 ) { 112. 			while(cnt--) { 113. 				pos = rn2(lth); 114. 				if((ch = ep->engr_txt[pos]) == ' ') 115. 					continue; 116. 				ep->engr_txt[pos] = (ch != '?') ? '?' : ' '; 117.  			}  118.  		}  119.  		while(lth && ep->engr_txt[lth-1] == ' ') 120. 			ep->engr_txt[--lth] = 0; 121. 		while(ep->engr_txt[0] == ' ') 122. 			ep->engr_txt++; 123. 		if(!ep->engr_txt[0]) del_engr(ep); 124. 	    }  125.  	}  126.  }  127.   128.  #endif /* OVL1 */ 129. #ifdef OVL2 130.  131.  void 132. read_engr_at(x,y) 133. register int x,y; 134. {  135.  	register struct engr *ep = engr_at(x,y); 136. 	register int	sensed = 0; 137.  138.  	if(ep && ep->engr_txt[0]) { 139. 	    switch(ep->engr_type) { 140. 	    case DUST: 141. 		if(!Blind) { 142. 			sensed = 1; 143. 			pline("Something is written here in the dust."); 144. 		}  145.  		break; 146. 	    case ENGRAVE: 147. 		if(!Blind || !Levitation) { 148. 			sensed = 1; 149. 			pline("Something is engraved here on the floor."); 150. 		}  151.  		break; 152. 	    case BURN: 153. 		if(!Blind || !Levitation) { 154. 			sensed = 1; 155. 			pline("Some text has been burned into the floor here."); 156. 		}  157.  		break; 158. 	    case MARK: 159. 		if(!Blind) { 160. 			sensed = 1; 161. 			pline("There's some graffiti on the floor here."); 162. 		}  163.  		break; 164. 	    case BLOOD: 165. 		/* "It's a message!  Scrawled in blood!" 166. 		 * "What's it say?" 167. 		 * "It says... `See you next Wednesday.'" -- Thriller 168. 		 */  169.  		if(!Blind) { 170. 			sensed = 1; 171. 			You("see a message scrawled in blood here."); 172. 		}  173.  		break; 174. 	    default: 175. 		impossible("Something is written in a very strange way."); 176. 		sensed = 1; 177. 	    }  178.  	    if (sensed) { 179. 		You("%s: \"%s\".",  180.  		      (Blind) ? "feel the words" : "read",  ep->engr_txt); 181. 		if(flags.run > 1) nomul(0); 182. 	    }  183.  	}  184.  }  185.   186.  #endif /* OVL2 */ 187. #ifdef OVLB 188.  189.  void 190. make_engr_at(x,y,s,e_time,e_type) 191. register int x,y; 192. register const char *s; 193. register long e_time; 194. register xchar e_type; 195. {  196.  	register struct engr *ep; 197.  198.  	if(ep = engr_at(x,y)) 199. 	    del_engr(ep); 200. 	ep = newengr(strlen(s) + 1); 201. 	ep->nxt_engr = head_engr; 202. 	head_engr = ep; 203. 	ep->engr_x = x;  204. ep->engr_y = y; 205. ep->engr_txt = (char *)(ep + 1); 206. 	Strcpy(ep->engr_txt, s); 207. 	if(strcmp(s, "Elbereth")) exercise(A_WIS, TRUE); 208. 	ep->engr_time = e_time; 209. 	ep->engr_type = e_type > 0 ? e_type : rnd(N_ENGRAVE); 210. 	ep->engr_lth = strlen(s) + 1; 211. }  212.   213.  /*  214.   *	freehand - returns true if player has a free hand 215.  */  216.  int 217. freehand 218. {  219.  	return(!uwep || !welded(uwep) ||  220.  	   (!bimanual(uwep) && (!uarms || !uarms->cursed))); 221. /*	if ((uwep && bimanual(uwep)) ||  222.  	    (uwep && uarms)) 223. 		return(0); 224. 	else 225. 		return(1);*/ 226. }  227.   228.  static const char NEARDATA styluses[] = 229. 	{ ALL_CLASSES, ALLOW_NONE, TOOL_CLASS, WEAPON_CLASS, WAND_CLASS, 230. 	  GEM_CLASS, RING_CLASS, 0 }; 231.  232.  /* Mohs' Hardness Scale: 233.  *  1 - Talc		 6 - Orthoclase 234.  *  2 - Gypsum		 7 - Quartz 235.  *  3 - Calcite		 8 - Topaz 236.  *  4 - Fluorite	 9 - Corundum 237.  *  5 - Apatite		10 - Diamond 238.  *  239.   * Since granite is a igneous rock hardness ~ 7, anything >= 8 should 240.  * probably be able to scratch the rock. 241.  * Devaluation of less hard gems is not easily possible because obj struct 242.  * does not contain individual oc_cost currently. 7/91 243.   *  244.   * dilithium  - ?? * jade	   -  5-6	(nephrite) 245.  * diamond    - 10			* turquoise -  5-6 246.  * ruby	      -  9	(corundum)	* opal	    -  5-6 247.  * sapphire   -  9	(corundum)	* iron	    -  4-5 248.  * topaz      -  8			* fluorite  -  4 249.  * emerald    -  7.5-8	(beryl)		* brass     -  3-4 250.  * aquamarine -  7.5-8	(beryl)		* gold	    -  2.5-3 251.  * garnet     -  7.25	(var. 6.5-8)	* silver    -  2.5-3 252.  * agate      -  7	(quartz)	* copper    -  2.5-3 253.  * amethyst   -  7	(quartz)	* amber     -  2-2.5 254.  * jasper     -  7	(quartz)	* 255.  * onyx	      -  7 	(quartz)	* steel     -  5-8.5	(usu. weapon) 256.  * moonstone  -  6	(orthoclase)	* 257.  */  258.   259.  static const short NEARDATA hard_gems[] = 260. 	{ DIAMOND, RUBY, SAPPHIRE, TOPAZ, EMERALD, AQUAMARINE, GARNET, 0 }; 261.  262.  static const char NEARDATA *hard_ring_names[] = 263. 	{"diamond", "ruby", "sapphire", "emerald", "topaz", ""}; 264.  265.  /* return 1 if action took 1 (or more) moves, 0 if error or aborted */ 266. int 267. doengrave 268. {  269.  	boolean dengr = FALSE;	/* TRUE if we wipe out the current engraving */ 270. 	boolean doblind = FALSE;/* TRUE if engraving blinds the player */ 271. 	boolean doknown = FALSE;/* TRUE if we identify the stylus */ 272. 	boolean eow = FALSE;	/* TRUE if we are overwriting oep */ 273. 	boolean jello = FALSE;	/* TRUE if we are engraving in slime */ 274. 	boolean ptext = TRUE;	/* TRUE if we must prompt for engrave text */ 275. 	boolean teleengr =FALSE;/* TRUE if we move the old engraving */ 276. 	boolean zapwand = FALSE;/* TRUE if we remove a wand charge */ 277. 	xchar type = DUST;	/* Type of engraving made */ 278. 	char buf[BUFSZ];	/* Buffer for final/poly engraving text */ 279. 	char ebuf[BUFSZ];	/* Buffer for initial engraving text */ 280. 	char qbuf[QBUFSZ];	/* Buffer for query text */ 281. 	const char *everb;	/* Present tense of engraving type */ 282. 	const char *eloc;	/* Where the engraving is (ie dust/floor/...) */ 283. 	const char *post_engr_text; /* Text displayed after engraving prompt */ 284. 	register char *sp;	/* Place holder for space count of engr text */ 285. 	register int len;	/* # of nonspace chars of new engraving text */ 286. 	register int maxelen;	/* Max allowable length of new engraving text */ 287. 	register int spct;	/* # of spaces in new engraving text */ 288. 	register struct engr *oep = engr_at(u.ux,u.uy); 289. 				/* The current engraving */ 290. 	register struct obj *otmp; /* Object selected with which to engrave */ 291.  292.   293.  	multi = 0;		/* moves consumed */ 294. 	nomovemsg = (char *)0;	/* occupation end message */ 295.  296.  	buf[0] = (char)0; 297. 	ebuf[0] = (char)0; 298. 	post_engr_text = (char *)0; 299. 	maxelen = BUFSZ - 1; 300.  301.  	/* Can the adventurer engrave at all? */ 302.   303.  	if(u.uswallow) { 304. 		if (is_animal(u.ustuck->data)) { 305. 			pline("What would you write?  \"Jonah was here\"?"); 306. 			return(0); 307. 		} else if (is_whirly(u.ustuck->data)) { 308. 			You("can't reach the ground."); 309. 			return(0); 310. 		} else 311. 			jello = TRUE; 312.     	} else if (is_lava(u.ux, u.uy)) { 313. 		You("can't write on the lava!"); 314. 		return(0); 315. 	} else if (is_pool(u.ux,u.uy) || IS_FOUNTAIN(levl[u.ux][u.uy].typ)) { 316. 		You("can't write on the water!"); 317. 		return(0); 318. 	}  319.  	if(Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)/* in bubble */) { 320. 		You("can't write in thin air!"); 321. 		return(0); 322. 	}  323.  #ifdef POLYSELF 324. 	if (cantwield(uasmon)) { 325. 		You("can't even hold anything!"); 326. 		return(0); 327. 	}  328.  #endif 329. 	if (check_capacity(NULL)) return (0); 330.  331.  	/* One may write with finger, or weapon, or wand, or..., or...  332. * Edited by GAN 10/20/86 so as not to change weapon wielded. 333. 	 */  334.   335.  	otmp = getobj(styluses, "write with"); 336. 	if(!otmp) return(0);		/* otmp == zeroobj if fingers */ 337.  338.  	/* There's no reason you should be able to write with a wand 339. 	 * while both your hands are tied up. 340. 	 */  341.  	if (!freehand && otmp != uwep && !otmp->owornmask) { 342. 		You("have no free %s to write with!", body_part(HAND)); 343. 		return(0); 344. 	}  345.   346.  	if (jello) { 347. 		You("tickle %s with your %s.", mon_nam(u.ustuck),  348.  		    (otmp == &zeroobj) ? makeplural(body_part(FINGER)) :  349.  			xname(otmp)); 350. 		Your("message dissolves..."); 351. 		return(0); 352. 	}  353.  	if(Levitation && otmp->oclass != WAND_CLASS){		/* riv05!a3 */ 354. 		You("can't reach the floor!"); 355. 		return(0); 356. 	}  357.   358.  	/* SPFX for items */ 359.  360.  	switch (otmp->oclass) { 361. 	    default: 362. 	    case AMULET_CLASS: 363. 	    case CHAIN_CLASS: 364. 	    case POTION_CLASS: 365. 	    case GOLD_CLASS: 366. 		break; 367.  368.  	    case RING_CLASS: 369. 		/* "diamond" rings and others should work */ 370. 		{  371.  		    register int i, j;  372. 373. 		    for (i=0, j=strlen(hard_ring_names[i]); j; i++) 374. 			if ( !strncmp(hard_ring_names[i], 375. 			     OBJ_DESCR(objects[otmp->otyp]), 376. 			     j=strlen(hard_ring_names[i])) ) { 377. 			    type = ENGRAVE; 378. 			    break; 379. 			}  380.  		}  381.  		break; 382.  383.  	    case GEM_CLASS: 384. 		/* diamonds & other gems should work */ 385. 		{  386.  		    register int i;  387. 388. 		    for (i=0; hard_gems[i]; i++) 389. 			if (otmp->otyp == hard_gems[i]) { 390. 			    type = ENGRAVE; 391. 			    break; 392. 			}  393.  		}  394.  		break; 395.  396.  	    /* Objects too large to engrave with */ 397. 	    case BALL_CLASS: 398. 	    case ROCK_CLASS: 399. 	    case ARMOR_CLASS: 400. 		You("can't engrave with such a large object!"); 401. 		ptext = FALSE; 402. 		break; 403.  404.  	    /* Objects too silly to engrave with */ 405. 	    case FOOD_CLASS: 406. 	    case SCROLL_CLASS: 407. 	    case SPBOOK_CLASS: 408. 		Your("%s would get too dirty.", xname(otmp)); 409. 		ptext = FALSE; 410. 		break; 411.  412.  	    case RANDOM_CLASS:	/* This should mean fingers */ 413. 		break; 414.  415.  	    /* The charge is removed from the wand before prompting for 416. 	     * the engraving text, because all kinds of setup decisions 417. 	     * and pre-engraving messages are based upon knowing what type 418. 	     * of engraving the wand is going to do. Also, the player 419. 	     * will have potentially seen "You wrest .." message, and 420. 	     * therefore will know they are using a charge. 421. 	     */  422.  	    case WAND_CLASS: 423. 		if (zappable(otmp)) { 424. 		    zapwand = TRUE; 425. 		    if (Levitation) ptext = FALSE; 426.  427.  		    switch (otmp->otyp) { 428. 		    /* DUST wands */ 429. 		    default: 430. 			break; 431.  432.  			/* NODIR wands */ 433. 		    case WAN_LIGHT: 434. 		    case WAN_SECRET_DOOR_DETECTION: 435. 		    case WAN_CREATE_MONSTER: 436. 		    case WAN_WISHING: 437. 	  		zapnodir(otmp); 438. 			break; 439.  440.  			/* IMMEDIATE wands */ 441. 	    		/* If wand is "IMMEDIATE", remember to effect the 442. 			 * previous engraving even if turning to dust., 443. 			 */  444.  		    case WAN_STRIKING: 445. 			post_engr_text = 446. 			"The wand unsuccessfully fights your attempt to write!"; 447. 			break; 448. 		    case WAN_SLOW_MONSTER: 449. 			if (!Blind) 450. 			   post_engr_text = "The bugs on the ground slow down!"; 451. 			break; 452. 		    case WAN_SPEED_MONSTER: 453. 			if (!Blind) 454. 			   post_engr_text = "The bugs on the ground speed up!"; 455. 			break; 456. 		    case WAN_POLYMORPH: 457. 			if(oep)  { 458. 			    if (!Blind) { 459. 				type = (xchar)0;	/* random */ 460. 				Strcpy(buf,random_engraving); 461. 			    }  462.  			    dengr = TRUE; 463. 			}  464.  			break; 465. 		    case WAN_NOTHING: 466. 		    case WAN_UNDEAD_TURNING: 467. 		    case WAN_OPENING: 468. 		    case WAN_LOCKING: 469. 		    case WAN_PROBING: 470. 			break; 471.  472.  			/* RAY wands */ 473. 		    case WAN_MAGIC_MISSILE: 474. 			ptext = TRUE; 475. 			if (!Blind) 476. 			    post_engr_text = 477. 				"The ground is riddled by bullet holes!"; 478. 			break; 479.  480.  		    /* can't tell sleep from death - Eric Backus */ 481. 		    case WAN_SLEEP: 482. 		    case WAN_DEATH: 483. 			if (!Blind) 484. 			    post_engr_text = 485. 				"The bugs on the ground stop moving!"; 486. 			break; 487.  488.  		    case WAN_COLD: 489. 			if (!Blind) 490. 			    post_engr_text = 491. 				"A few ice cubes drop from the wand."; 492. 			if(!oep || (oep->engr_type != BURN)) 493. 			    break; 494. 		    case WAN_CANCELLATION: 495. 		    case WAN_MAKE_INVISIBLE: 496. 			if(oep) { 497. 			    if (!Blind) 498. 				pline("The engraving on the floor vanishes!"); 499. 			    dengr = TRUE; 500. 			}  501.  			break; 502. 		    case WAN_TELEPORTATION: 503. 			if (oep) { 504. 			    if (!Blind) 505. 				pline("The engraving on the floor vanishes!"); 506. 			    teleengr = TRUE; 507. 			}  508.  			break; 509.  510.  		    /* type = ENGRAVE wands */ 511. 		    case WAN_DIGGING: 512. 			ptext = TRUE; 513. 			type  = ENGRAVE; 514. 			if(!objects[otmp->otyp].oc_name_known) { 515. 	    		    if (flags.verbose) 516. 				pline("This %s is a wand of digging!",  517.  				xname(otmp)); 518. 			    doknown = TRUE; 519. 			}  520.  			if (!Blind) 521. 			    post_engr_text = "Gravel flies up from the floor."; 522. 			else 523. 			    post_engr_text = "You hear drilling!"; 524. 			break; 525.  526.  		    /* type = BURN wands */ 527. 		    case WAN_FIRE: 528. 			ptext = TRUE; 529. 			type  = BURN; 530. 			if(!objects[otmp->otyp].oc_name_known) { 531. 	    		if (flags.verbose) 532. 			    pline("This %s is a wand of fire!", xname(otmp)); 533. 			    doknown = TRUE; 534. 			}  535.  			if (!Blind) 536. 			    post_engr_text = "Flames fly from the wand."; 537. 			else 538. 			    post_engr_text = "You feel the wand heat up."; 539. 			break; 540. 		    case WAN_LIGHTNING: 541. 			ptext = TRUE; 542. 			type  = BURN; 543. 			if(!objects[otmp->otyp].oc_name_known) { 544. 	    		    if (flags.verbose) 545. 				pline("This %s is a wand of lightning!",  546.  					xname(otmp)); 547. 			    doknown = TRUE; 548. 			}  549.  			if (!Blind) { 550. 			    post_engr_text = "Lightning arcs from the wand."; 551. 			    doblind = TRUE; 552. 			} else 553. 			    post_engr_text = "You hear crackling!"; 554. 			break; 555.  556.  		    /* type = MARK wands */ 557. 		    /* type = BLOOD wands */ 558. 		    }  559.  		} else /* end if zappable */ 560. 		    if (Levitation) { 561. 			You("can't reach the floor!"); 562. 			return(0); 563. 		    }  564.  		break; 565.  566.  	    case WEAPON_CLASS: 567. 		if(is_blade(otmp)) 568. 		    if ((int)otmp->spe > -3) 569. 			type = ENGRAVE; 570. 		    else 571. 			Your("%s too dull for engraving.", aobjnam(otmp,"are")); 572. 		break; 573.  574.  	    case TOOL_CLASS: 575. 		if(otmp == ublindf) { 576. 		    pline(  577.  		"That is a bit difficult to engrave with, don't you think?"); 578. 		    return(0); 579. 		}  580.  		switch (otmp->otyp)  { 581. 		    case MAGIC_MARKER: 582. 			if (otmp->spe <= 0) 583. 			    Your("marker has dried out."); 584. 			else 585. 			    type = MARK; 586. 			break; 587. 		    case TOWEL: 588.  			/* Can't really engrave with a towel */ 589. 			ptext = FALSE; 590. 			if (oep) 591. 			    if ((oep->engr_type == DUST ) ||  592.  				(oep->engr_type == BLOOD) ||  593.  				(oep->engr_type == MARK )) { 594. 				if (!Blind) 595. 				    You("wipe out the message here."); 596. 				else 597. 				    Your("%s gets dusty.", xname(otmp)); 598. 				dengr = TRUE; 599. 			    } else 600. 				Your("%s can't wipe out this engraving.",  601.  				     xname(otmp)); 602. 			else 603. 			    Your("%s gets dusty.", xname(otmp)); 604. 			break; 605. 		    default: 606. 			break; 607. 		}  608.  		break; 609.  610.  	    case VENOM_CLASS: 611. #ifdef WIZARD 612. 		if (wizard) { 613. 		    pline("Writing a poison pen letter??"); 614. 		    break; 615. 		}  616.  #endif 617. 	    case ILLOBJ_CLASS: 618. 		impossible("You're engraving with an illegal object!"); 619. 		break; 620. 	}  621.   622.  	/* End of implement setup */ 623.  624.  	/* Identify stylus */ 625. 	if (doknown) { 626. 	    makeknown(otmp->otyp); 627. 	    more_experienced(0,10); 628. 	}  629.   630.  	if (teleengr) { 631. 	    register int tx,ty; 632.  633.  	    do  { 634.  		tx = rn1(COLNO-3,2); 635. 		ty = rn2(ROWNO); 636. 	    } while(!goodpos(tx,ty, (struct monst *)0, (struct permonst *)0)); 637.  638.  	    oep->engr_x = tx; 639. 	    oep->engr_y = ty; 640.  641.  	    oep = (struct engr *)0; 642. 	}  643.   644.  	if (dengr) { 645. 	    del_engr (oep); 646. 	    oep = (struct engr *)0; 647. 	}  648.   649.  	/* Something has changed the engraving here */ 650. 	if (*buf) { 651. 	    make_engr_at(u.ux, u.uy, buf, moves, type); 652. 	    pline("The engraving now reads: \"%s\".", buf); 653. 	    ptext = FALSE; 654. 	}  655.   656.  	if (zapwand && (otmp->spe < 0)) { 657. 	    pline("%s %sturns to dust.",  658.  		  The(xname(otmp)), Blind ? "" : "glows violently, then "); 659. You("are not going to get anywhere trying to write in the dust with your dust."); 660. 	    useup(otmp); 661. 	    ptext = FALSE; 662. 	}  663.   664.  	if (!ptext) {		/* Early exit for some implements. */ 665.  	    if (Levitation && (otmp->oclass == WAND_CLASS)) 666. 		You("can't reach the floor!"); 667. 	    return(1); 668. 	}  669.   670.  	/* Special effects should have deleted the current engraving (if  671.  	 * possible) by now. 672. 	 */  673.   674.  	if (oep) { 675. 	    register char c = 'n'; 676.  677.  	    /* Give player the choice to add to engraving. */ 678.   679.  	    if ( (type == oep->engr_type) && (!Blind || 680. 		 (oep->engr_type == BURN) || (oep->engr_type == ENGRAVE)) ) { 681. 	    	c = yn_function("Do you want to add to the current engraving?",  682.  				ynqchars, 'y'); 683. 		if (c == 'q') { 684. 		    pline("Never mind."); 685. 		    return(0); 686. 		}  687.  	    }  688.   689.  	    if (c == 'n' || Blind) 690.  691.  		if( (oep->engr_type == DUST) || (oep->engr_type == BLOOD) ||  692.  		    (oep->engr_type == MARK) ) { 693. 		    if (!Blind) { 694. 			You("wipe out the message that was %s here.",  695.  			    ((oep->engr_type == DUST)  ? "written in the dust" : 696. 			    ((oep->engr_type == BLOOD) ? "scrawled in blood"   :  697.  							 "written"))); 698. 			del_engr(oep); 699. 			oep = (struct engr *)0; 700. 		    } else 701. 		   /* Don't delete engr until after we *know* we're engraving */ 702. 			eow = TRUE; 703. 		} else 704. 		    if ( (type == DUST) || (type == MARK) || (type == BLOOD) ) { 705. 			You(  706.  		       "cannot wipe out the message that is %s the floor here.",  707.  		            (oep->engr_type == BURN) ? "burned into" :  708.  			    "engraved in"); 709. 			return(1); 710. 		    } else 711. 			if ( (type != oep->engr_type) || (c == 'n') ) { 712. 			    if (!Blind || !Levitation) 713. 				You("will overwrite the current message."); 714. 			    eow = TRUE; 715. 			}  716.  	}  717.   718.  	switch(type){ 719. 	    default: 720. 		everb = (oep && !eow ? "add to the weird writing on" :  721.  				       "write strangely on"); 722. 		eloc  = "the floor"; 723. 		break; 724. 	    case DUST: 725. 		everb = (oep && !eow ? "add to the writing in" :  726.  				       "write in"); 727. 		eloc = "the dust"; 728. 		break; 729. 	    case ENGRAVE: 730. 		everb = (oep && !eow ? "add to the engraving in" :  731.  				       "engrave in"); 732. 		eloc = "the floor"; 733. 		break; 734. 	    case BURN: 735. 		everb = (oep && !eow ? "add to the text burned into" :  736.  				       "burn into"); 737. 		eloc = "the floor"; 738. 		break; 739. 	    case MARK: 740. 		everb = (oep && !eow ? "add to the graffiti on" :  741.  				       "scribble on"); 742. 		eloc = "the floor"; 743. 		break; 744. 	    case BLOOD: 745. 		everb = (oep && !eow ? "add to the scrawl on" :  746.  				       "scrawl on"); 747. 		eloc = "the floor"; 748. 		break; 749. 	}  750.   751.  	/* Tell adventurer what is going on */ 752. 	if (otmp != &zeroobj) 753. 	    You("%s %s with %s.", everb, eloc, doname(otmp)); 754. 	else 755. 	    You("%s %s with your %s.", everb, eloc,  756.  		makeplural(body_part(FINGER))); 757.  758.  	/* Prompt for engraving! */ 759.  	Sprintf(qbuf,"What do you want to %s %s here?", everb, eloc); 760. 	getlin(qbuf, ebuf); 761. 	clear_nhwindow(WIN_MESSAGE); 762.  763.  	/* Mix up engraving if surface or state of mind is unsound. */ 764.  	/* Original kludge by stewr 870708. modified by njm 910722. */ 765.  	for (sp = ebuf; *sp; sp++) 766. 	    if ( ((type == DUST || type == BLOOD) && !rn2(25)) ||  767.  		 (Blind   && !rn2(9)) || (Confusion     && !rn2(12)) ||  768.  		 (Stunned && !rn2(4)) || (Hallucination && !rn2(1)) ) 769. 		 *sp = '!' + rn2(93); /* ASCII-code only */ 770.  771.  	/* Count the actual # of chars engraved not including spaces */ 772. 	len = strlen(ebuf); 773.  774.  	for (sp = ebuf, spct = 0; *sp; sp++) if (isspace(*sp)) spct++; 775.  776.  	if ( (len == spct) || index(ebuf, '\033') ) { 777. 	    if (zapwand) { 778. 		if (!Blind) 779. 		    pline("%s glows, then fades.", The(xname(otmp))); 780. 	    	return(1); 781. 	    } else { 782. 		pline("Never mind."); 783. 		return(0); 784. 	    }  785.  	}  786.   787.  	len -= spct; 788.  789.  	/* Previous engraving is overwritten */ 790. 	if (eow) { 791. 	    del_engr(oep); 792. 	    oep = (struct engr *)0; 793. 	}  794.   795.  	/* Figure out how long it took to engrave, and if player has 796. 	 * engraved too much. 797. 	 */  798.  	switch(type){ 799. 	    default: 800. 		multi = -(len/10); 801. 		if (multi) nomovemsg = "You finish your weird engraving."; 802. 		break; 803. 	    case DUST: 804. 		multi = -(len/10); 805. 		if (multi) nomovemsg = "You finish writing in the dust."; 806. 		break; 807. 	    case ENGRAVE: 808. 		multi = -(len/10); 809. 		if ((otmp->oclass == WEAPON_CLASS) &&  810.  		    ((otmp->otyp != ATHAME) || otmp->cursed)) { 811. 		    multi = -len; 812. 		    maxelen = ((otmp->spe + 3) * 2) + 1; 813. 			/* -2 = 3, -1 = 5, 0 = 7, +1 = 9, +2 = 11  814.  			 * Note: this does not allow a +0 anything (except  815.  			 *	 an athame) to engrave "Elbereth" all at once. 816. 			 *	 However, you could now engrave "Elb", then 817. 			 *	 "ere", then "th". 818. 			 */  819.  		    Your("%s dull.", aobjnam(otmp, "get")); 820. 		    if (len > maxelen) { 821. 		    	multi = -maxelen; 822. 			otmp->spe = -3; 823. 		    } else 824. 			if (len > 1) otmp->spe -= len >> 1; 825. 			else otmp->spe -= 1; /* Prevent infinite engraving */ 826. 		} else 827. 		    if ( (otmp->oclass == RING_CLASS) ||  828.  			 (otmp->oclass == GEM_CLASS) ) 829. 			multi = -len; 830. 		if (multi) nomovemsg = "You finish engraving."; 831. 		break; 832. 	    case BURN: 833. 		multi = -(len/10); 834. 		if (multi) 835. 		    nomovemsg = 836. 			"You finish burning your message into the floor."; 837. 		break; 838. 	    case MARK: 839. 		multi = -(len/10); 840. 		if ((otmp->oclass == TOOL_CLASS) &&  841.  		    (otmp->otyp == MAGIC_MARKER)) { 842. 		    maxelen = (otmp->spe) * 2; /* one charge / 2 letters */ 843. 		    if (len > maxelen) { 844. 			Your("marker dries out."); 845. 			otmp->spe = 0; 846. 			multi = -(maxelen/10); 847. 		    } else 848. 			if (len > 1) otmp->spe -= len >> 1; 849. 			else otmp->spe -= 1; /* Prevent infinite grafitti */ 850. 		}  851.  		if (multi) nomovemsg = "You finish defacing the dungeon."; 852. 		break; 853. 	    case BLOOD: 854. 		multi = -(len/10); 855. 		if (multi) nomovemsg = "You finish scrawling."; 856. 		break; 857. 	}  858.   859.  	/* Chop engraving down to size if necessary */ 860. 	if (len > maxelen) { 861. 	    for (sp = ebuf; (maxelen && *sp); sp++) 862. 		if (!isspace(*sp)) maxelen--; 863. 	    if (!maxelen && *sp) { 864. 		*sp = (char)0; 865. 		if (multi) nomovemsg = "You cannot write any more."; 866. 		You("only are able to write \"%s\"", ebuf); 867. 	    }  868.  	}  869.   870.  	/* Add to existing engraving */ 871. 	if (oep) Strcpy(buf, oep->engr_txt); 872.  873.  	(void) strncat(buf, ebuf, (BUFSZ - (int)strlen(buf) - 1)); 874.  875.  	make_engr_at(u.ux, u.uy, buf, (moves - multi), type); 876.  877.  	if (post_engr_text) pline(post_engr_text); 878.  879.  	if (doblind) { 880. 	    You("are blinded by the flash!"); 881. 	    make_blinded((long)rnd(50),FALSE); 882. 	}  883.   884.  	return(1); 885. }  886.   887.  void 888. save_engravings(fd, mode) 889. int fd, mode; 890. {  891.  	register struct engr *ep = head_engr; 892. 	register struct engr *ep2; 893. #ifdef GCC_WARN 894. 	static long nulls[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 895. #endif 896. 	while(ep) { 897. 	    ep2 = ep->nxt_engr; 898. 	    if(ep->engr_lth && ep->engr_txt[0]){ 899. 		bwrite(fd, (genericptr_t)&(ep->engr_lth), sizeof(ep->engr_lth)); 900. 		bwrite(fd, (genericptr_t)ep, sizeof(struct engr) + ep->engr_lth); 901. 	    }  902.  	    if (mode & FREE_SAVE) 903. 		dealloc_engr(ep); 904. 	    ep = ep2; 905. 	}  906.   907.  #ifdef GCC_WARN 908. 	bwrite(fd, (genericptr_t)nulls, sizeof(unsigned)); 909. #else 910. 	bwrite(fd, (genericptr_t)nul, sizeof(unsigned)); 911. #endif 912.  913.  	if (mode & FREE_SAVE) 914. 	    head_engr = 0; 915. }  916.   917.  void 918. rest_engravings(fd) int fd; { 919. register struct engr *ep; 920. unsigned lth; 921. 	head_engr = 0; 922. 	while(1) { 923. 		mread(fd, (genericptr_t) &lth, sizeof(unsigned)); 924. 		if(lth == 0) return; 925. 		ep = newengr(lth); 926. 		mread(fd, (genericptr_t) ep, sizeof(struct engr) + lth); 927. 		ep->nxt_engr = head_engr; 928. 		head_engr = ep; 929. 		ep->engr_txt = (char *) (ep + 1);	/* Andreas Bormann */ 930. 		/* mark as finished for bones levels -- no problem for 931. 		 * normal levels as the player must have finished engraving 932. 		 * to be able to move again */ 933. 		ep->engr_time = moves; 934. 	}  935.  }  936.   937.  STATIC_OVL void 938. del_engr(ep) register struct engr *ep; { 939. register struct engr *ept; 940. 	if(ep == head_engr) 941. 		head_engr = ep->nxt_engr; 942. 	else { 943. 		for(ept = head_engr; ept; ept = ept->nxt_engr) { 944. 			if(ept->nxt_engr == ep) { 945. 				ept->nxt_engr = ep->nxt_engr; 946. 				goto fnd; 947. 			}  948.  		}  949.  		impossible("Error in del_engr?"); 950. 		return; 951. 	fnd:	; 952. 	}  953.  	dealloc_engr(ep); 954. }  955.   956.  #endif /* OVLB */ 957.  958.  /*engrave.c*/