Source:NetHack 1.4f/engrave.c

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