Source:NetHack 3.0.0/engrave.c

From NetHackWiki
Jump to navigation Jump to search

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

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

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