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