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