Source:NetHack 2.3e/engrave.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to engrave.c from the source code of NetHack 2.3e.

Warning! This is the source code from an old release. For newer releases, see Source code

Screenshots and source code from Hack are used under the CWI license.

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.  }