Source:NetHack 2.3e/engrave.c

Below is the full text to engrave.c from the source code of NetHack 2.3e. To link to a particular line, write [[NetHack 2.3e/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.3	88/02/11 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_LIGHTNING: 248. 				if(!objects[otmp->otyp].oc_name_known) { 249. 					pline("The %s is a wand of lightning!",  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_FIRE: 257. 				if(!objects[otmp->otyp].oc_name_known) { 258. 					pline("The %s is a wand of fire!",  259.  					   xname(otmp)); 260. 					objects[otmp->otyp].oc_name_known = 1; 261. 					more_experienced(0,10); 262. 				}  263.  				type = BURN; 264. 				break; 265. 			case WAN_DIGGING: 266. 				if(!objects[otmp->otyp].oc_name_known) { 267. 					pline("The %s is a wand of digging!",  268.  					   xname(otmp)); 269. 					objects[otmp->otyp].oc_name_known = 1; 270. 					more_experienced(0,10); 271. 				}  272.  				type = ENGRAVE; 273. 				break; 274. 			case WAN_POLYMORPH: 275. 				if(oep)  { 276. 					del_engr(oep); 277. 					oep = 0; 278. 					type = POLY; 279. 				}  else 280. 					type = DUST; 281. 				break; 282. 			case WAN_COLD: 283. 				type = DUST; 284. 				if(!oep || (oep->engr_type != BURN)) 285. 					break; 286. 			case WAN_CANCELLATION: 287. 			case WAN_MAKE_INVISIBLE: 288. 				if(!oep) {		/* Eric Backus */ 289. 					type = DUST; 290. 					break; 291. 				}  292.  				del_engr(oep); 293. 				pline("The engraving on the floor vanishes!"); 294. 				return(1); 295. 				break; 296. 			case WAN_TELEPORTATION: 297. 				if(!oep) 298. 					type = DUST; 299. 				else  { 300. 					register tx,ty; 301.  302.  					do  { 303. 						tx = rn1(COLNO-3,2); 304. 						ty = rn2(ROWNO); 305. 					}  while(!goodpos(tx,ty)); 306. 					oep->engr_x = tx; 307. 					oep->engr_y = ty; 308. 					pline("The engraving on the floor vanishes!"); 309. 					return(1); 310. 				}  311.  				break; 312. 			default: 313. 				type = DUST; 314. 			}  315.  		}  316.  		if(type == DUST) 317. 			pline("You write in the dust with %s.",  318.  			   doname(otmp)); 319. 	  320.  	} else { 321. 		if(otmp->otyp == DAGGER || otmp->otyp == TWO_HANDED_SWORD ||  322.  		otmp->otyp == CRYSKNIFE || otmp->otyp == KATANA ||  323.  		otmp->otyp == SCIMITAR || otmp->otyp == BROAD_SWORD ||  324.  		otmp->otyp == SHORT_SWORD ||  325.  		otmp->otyp == LONG_SWORD || otmp->otyp == AXE) { 326. 			type = ENGRAVE; 327. 			if((int)otmp->spe <= -3) { 328. 				pline("Your %s too dull for engraving.",  329.  					aobjnam(otmp, "are")); 330. 				type = DUST; 331. 				/* following messaged added 10/20/86 - GAN */ 332. 				pline("You write in the dust with %s.",  333.  				   doname(otmp)); 334. 			}  else 335. 				pline("You engrave with %s.", doname(otmp)); 336. #ifdef MARKER 337. 		} else if(otmp->otyp == MAGIC_MARKER)  { 338. 			if(otmp->spe <= 0)  { 339. 				pline("Your marker is dried out."); 340. 				pline("You write in the dust with the marker."); 341. 				type = DUST; 342. 			}  else  { 343. 				pline("You write with %s.", doname(otmp)); 344. 				type = MARK; 345. 			}  346.  #endif 347. 		}  else  { 348. 			pline("You write in the dust with %s.",  349.  			   doname(otmp)); 350. 			type = DUST; 351. 		}  352.  	}  353.  	  354.  	if(type != POLY && oep && oep->engr_type == DUST){ 355. 		  pline("You wipe out the message that was written here."); 356. 		  del_engr(oep); 357. 		  oep = 0; 358. 	}  359.  	if(type == DUST && oep){ 360. 	pline("You cannot wipe out the message that is %s in the rock.",  361.  		    (oep->engr_type == BURN) ? "burned" : (oep->engr_type == ENGRAVE)? "engraved" : "scribbled"); 362. 		  return(1); 363. 	}  364.  	if(type == POLY)  { 365. #ifdef MARKER 366. 		type = rnd(4); 367. #else 368. 		type = rnd(3); 369. #endif 370. 		strcpy(buf,random_engr[rn2(RAND_ENGRS)]); 371. 		switch(type){ 372. 		case DUST: 373. 			pline("\"%s\" is now written on the ground.",buf); 374. 			break; 375. 		case ENGRAVE: 376. 			pline("\"%s\" is now engraved in the rock.",buf); 377. 			break; 378. 		case BURN: 379. 			pline("\"%s\" is now burned in the rock.",buf); 380. 			break; 381. #ifdef MARKER 382. 		case MARK: 383. 			pline("\"%s\" is now scribbled on the rock.",buf); 384. 			break; 385. #endif 386. 		default: 387. 			impossible("\"%s\" is now written in a very strange way.",  388.  			   buf); 389. 		}  390.  	}  else  { 391. 		pline("What do you want to %s on the floor here? ",  392.  		  (type == ENGRAVE) ? "engrave" : (type == BURN) ? "burn" : "write"); 393. 		getlin(buf); 394. 		clrlin; 395. 	}  396.  	spct = 0; 397. 	sp = buf; 398. 	while(*sp == ' ') spct++, sp++; 399. 	len = strlen(sp); 400. 	if(!len || *buf == '\033') { 401. 		/* changed by GAN 11/01/86 to not recharge wand */ 402. 		return(1); 403. 	}  404.  	if(otmp->otyp == WAN_FIRE) { 405. 		if (!Blind) pline("Flames fly from the wand."); 406. 		else pline("You feel the wand heat up."); 407. 	} else if(otmp->otyp == WAN_LIGHTNING) { 408. 		if (!Blind) { 409. 			pline("Sparks fly from the wand."); 410. 			pline("You are blinded by the flashing!"); 411. 			Blinded += rnd(50); 412. 			seeoff(0); 413. 		} else pline("You hear crackling!"); 414. 	} else if(otmp->otyp == WAN_DIGGING) { 415. 		if (!Blind) pline("Gravel flies up from the floor."); 416. 		else pline("You hear drilling!"); 417.   	}  418.  	        /* kludge by stewr 870708 */ 419. 	for (sptmp = sp, tmp=0; !(tmp == len); sptmp++,tmp++) { 420. 	        if (((type == DUST) && !rn2(25))  421.  		     || (Blind && !rn2(12))  422.  		     || (Confusion && !rn2(3))) { 423. 		         *sptmp = '!' + rn2(93); /* ASCII-code only */ 424. 		       }  425.  	      }  426.   427.  	switch(type) { 428. 	case DUST: 429. 	case BURN: 430. 		if(len > 15) { 431. 			multi = -(len/10); 432. 			nomovemsg = "You finished writing."; 433. 		}  434.  		break; 435. 	case ENGRAVE: 436. #ifdef MARKER 437. 	case MARK: 438. 		{	int len2; 439. 		  440.  			if(type == ENGRAVE) 441. 				len2 = (otmp->spe + 3) * 2 + 1; 442. 			else 443. 				len2 = (otmp->spe) * 2; 444. 			nomovemsg = "You finished writing."; 445. 			if(type != MARK) 446. #else 447. 		{	int len2 = (otmp->spe + 3) * 2 + 1; 448. #endif 449. 			nomovemsg = "You finished engraving."; 450. 			if(otmp->olet != WAND_SYM)  { 451. 				if(otmp->olet == WEAPON_SYM) 452. 					pline("Your %s dull.",  453.  					       aobjnam(otmp, "get")); 454. 				if(len2 < len) { 455. 					len = len2; 456. 					sp[len] = 0; 457. 					if(type == ENGRAVE)  { 458. 						otmp->spe = -3; 459. 					}  else  { 460. 						pline("Your marker dries out!"); 461. 						otmp->spe = 0; 462. 					}  463.  					/* next line added by GAN 10/20/86 */ 464. 					pline("You only write \"%s\".", sp); 465. 					nomovemsg = "You cannot write more."; 466. 				} else 467. 					otmp->spe -= len/2; 468. #ifdef MARKER 469. 				if(type == MARK) 470. 					multi = -(len/10); 471. 				else 472. #endif 473. 					multi = -len; 474. 			}  else 475. 				multi = -(len/10); 476. 		}  477.  		break; 478. 	}  479.  	if(oep) len += strlen(oep->engr_txt) + spct; 480. 	ep = (struct engr *) alloc((unsigned)(sizeof(struct engr) + len + 1)); 481. 	ep->nxt_engr = head_engr; 482. 	head_engr = ep; 483. 	ep->engr_x = u.ux; 484. 	ep->engr_y = u.uy; 485. 	sp = (char *)(ep + 1);	/* (char *)ep + sizeof(struct engr) */ 486. 	ep->engr_txt = sp; 487. 	if(oep) { 488. 		(void) strcpy(sp, oep->engr_txt); 489. 		(void) strcat(sp, buf); 490. 		del_engr(oep); 491. 	} else 492. 		(void) strcpy(sp, buf); 493. 	ep->engr_lth = len+1; 494. 	ep->engr_type = type; 495. 	ep->engr_time = moves-multi; 496.  497.  	/* kludge to protect pline against excessively long texts */ 498. 	if(len > BUFSZ-20) sp[BUFSZ-20] = 0; 499. 	  500.  	/* cute messages for odd wands */ 501. 	switch(otmp->otyp)  { 502. 	case WAN_SLOW_MONSTER: 503. 		pline("The bugs on the ground slow down!"); 504. 		break; 505. 	case WAN_SPEED_MONSTER: 506. 		pline("The bugs on the ground speed up!"); 507. 		break; 508. 	case WAN_MAGIC_MISSILE: 509. 		pline("The ground is riddled by bullet holes!"); 510. 		break; 511. 	case WAN_SLEEP: 512. 	case WAN_DEATH:	/* can't tell sleep from death - Eric Backus */ 513. 		pline("The bugs on the ground stop moving!"); 514. 		break; 515. 	case WAN_COLD: 516. 		pline("A few ice cubes drop from your %s.",xname(otmp)); 517. 		break; 518. 	case WAN_STRIKING: 519. 		pline("The %s unsuccessfully fights your attempt to write!",xname(otmp)); 520. 	}  521.   522.  	return(1); 523. }  524.   525.  save_engravings(fd) int fd; { 526. register struct engr *ep = head_engr; 527. 	while(ep) { 528. 		if(!ep->engr_lth || !ep->engr_txt[0]){ 529. 			ep = ep->nxt_engr; 530. 			continue; 531. 		}  532.  		bwrite(fd, (char *) & (ep->engr_lth), sizeof(ep->engr_lth)); 533. 		bwrite(fd, (char *) ep, sizeof(struct engr) + ep->engr_lth); 534. 		ep = ep->nxt_engr; 535. 	}  536.  	bwrite(fd, (char *) nul, sizeof(unsigned)); 537. #ifdef DGK 538. 	if (!count_only) 539. #endif 540. 		head_engr = 0; 541. }  542.   543.  rest_engravings(fd) int fd; { 544. register struct engr *ep; 545. unsigned lth; 546. 	head_engr = 0; 547. 	while(1) { 548. 		mread(fd, (char *) &lth, sizeof(unsigned)); 549. 		if(lth == 0) return; 550. 		ep = (struct engr *) alloc(sizeof(struct engr) + lth); 551. 		mread(fd, (char *) ep, sizeof(struct engr) + lth); 552. 		ep->nxt_engr = head_engr; 553. 		ep->engr_txt = (char *) (ep + 1);	/* Andreas Bormann */ 554. 		head_engr = ep; 555. 	}  556.  }  557.   558.  del_engr(ep) register struct engr *ep; { 559. register struct engr *ept; 560. 	if(ep == head_engr) 561. 		head_engr = ep->nxt_engr; 562. 	else { 563. 		for(ept = head_engr; ept; ept = ept->nxt_engr) { 564. 			if(ept->nxt_engr == ep) { 565. 				ept->nxt_engr = ep->nxt_engr; 566. 				goto fnd; 567. 			}  568.  		}  569.  		impossible("Error in del_engr?"); 570. 		return; 571. 	fnd:	; 572. 	}  573.  	free((char *) ep); 574. }