xref: /openbsd-src/games/hack/hack.engrave.c (revision df930be708d50e9715f173caa26ffe1b7599b157)
1*df930be7Sderaadt /*
2*df930be7Sderaadt  * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985.
3*df930be7Sderaadt  */
4*df930be7Sderaadt 
5*df930be7Sderaadt #ifndef lint
6*df930be7Sderaadt static char rcsid[] = "$NetBSD: hack.engrave.c,v 1.3 1995/03/23 08:30:08 cgd Exp $";
7*df930be7Sderaadt #endif /* not lint */
8*df930be7Sderaadt 
9*df930be7Sderaadt #include	"hack.h"
10*df930be7Sderaadt 
11*df930be7Sderaadt extern char *nomovemsg;
12*df930be7Sderaadt extern char nul[];
13*df930be7Sderaadt extern struct obj zeroobj;
14*df930be7Sderaadt struct engr {
15*df930be7Sderaadt 	struct engr *nxt_engr;
16*df930be7Sderaadt 	char *engr_txt;
17*df930be7Sderaadt 	xchar engr_x, engr_y;
18*df930be7Sderaadt 	unsigned engr_lth;	/* for save & restore; not length of text */
19*df930be7Sderaadt 	long engr_time;	/* moment engraving was (will be) finished */
20*df930be7Sderaadt 	xchar engr_type;
21*df930be7Sderaadt #define	DUST	1
22*df930be7Sderaadt #define	ENGRAVE	2
23*df930be7Sderaadt #define	BURN	3
24*df930be7Sderaadt } *head_engr;
25*df930be7Sderaadt 
26*df930be7Sderaadt struct engr *
27*df930be7Sderaadt engr_at(x,y) register xchar x,y; {
28*df930be7Sderaadt register struct engr *ep = head_engr;
29*df930be7Sderaadt 	while(ep) {
30*df930be7Sderaadt 		if(x == ep->engr_x && y == ep->engr_y)
31*df930be7Sderaadt 			return(ep);
32*df930be7Sderaadt 		ep = ep->nxt_engr;
33*df930be7Sderaadt 	}
34*df930be7Sderaadt 	return((struct engr *) 0);
35*df930be7Sderaadt }
36*df930be7Sderaadt 
37*df930be7Sderaadt sengr_at(s,x,y) register char *s; register xchar x,y; {
38*df930be7Sderaadt register struct engr *ep = engr_at(x,y);
39*df930be7Sderaadt register char *t;
40*df930be7Sderaadt register int n;
41*df930be7Sderaadt 	if(ep && ep->engr_time <= moves) {
42*df930be7Sderaadt 		t = ep->engr_txt;
43*df930be7Sderaadt /*
44*df930be7Sderaadt 		if(!strcmp(s,t)) return(1);
45*df930be7Sderaadt */
46*df930be7Sderaadt 		n = strlen(s);
47*df930be7Sderaadt 		while(*t) {
48*df930be7Sderaadt 			if(!strncmp(s,t,n)) return(1);
49*df930be7Sderaadt 			t++;
50*df930be7Sderaadt 		}
51*df930be7Sderaadt 	}
52*df930be7Sderaadt 	return(0);
53*df930be7Sderaadt }
54*df930be7Sderaadt 
55*df930be7Sderaadt u_wipe_engr(cnt)
56*df930be7Sderaadt register int cnt;
57*df930be7Sderaadt {
58*df930be7Sderaadt 	if(!u.uswallow && !Levitation)
59*df930be7Sderaadt 		wipe_engr_at(u.ux, u.uy, cnt);
60*df930be7Sderaadt }
61*df930be7Sderaadt 
62*df930be7Sderaadt wipe_engr_at(x,y,cnt) register xchar x,y,cnt; {
63*df930be7Sderaadt register struct engr *ep = engr_at(x,y);
64*df930be7Sderaadt register int lth,pos;
65*df930be7Sderaadt char ch;
66*df930be7Sderaadt 	if(ep){
67*df930be7Sderaadt 		if((ep->engr_type != DUST) || Levitation) {
68*df930be7Sderaadt 			cnt = rn2(1 + 50/(cnt+1)) ? 0 : 1;
69*df930be7Sderaadt 		}
70*df930be7Sderaadt 		lth = strlen(ep->engr_txt);
71*df930be7Sderaadt 		if(lth && cnt > 0 ) {
72*df930be7Sderaadt 			while(cnt--) {
73*df930be7Sderaadt 				pos = rn2(lth);
74*df930be7Sderaadt 				if((ch = ep->engr_txt[pos]) == ' ')
75*df930be7Sderaadt 					continue;
76*df930be7Sderaadt 				ep->engr_txt[pos] = (ch != '?') ? '?' : ' ';
77*df930be7Sderaadt 			}
78*df930be7Sderaadt 		}
79*df930be7Sderaadt 		while(lth && ep->engr_txt[lth-1] == ' ')
80*df930be7Sderaadt 			ep->engr_txt[--lth] = 0;
81*df930be7Sderaadt 		while(ep->engr_txt[0] == ' ')
82*df930be7Sderaadt 			ep->engr_txt++;
83*df930be7Sderaadt 		if(!ep->engr_txt[0]) del_engr(ep);
84*df930be7Sderaadt 	}
85*df930be7Sderaadt }
86*df930be7Sderaadt 
87*df930be7Sderaadt read_engr_at(x,y) register int x,y; {
88*df930be7Sderaadt register struct engr *ep = engr_at(x,y);
89*df930be7Sderaadt 	if(ep && ep->engr_txt[0]) {
90*df930be7Sderaadt 	    switch(ep->engr_type) {
91*df930be7Sderaadt 	    case DUST:
92*df930be7Sderaadt 		pline("Something is written here in the dust.");
93*df930be7Sderaadt 		break;
94*df930be7Sderaadt 	    case ENGRAVE:
95*df930be7Sderaadt 		pline("Something is engraved here on the floor.");
96*df930be7Sderaadt 		break;
97*df930be7Sderaadt 	    case BURN:
98*df930be7Sderaadt 		pline("Some text has been burned here in the floor.");
99*df930be7Sderaadt 		break;
100*df930be7Sderaadt 	    default:
101*df930be7Sderaadt 		impossible("Something is written in a very strange way.");
102*df930be7Sderaadt 	    }
103*df930be7Sderaadt 	    pline("You read: \"%s\".", ep->engr_txt);
104*df930be7Sderaadt 	}
105*df930be7Sderaadt }
106*df930be7Sderaadt 
107*df930be7Sderaadt make_engr_at(x,y,s)
108*df930be7Sderaadt register int x,y;
109*df930be7Sderaadt register char *s;
110*df930be7Sderaadt {
111*df930be7Sderaadt 	register struct engr *ep;
112*df930be7Sderaadt 
113*df930be7Sderaadt 	if(ep = engr_at(x,y))
114*df930be7Sderaadt 	    del_engr(ep);
115*df930be7Sderaadt 	ep = (struct engr *)
116*df930be7Sderaadt 	    alloc((unsigned)(sizeof(struct engr) + strlen(s) + 1));
117*df930be7Sderaadt 	ep->nxt_engr = head_engr;
118*df930be7Sderaadt 	head_engr = ep;
119*df930be7Sderaadt 	ep->engr_x = x;
120*df930be7Sderaadt 	ep->engr_y = y;
121*df930be7Sderaadt 	ep->engr_txt = (char *)(ep + 1);
122*df930be7Sderaadt 	(void) strcpy(ep->engr_txt, s);
123*df930be7Sderaadt 	ep->engr_time = 0;
124*df930be7Sderaadt 	ep->engr_type = DUST;
125*df930be7Sderaadt 	ep->engr_lth = strlen(s) + 1;
126*df930be7Sderaadt }
127*df930be7Sderaadt 
128*df930be7Sderaadt doengrave(){
129*df930be7Sderaadt register int len;
130*df930be7Sderaadt register char *sp;
131*df930be7Sderaadt register struct engr *ep, *oep = engr_at(u.ux,u.uy);
132*df930be7Sderaadt char buf[BUFSZ];
133*df930be7Sderaadt xchar type;
134*df930be7Sderaadt int spct;		/* number of leading spaces */
135*df930be7Sderaadt register struct obj *otmp;
136*df930be7Sderaadt 	multi = 0;
137*df930be7Sderaadt 
138*df930be7Sderaadt 	if(u.uswallow) {
139*df930be7Sderaadt 		pline("You're joking. Hahaha!");	/* riv05!a3 */
140*df930be7Sderaadt 		return(0);
141*df930be7Sderaadt 	}
142*df930be7Sderaadt 
143*df930be7Sderaadt 	/* one may write with finger, weapon or wand */
144*df930be7Sderaadt 	otmp = getobj("#-)/", "write with");
145*df930be7Sderaadt 	if(!otmp) return(0);
146*df930be7Sderaadt 
147*df930be7Sderaadt 	if(otmp == &zeroobj)
148*df930be7Sderaadt 		otmp = 0;
149*df930be7Sderaadt 	if(otmp && otmp->otyp == WAN_FIRE && otmp->spe) {
150*df930be7Sderaadt 		type = BURN;
151*df930be7Sderaadt 		otmp->spe--;
152*df930be7Sderaadt 	} else {
153*df930be7Sderaadt 		/* first wield otmp */
154*df930be7Sderaadt 		if(otmp != uwep) {
155*df930be7Sderaadt 			if(uwep && uwep->cursed) {
156*df930be7Sderaadt 			    /* Andreas Bormann */
157*df930be7Sderaadt 			    pline("Since your weapon is welded to your hand,");
158*df930be7Sderaadt 			    pline("you use the %s.", aobjnam(uwep, (char *) 0));
159*df930be7Sderaadt 			    otmp = uwep;
160*df930be7Sderaadt 			} else {
161*df930be7Sderaadt 			    if(!otmp)
162*df930be7Sderaadt 				pline("You are now empty-handed.");
163*df930be7Sderaadt 			    else if(otmp->cursed)
164*df930be7Sderaadt 				pline("The %s %s to your hand!",
165*df930be7Sderaadt 				    aobjnam(otmp, "weld"),
166*df930be7Sderaadt 				    (otmp->quan == 1) ? "itself" : "themselves");
167*df930be7Sderaadt 			    else
168*df930be7Sderaadt 				pline("You now wield %s.", doname(otmp));
169*df930be7Sderaadt 			    setuwep(otmp);
170*df930be7Sderaadt 			}
171*df930be7Sderaadt 		}
172*df930be7Sderaadt 
173*df930be7Sderaadt 		if(!otmp)
174*df930be7Sderaadt 			type = DUST;
175*df930be7Sderaadt 		else
176*df930be7Sderaadt 		if(otmp->otyp == DAGGER || otmp->otyp == TWO_HANDED_SWORD ||
177*df930be7Sderaadt 		otmp->otyp == CRYSKNIFE ||
178*df930be7Sderaadt 		otmp->otyp == LONG_SWORD || otmp->otyp == AXE) {
179*df930be7Sderaadt 			type = ENGRAVE;
180*df930be7Sderaadt 			if((int)otmp->spe <= -3) {
181*df930be7Sderaadt 				type = DUST;
182*df930be7Sderaadt 				pline("Your %s too dull for engraving.",
183*df930be7Sderaadt 					aobjnam(otmp, "are"));
184*df930be7Sderaadt 				if(oep && oep->engr_type != DUST) return(1);
185*df930be7Sderaadt 			}
186*df930be7Sderaadt 		} else	type = DUST;
187*df930be7Sderaadt 	}
188*df930be7Sderaadt 	if(Levitation && type != BURN){		/* riv05!a3 */
189*df930be7Sderaadt 		pline("You can't reach the floor!");
190*df930be7Sderaadt 		return(1);
191*df930be7Sderaadt 	}
192*df930be7Sderaadt 	if(oep && oep->engr_type == DUST){
193*df930be7Sderaadt 		  pline("You wipe out the message that was written here.");
194*df930be7Sderaadt 		  del_engr(oep);
195*df930be7Sderaadt 		  oep = 0;
196*df930be7Sderaadt 	}
197*df930be7Sderaadt 	if(type == DUST && oep){
198*df930be7Sderaadt 	pline("You cannot wipe out the message that is %s in the rock.",
199*df930be7Sderaadt 		    (oep->engr_type == BURN) ? "burned" : "engraved");
200*df930be7Sderaadt 		  return(1);
201*df930be7Sderaadt 	}
202*df930be7Sderaadt 
203*df930be7Sderaadt 	pline("What do you want to %s on the floor here? ",
204*df930be7Sderaadt 	  (type == ENGRAVE) ? "engrave" : (type == BURN) ? "burn" : "write");
205*df930be7Sderaadt 	getlin(buf);
206*df930be7Sderaadt 	clrlin();
207*df930be7Sderaadt 	spct = 0;
208*df930be7Sderaadt 	sp = buf;
209*df930be7Sderaadt 	while(*sp == ' ') spct++, sp++;
210*df930be7Sderaadt 	len = strlen(sp);
211*df930be7Sderaadt 	if(!len || *buf == '\033') {
212*df930be7Sderaadt 		if(type == BURN) otmp->spe++;
213*df930be7Sderaadt 		return(0);
214*df930be7Sderaadt 	}
215*df930be7Sderaadt 
216*df930be7Sderaadt 	switch(type) {
217*df930be7Sderaadt 	case DUST:
218*df930be7Sderaadt 	case BURN:
219*df930be7Sderaadt 		if(len > 15) {
220*df930be7Sderaadt 			multi = -(len/10);
221*df930be7Sderaadt 			nomovemsg = "You finished writing.";
222*df930be7Sderaadt 		}
223*df930be7Sderaadt 		break;
224*df930be7Sderaadt 	case ENGRAVE:		/* here otmp != 0 */
225*df930be7Sderaadt 		{	int len2 = (otmp->spe + 3) * 2 + 1;
226*df930be7Sderaadt 
227*df930be7Sderaadt 			pline("Your %s dull.", aobjnam(otmp, "get"));
228*df930be7Sderaadt 			if(len2 < len) {
229*df930be7Sderaadt 				len = len2;
230*df930be7Sderaadt 				sp[len] = 0;
231*df930be7Sderaadt 				otmp->spe = -3;
232*df930be7Sderaadt 				nomovemsg = "You cannot engrave more.";
233*df930be7Sderaadt 			} else {
234*df930be7Sderaadt 				otmp->spe -= len/2;
235*df930be7Sderaadt 				nomovemsg = "You finished engraving.";
236*df930be7Sderaadt 			}
237*df930be7Sderaadt 			multi = -len;
238*df930be7Sderaadt 		}
239*df930be7Sderaadt 		break;
240*df930be7Sderaadt 	}
241*df930be7Sderaadt 	if(oep) len += strlen(oep->engr_txt) + spct;
242*df930be7Sderaadt 	ep = (struct engr *) alloc((unsigned)(sizeof(struct engr) + len + 1));
243*df930be7Sderaadt 	ep->nxt_engr = head_engr;
244*df930be7Sderaadt 	head_engr = ep;
245*df930be7Sderaadt 	ep->engr_x = u.ux;
246*df930be7Sderaadt 	ep->engr_y = u.uy;
247*df930be7Sderaadt 	sp = (char *)(ep + 1);	/* (char *)ep + sizeof(struct engr) */
248*df930be7Sderaadt 	ep->engr_txt = sp;
249*df930be7Sderaadt 	if(oep) {
250*df930be7Sderaadt 		(void) strcpy(sp, oep->engr_txt);
251*df930be7Sderaadt 		(void) strcat(sp, buf);
252*df930be7Sderaadt 		del_engr(oep);
253*df930be7Sderaadt 	} else
254*df930be7Sderaadt 		(void) strcpy(sp, buf);
255*df930be7Sderaadt 	ep->engr_lth = len+1;
256*df930be7Sderaadt 	ep->engr_type = type;
257*df930be7Sderaadt 	ep->engr_time = moves-multi;
258*df930be7Sderaadt 
259*df930be7Sderaadt 	/* kludge to protect pline against excessively long texts */
260*df930be7Sderaadt 	if(len > BUFSZ-20) sp[BUFSZ-20] = 0;
261*df930be7Sderaadt 
262*df930be7Sderaadt 	return(1);
263*df930be7Sderaadt }
264*df930be7Sderaadt 
265*df930be7Sderaadt save_engravings(fd) int fd; {
266*df930be7Sderaadt register struct engr *ep = head_engr;
267*df930be7Sderaadt 	while(ep) {
268*df930be7Sderaadt 		if(!ep->engr_lth || !ep->engr_txt[0]){
269*df930be7Sderaadt 			ep = ep->nxt_engr;
270*df930be7Sderaadt 			continue;
271*df930be7Sderaadt 		}
272*df930be7Sderaadt 		bwrite(fd, (char *) & (ep->engr_lth), sizeof(ep->engr_lth));
273*df930be7Sderaadt 		bwrite(fd, (char *) ep, sizeof(struct engr) + ep->engr_lth);
274*df930be7Sderaadt 		ep = ep->nxt_engr;
275*df930be7Sderaadt 	}
276*df930be7Sderaadt 	bwrite(fd, (char *) nul, sizeof(unsigned));
277*df930be7Sderaadt 	head_engr = 0;
278*df930be7Sderaadt }
279*df930be7Sderaadt 
280*df930be7Sderaadt rest_engravings(fd) int fd; {
281*df930be7Sderaadt register struct engr *ep;
282*df930be7Sderaadt unsigned lth;
283*df930be7Sderaadt 	head_engr = 0;
284*df930be7Sderaadt 	while(1) {
285*df930be7Sderaadt 		mread(fd, (char *) &lth, sizeof(unsigned));
286*df930be7Sderaadt 		if(lth == 0) return;
287*df930be7Sderaadt 		ep = (struct engr *) alloc(sizeof(struct engr) + lth);
288*df930be7Sderaadt 		mread(fd, (char *) ep, sizeof(struct engr) + lth);
289*df930be7Sderaadt 		ep->nxt_engr = head_engr;
290*df930be7Sderaadt 		ep->engr_txt = (char *) (ep + 1);	/* Andreas Bormann */
291*df930be7Sderaadt 		head_engr = ep;
292*df930be7Sderaadt 	}
293*df930be7Sderaadt }
294*df930be7Sderaadt 
295*df930be7Sderaadt del_engr(ep) register struct engr *ep; {
296*df930be7Sderaadt register struct engr *ept;
297*df930be7Sderaadt 	if(ep == head_engr)
298*df930be7Sderaadt 		head_engr = ep->nxt_engr;
299*df930be7Sderaadt 	else {
300*df930be7Sderaadt 		for(ept = head_engr; ept; ept = ept->nxt_engr) {
301*df930be7Sderaadt 			if(ept->nxt_engr == ep) {
302*df930be7Sderaadt 				ept->nxt_engr = ep->nxt_engr;
303*df930be7Sderaadt 				goto fnd;
304*df930be7Sderaadt 			}
305*df930be7Sderaadt 		}
306*df930be7Sderaadt 		impossible("Error in del_engr?");
307*df930be7Sderaadt 		return;
308*df930be7Sderaadt 	fnd:	;
309*df930be7Sderaadt 	}
310*df930be7Sderaadt 	free((char *) ep);
311*df930be7Sderaadt }
312