Source:NetHack 3.0.0/engrave.c

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