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