Source:NetHack 2.2a/engrave.c

Below is the full text to engrave.c from the source code of NetHack 2.2a. To link to a particular line, write [[NetHack 2.2a/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	2.0	87/09/14 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.     4.    #include	"hack.h"  5. 6.   extern char *nomovemsg; 7.   extern char nul[]; 8.   extern struct obj zeroobj; 9.   #ifdef KAA 10.  extern char *xname; 11.  #endif 12.  struct engr { 13.  	struct engr *nxt_engr; 14.  	char *engr_txt; 15.  	xchar engr_x, engr_y; 16.  	unsigned engr_lth;	/* for save & restore; not length of text */ 17.  	long engr_time;	/* moment engraving was (will be) finished */ 18.  	xchar engr_type; 19.  #define	DUST	1 20.  #define	ENGRAVE	2 21.  #define	BURN	3 22.  #ifdef MARKER 23.  #define MARK	4 24.  #define POLY	5	/* temporary type - for polymorphing engraving */ 25.  #else 26.  #define POLY	4	/* temporary type - for polymorphing engraving */ 27.  #endif 28.  } *head_engr; 29.   30.   /* random engravings */ 31.  #ifdef KAA 32.  char *random_engr[] = 33.  #else 34.  char random_engr[][30] = 35.  #endif 36.  			 {"Elbereth", "ad ae?ar um", 37.  #ifdef NEWCLASS 38.  			 "?la? ?as he??", 39.  #endif 40.  			/* more added by Eric Backus */ 41.  			"?ilroy wa? h?re", "?ala??iel", "Aba?don H?pe...", 42.  			"Fo? a ?ood time c?ll 6?6-4311"}; 43.  #ifdef NEWCLASS 44.  #define RAND_ENGRS	7 45.  #else 46.  #define RAND_ENGRS	6 47.  #endif 48.   49.   struct engr * 50.  engr_at(x,y) register xchar x,y; { 51.  register struct engr *ep = head_engr; 52.  	while(ep) { 53.  		if(x == ep->engr_x && y == ep->engr_y) 54.  			return(ep); 55.  		ep = ep->nxt_engr; 56.  	}  57.   	return((struct engr *) 0); 58.  }  59.    60.   sengr_at(s,x,y) register char *s; register xchar x,y; { 61.  register struct engr *ep = engr_at(x,y); 62.  register char *t; 63.  register int n;  64. if(ep && ep->engr_time <= moves) { 65.  		t = ep->engr_txt; 66.  /*  67.   		if(!strcmp(s,t)) return(1); 68.  */  69.   		n = strlen(s); 70.  		while(*t) { 71.  			if(!strncmp(s,t,n)) return(1); 72.  			t++; 73.  		}  74.   	}  75.   	return(0); 76.  }  77.    78.   u_wipe_engr(cnt) 79.  register int cnt; 80.  {  81.   	if(!u.uswallow && !Levitation) 82.  		wipe_engr_at(u.ux, u.uy, cnt); 83.  }  84.    85.   wipe_engr_at(x,y,cnt) register xchar x,y,cnt; { 86.  register struct engr *ep = engr_at(x,y); 87.  register int lth,pos; 88.  char ch; 89.  	if(ep){ 90.  	    if(ep->engr_type != BURN) { 91.  		if(ep->engr_type != DUST) { 92.  			cnt = rn2(1 + 50/(cnt+1)) ? 0 : 1; 93.   		}  94.   		lth = strlen(ep->engr_txt); 95.  		if(lth && cnt > 0 ) { 96.  			while(cnt--) { 97.  				pos = rn2(lth); 98.  				if((ch = ep->engr_txt[pos]) == ' ') 99.  					continue; 100. 				ep->engr_txt[pos] = (ch != '?') ? '?' : ' '; 101.  			}  102.  		}  103.  		while(lth && ep->engr_txt[lth-1] == ' ') 104. 			ep->engr_txt[--lth] = 0; 105. 		while(ep->engr_txt[0] == ' ') 106. 			ep->engr_txt++; 107. 		if(!ep->engr_txt[0]) del_engr(ep); 108. 	    }  109.  	}  110.  }  111.   112.  read_engr_at(x,y) register int x,y; { 113. register struct engr *ep = engr_at(x,y); 114. register int	canfeel; 115. 	if(ep && ep->engr_txt[0]) { 116. 	    switch(ep->engr_type) { 117. 	    case DUST: 118. 		if(!Blind) pline("Something is written here in the dust."); 119. 		canfeel = 0; 120. 		break; 121. 	    case ENGRAVE: 122. 		pline("Something is engraved here on the floor."); 123. 		canfeel = 1; 124. 		break; 125. 	    case BURN: 126. 		pline("Some text has been burned here in the floor."); 127. 		canfeel = 1; 128. 		break; 129. #ifdef MARKER 130. 	    case MARK: 131. 		if(!Blind) pline("There's some graffiti here on the floor."); 132. 		canfeel = 0; 133. 		break; 134. #endif 135. 	    default: 136. 		impossible("Something is written in a very strange way."); 137. 		canfeel = 1; 138. 	    }  139.  	    if (canfeel || !Blind) 140. 		pline("You %s: \"%s\".",  141.  		      (Blind) ? "feel the words" : "read",  ep->engr_txt); 142. 	}  143.  }  144.   145.  make_engr_at(x,y,s) 146. register int x,y; 147. register char *s; 148. {  149.  	register struct engr *ep; 150.  151.  	if(ep = engr_at(x,y)) 152. 	    del_engr(ep); 153. 	ep = (struct engr *) 154. 	    alloc((unsigned)(sizeof(struct engr) + strlen(s) + 1)); 155. 	ep->nxt_engr = head_engr; 156. 	head_engr = ep; 157. 	ep->engr_x = x;  158. ep->engr_y = y; 159. ep->engr_txt = (char *)(ep + 1); 160. 	(void) strcpy(ep->engr_txt, s); 161. 	ep->engr_time = 0; 162. 	ep->engr_type = DUST; 163. 	ep->engr_lth = strlen(s) + 1; 164. }  165.  /*  166.   *	freehand - returns true if player has a free hand 167.  */  168.  int 169. freehand{ 170.  171.  	return(!uwep ||  172.  	   !uwep->cursed ||  173.  	   (uwep->otyp != TWO_HANDED_SWORD && (!uarms || !uarms->cursed))); 174. /*	if ((uwep && uwep->otyp == TWO_HANDED_SWORD) ||  175.  	    (uwep && uarms)) 176. 		return(0); 177. 	else 178. 		return(1);*/ 179. }  180.   181.   182.   183.  doengrave{ 184. register int len, tmp; 185. register char *sp, *sptmp; 186. register struct engr *ep, *oep = engr_at(u.ux,u.uy); 187. char buf[BUFSZ]; 188. xchar type; 189. int spct;		/* number of leading spaces */ 190. register struct obj *otmp; 191. 	multi = 0; 192.  193.  	if(u.uswallow) { 194. 		pline("You're joking. Hahaha!");	/* riv05!a3 */ 195. 		return(0); 196. 	}  197.   198.  	/* one may write with finger, weapon or wand */ 199. 	/* edited by GAN 10/20/86 so as not to change 200. 	 * weapon wielded. 201. 	 */  202.  	otmp = getobj("#-/", "write with"); 203. 	if(!otmp) return(0); 204.  205.  #ifdef FREEHAND /* There's no reason you should be able to write with a wand 206. 		 * while both your hands are tied up. Also, it's necessary to 207. * prevent engraving with "worn" objects other than weapons. 208. 		 */  209.  	if (!freehand && otmp != uwep) { 210. #else 211. 	/* added by GAN 10/20/86 to require you to need a hand to  212. write with. 213. 	 */  214.  	if(!(otmp->owornmask || otmp->olet == WAND_SYM) && !freehand)  { 215. #endif 216. 		pline("You have no free hand to write with!"); 217. 		return(0); 218. 	}  219.  #ifdef KAA 220. 	if (cantwield(u.usym)) { 221. 		pline("You can't even hold anything!"); 222. 		return(0); 223. 	}  224.  	if(otmp != &zeroobj && index("][0`",otmp->olet)) { 225. 		pline("You can't engrave with such a large object!"); 226. 		return(1); 227. 	}  228.  #endif 229.  230.  	if(Levitation && otmp->olet != WAND_SYM){		/* riv05!a3 */ 231. 		pline("You can't reach the floor!"); 232. 		return(0); 233. 	}  234.   235.  	if(otmp == &zeroobj) { 236. 		pline("You write in the dust with your fingers."); 237. 		type = DUST; 238. 	} else if(otmp->olet == WAND_SYM && zappable(otmp)) { 239. 		/* changed so any wand gets zapped out, but fire 240. 		 * wands become known. 241. 		 */  242.  		if((objects[otmp->otyp].bits & NODIR))  { 243. 			zapnodir(otmp); 244. 			type = DUST; 245. 		}  else  { 246. 			switch(otmp->otyp)  { 247. 			case WAN_FIRE: 248. 				if(!objects[otmp->otyp].oc_name_known) { 249. 					pline("The %s is a wand of fire!",  250.  					   xname(otmp)); 251. 					objects[otmp->otyp].oc_name_known = 1; 252. 					more_experienced(0,10); 253. 				}  254.  				type = BURN; 255. 				break; 256. 			case WAN_DIGGING: 257. 				if(!objects[otmp->otyp].oc_name_known) { 258. 					pline("The %s is a wand of digging!",  259.  					   xname(otmp)); 260. 					objects[otmp->otyp].oc_name_known = 1; 261. 					more_experienced(0,10); 262. 				}  263.  				type = ENGRAVE; 264. 				break; 265. 			case WAN_POLYMORPH: 266. 				if(oep)  { 267. 					del_engr(oep); 268. 					oep = 0; 269. 					type = POLY; 270. 				}  else 271. 					type = DUST; 272. 				break; 273. 			case WAN_COLD: 274. 				type = DUST; 275. 				if(!oep || (oep->engr_type != BURN)) 276. 					break; 277. 			case WAN_CANCELLATION: 278. 			case WAN_MAKE_INVISIBLE: 279. 				if(!oep) {		/* Eric Backus */ 280. 					type = DUST; 281. 					break; 282. 				}  283.  				del_engr(oep); 284. 				pline("The engraving on the floor vanishes!"); 285. 				return(1); 286. 				break; 287. 			case WAN_TELEPORTATION: 288. 				if(!oep) 289. 					type = DUST; 290. 				else  { 291. 					register tx,ty; 292.  293.  					do  { 294. 						tx = rn1(COLNO-3,2); 295. 						ty = rn2(ROWNO); 296. 					}  while(!goodpos(tx,ty)); 297. 					oep->engr_x = tx; 298. 					oep->engr_y = ty; 299. 					pline("The engraving on the floor vanishes!"); 300. 					return(1); 301. 				}  302.  				break; 303. 			default: 304. 				type = DUST; 305. 			}  306.  		}  307.  		if(type == DUST) 308. 			pline("You write in the dust with %s.",  309.  			   doname(otmp)); 310. 	  311.  	} else { 312. 		if(otmp->otyp == DAGGER || otmp->otyp == TWO_HANDED_SWORD ||  313.  		otmp->otyp == CRYSKNIFE || otmp->otyp == KATANA ||  314.  		otmp->otyp == SCIMITAR || otmp->otyp == BROAD_SWORD ||  315.  		otmp->otyp == SHORT_SWORD ||  316.  		otmp->otyp == LONG_SWORD || otmp->otyp == AXE) { 317. 			type = ENGRAVE; 318. 			if((int)otmp->spe <= -3) { 319. 				pline("Your %s too dull for engraving.",  320.  					aobjnam(otmp, "are")); 321. 				type = DUST; 322. 				/* following messaged added 10/20/86 - GAN */ 323. 				pline("You write in the dust with %s.",  324.  				   doname(otmp)); 325. 			}  else 326. 				pline("You engrave with %s.", doname(otmp)); 327. #ifdef MARKER 328. 		} else if(otmp->otyp == MAGIC_MARKER)  { 329. 			if(otmp->spe <= 0)  { 330. 				pline("Your marker is dried out."); 331. 				pline("You write in the dust with the marker."); 332. 				type = DUST; 333. 			}  else  { 334. 				pline("You write with %s.", doname(otmp)); 335. 				type = MARK; 336. 			}  337.  #endif 338. 		}  else  { 339. 			pline("You write in the dust with %s.",  340.  			   doname(otmp)); 341. 			type = DUST; 342. 		}  343.  	}  344.  	  345.  	if(type != POLY && oep && oep->engr_type == DUST){ 346. 		  pline("You wipe out the message that was written here."); 347. 		  del_engr(oep); 348. 		  oep = 0; 349. 	}  350.  	if(type == DUST && oep){ 351. 	pline("You cannot wipe out the message that is %s in the rock.",  352.  		    (oep->engr_type == BURN) ? "burned" : (oep->engr_type == ENGRAVE)? "engraved" : "scribbled"); 353. 		  return(1); 354. 	}  355.  	if(type == POLY)  { 356. #ifdef MARKER 357. 		type = rnd(4); 358. #else 359. 		type = rnd(3); 360. #endif 361. 		strcpy(buf,random_engr[rn2(RAND_ENGRS)]); 362. 		switch(type){ 363. 		case DUST: 364. 			pline("\"%s\" is now written on the ground.",buf); 365. 			break; 366. 		case ENGRAVE: 367. 			pline("\"%s\" is now engraved in the rock.",buf); 368. 			break; 369. 		case BURN: 370. 			pline("\"%s\" is now burned in the rock.",buf); 371. 			break; 372. #ifdef MARKER 373. 		case MARK: 374. 			pline("\"%s\" is now scribbled on the rock.",buf); 375. 			break; 376. #endif 377. 		default: 378. 			impossible("\"%s\" is now written in a very strange way.",  379.  			   buf); 380. 		}  381.  	}  else  { 382. 		pline("What do you want to %s on the floor here? ",  383.  		  (type == ENGRAVE) ? "engrave" : (type == BURN) ? "burn" : "write"); 384. 		getlin(buf); 385. 		clrlin; 386. 	}  387.  	spct = 0; 388. 	sp = buf; 389. 	while(*sp == ' ') spct++, sp++; 390. 	len = strlen(sp); 391. 	if(!len || *buf == '\033') { 392. 		/* changed by GAN 11/01/86 to not recharge wand */ 393. 		if(type == BURN) 394. 			pline("A few sparks fly from the wand of fire."); 395. 		else 396. 			if(otmp->otyp == WAN_DIGGING) 397. 				pline("Gravel flies up from the floor."); 398. 		return(1); 399. 	}  400.  	        /* kludge by stewr 870708 */ 401. 	for (sptmp = sp, tmp=0; !(tmp == len); sptmp++,tmp++) { 402. 	        if (((type == DUST) && !rn2(25))  403.  		     || (Blind && !rn2(12))  404.  		     || (Confusion && !rn2(3))) { 405. 		         *sptmp = '!' + rn2(93); /* ASCII-code only */ 406. 		       }  407.  	      }  408.   409.  	switch(type) { 410. 	case DUST: 411. 	case BURN: 412. 		if(len > 15) { 413. 			multi = -(len/10); 414. 			nomovemsg = "You finished writing."; 415. 		}  416.  		break; 417. 	case ENGRAVE: 418. #ifdef MARKER 419. 	case MARK: 420. 		{	int len2; 421. 		  422.  			if(type == ENGRAVE) 423. 				len2 = (otmp->spe + 3) * 2 + 1; 424. 			else 425. 				len2 = (otmp->spe) * 2; 426. 			nomovemsg = "You finished writing."; 427. 			if(type != MARK) 428. #else 429. 		{	int len2 = (otmp->spe + 3) * 2 + 1; 430. #endif 431. 			nomovemsg = "You finished engraving."; 432. 			if(otmp->olet != WAND_SYM)  { 433. 				if(otmp->olet == WEAPON_SYM) 434. 					pline("Your %s dull.",  435.  					       aobjnam(otmp, "get")); 436. 				if(len2 < len) { 437. 					len = len2; 438. 					sp[len] = 0; 439. 					if(type == ENGRAVE)  { 440. 						otmp->spe = -3; 441. 					}  else  { 442. 						pline("Your marker dries out!"); 443. 						otmp->spe = 0; 444. 					}  445.  					/* next line added by GAN 10/20/86 */ 446. 					pline("You only write \"%s\".", sp); 447. 					nomovemsg = "You cannot write more."; 448. 				} else 449. 					otmp->spe -= len/2; 450. #ifdef MARKER 451. 				if(type == MARK) 452. 					multi = -(len/10); 453. 				else 454. #endif 455. 					multi = -len; 456. 			}  else 457. 				multi = -(len/10); 458. 		}  459.  		break; 460. 	}  461.  	if(oep) len += strlen(oep->engr_txt) + spct; 462. 	ep = (struct engr *) alloc((unsigned)(sizeof(struct engr) + len + 1)); 463. 	ep->nxt_engr = head_engr; 464. 	head_engr = ep; 465. 	ep->engr_x = u.ux; 466. 	ep->engr_y = u.uy; 467. 	sp = (char *)(ep + 1);	/* (char *)ep + sizeof(struct engr) */ 468. 	ep->engr_txt = sp; 469. 	if(oep) { 470. 		(void) strcpy(sp, oep->engr_txt); 471. 		(void) strcat(sp, buf); 472. 		del_engr(oep); 473. 	} else 474. 		(void) strcpy(sp, buf); 475. 	ep->engr_lth = len+1; 476. 	ep->engr_type = type; 477. 	ep->engr_time = moves-multi; 478.  479.  	/* kludge to protect pline against excessively long texts */ 480. 	if(len > BUFSZ-20) sp[BUFSZ-20] = 0; 481. 	  482.  	/* cute messages for odd wands */ 483. 	switch(otmp->otyp)  { 484. 	case WAN_SLOW_MONSTER: 485. 		pline("The bugs on the ground slow down!"); 486. 		break; 487. 	case WAN_SPEED_MONSTER: 488. 		pline("The bugs on the ground speed up!"); 489. 		break; 490. 	case WAN_MAGIC_MISSILE: 491. 		pline("The ground is riddled by bullet holes!"); 492. 		break; 493. 	case WAN_SLEEP: 494. 	case WAN_DEATH:	/* can't tell sleep from death - Eric Backus */ 495. 		pline("The bugs on the ground stop moving!"); 496. 		break; 497. 	case WAN_COLD: 498. 		pline("A few ice cubes drop from your %s.",xname(otmp)); 499. 		break; 500. 	case WAN_STRIKING: 501. 		pline("The %s unsuccessfully fights your attempt to write!",xname(otmp)); 502. 	}  503.   504.  	return(1); 505. }  506.   507.  save_engravings(fd) int fd; { 508. register struct engr *ep = head_engr; 509. 	while(ep) { 510. 		if(!ep->engr_lth || !ep->engr_txt[0]){ 511. 			ep = ep->nxt_engr; 512. 			continue; 513. 		}  514.  		bwrite(fd, (char *) & (ep->engr_lth), sizeof(ep->engr_lth)); 515. 		bwrite(fd, (char *) ep, sizeof(struct engr) + ep->engr_lth); 516. 		ep = ep->nxt_engr; 517. 	}  518.  	bwrite(fd, (char *) nul, sizeof(unsigned)); 519. #ifdef DGK 520. 	if (!count_only) 521. #endif 522. 		head_engr = 0; 523. }  524.   525.  rest_engravings(fd) int fd; { 526. register struct engr *ep; 527. unsigned lth; 528. 	head_engr = 0; 529. 	while(1) { 530. 		mread(fd, (char *) &lth, sizeof(unsigned)); 531. 		if(lth == 0) return; 532. 		ep = (struct engr *) alloc(sizeof(struct engr) + lth); 533. 		mread(fd, (char *) ep, sizeof(struct engr) + lth); 534. 		ep->nxt_engr = head_engr; 535. 		ep->engr_txt = (char *) (ep + 1);	/* Andreas Bormann */ 536. 		head_engr = ep; 537. 	}  538.  }  539.   540.  del_engr(ep) register struct engr *ep; { 541. register struct engr *ept; 542. 	if(ep == head_engr) 543. 		head_engr = ep->nxt_engr; 544. 	else { 545. 		for(ept = head_engr; ept; ept = ept->nxt_engr) { 546. 			if(ept->nxt_engr == ep) { 547. 				ept->nxt_engr = ep->nxt_engr; 548. 				goto fnd; 549. 			}  550.  		}  551.  		impossible("Error in del_engr?"); 552. 		return; 553. 	fnd:	; 554. 	}  555.  	free((char *) ep); 556. }