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