Source:NetHack 1.3d/engrave.c

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