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