sys/vfs/hammer: Fix and add comments on btree boundaries
[dragonfly.git] / games / hack / hack.engrave.c
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
5 #include "hack.h"
6
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 static struct engr *engr_at(xchar, xchar);
22 static void del_engr(struct engr *);
23
24 static struct engr *
25 engr_at(xchar x, xchar y)
26 {
27         struct engr *ep = head_engr;
28
29         while (ep) {
30                 if (x == ep->engr_x && y == ep->engr_y)
31                         return(ep);
32                 ep = ep->nxt_engr;
33         }
34         return (NULL);
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
44         if (ep && ep->engr_time <= moves) {
45                 t = ep->engr_txt;
46                 n = strlen(s);
47                 while (*t) {
48                         if (!strncmp(s, t, n))
49                                 return (1);
50                         t++;
51                 }
52         }
53         return (0);
54 }
55
56 void
57 u_wipe_engr(int cnt)
58 {
59         if (!u.uswallow && !Levitation)
60                 wipe_engr_at(u.ux, u.uy, cnt);
61 }
62
63 void
64 wipe_engr_at(xchar x, xchar y, xchar cnt)
65 {
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;
73                 lth = strlen(ep->engr_txt);
74                 if (lth && cnt > 0) {
75                         while (cnt--) {
76                                 pos = rn2(lth);
77                                 if ((ch = ep->engr_txt[pos]) == ' ')
78                                         continue;
79                                 ep->engr_txt[pos] = (ch != '?') ? '?' : ' ';
80                         }
81                 }
82                 while (lth && ep->engr_txt[lth - 1] == ' ')
83                         ep->engr_txt[--lth] = 0;
84                 while (ep->engr_txt[0] == ' ')
85                         ep->engr_txt++;
86                 if (!ep->engr_txt[0])
87                         del_engr(ep);
88         }
89 }
90
91 void
92 read_engr_at(int x, int y)
93 {
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);
111         }
112 }
113
114 void
115 make_engr_at(int x, int y, const char *s)
116 {
117         struct engr *ep;
118
119         if ((ep = engr_at(x, y)))
120                 del_engr(ep);
121         ep = alloc((unsigned)(sizeof(struct engr) + strlen(s) + 1));
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);
127         strcpy(ep->engr_txt, s);
128         ep->engr_time = 0;
129         ep->engr_type = DUST;
130         ep->engr_lth = strlen(s) + 1;
131 }
132
133 int
134 doengrave(void)
135 {
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;
143
144         multi = 0;
145         if (u.uswallow) {
146                 pline("You're joking. Hahaha!");        /* riv05!a3 */
147                 return (0);
148         }
149
150         /* one may write with finger, weapon or wand */
151         otmp = getobj("#-)/", "write with");
152         if (!otmp)
153                 return (0);
154
155         if (otmp == &zeroobj)
156                 otmp = NULL;
157         if (otmp && otmp->otyp == WAN_FIRE && otmp->spe) {
158                 type = BURN;
159                 otmp->spe--;
160         } else {
161                 /* first wield otmp */
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;
168                         } else {
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);
178                         }
179                 }
180
181                 if (!otmp)
182                         type = DUST;
183                 else if (otmp->otyp == DAGGER || otmp->otyp == TWO_HANDED_SWORD ||
184                     otmp->otyp == CRYSKNIFE ||
185                     otmp->otyp == LONG_SWORD || otmp->otyp == AXE) {
186                         type = ENGRAVE;
187                         if ((int)otmp->spe <= -3) {
188                                 type = DUST;
189                                 pline("Your %s too dull for engraving.",
190                                       aobjnam(otmp, "are"));
191                                 if (oep && oep->engr_type != DUST)
192                                         return (1);
193                         }
194                 } else
195                         type = DUST;
196         }
197         if (Levitation && type != BURN) {       /* riv05!a3 */
198                 pline("You can't reach the floor!");
199                 return (1);
200         }
201         if (oep && oep->engr_type == DUST) {
202                 pline("You wipe out the message that was written here.");
203                 del_engr(oep);
204                 oep = NULL;
205         }
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);
210         }
211
212         pline("What do you want to %s on the floor here? ",
213               (type == ENGRAVE) ? "engrave" : (type == BURN) ? "burn" : "write");
214         getlin(buf);
215         clrlin();
216         spct = 0;
217         sp = buf;
218         while (*sp == ' ') {
219                 spct++;
220                 sp++;
221         }
222         len = strlen(sp);
223         if (!len || *buf == '\033') {
224                 if (type == BURN)
225                         otmp->spe++;
226                 return (0);
227         }
228
229         switch (type) {
230         case DUST:
231         case BURN:
232                 if (len > 15) {
233                         multi = -(len / 10);
234                         nomovemsg = "You finished writing.";
235                 }
236                 break;
237         case ENGRAVE:           /* here otmp != 0 */
238                 {
239                         int len2 = (otmp->spe + 3) * 2 + 1;
240
241                         pline("Your %s dull.", aobjnam(otmp, "get"));
242                         if (len2 < len) {
243                                 len = len2;
244                                 sp[len] = 0;
245                                 otmp->spe = -3;
246                                 nomovemsg = "You cannot engrave more.";
247                         } else {
248                                 otmp->spe -= len / 2;
249                                 nomovemsg = "You finished engraving.";
250                         }
251                         multi = -len;
252                 }
253                 break;
254         }
255         if (oep)
256                 len += strlen(oep->engr_txt) + spct;
257         ep = alloc((unsigned)(sizeof(struct engr) + len + 1));
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;
264         if (oep) {
265                 strcpy(sp, oep->engr_txt);
266                 strcat(sp, buf);
267                 del_engr(oep);
268         } else
269                 strcpy(sp, buf);
270         ep->engr_lth = len + 1;
271         ep->engr_type = type;
272         ep->engr_time = moves - multi;
273
274         /* kludge to protect pline against excessively long texts */
275         if (len > BUFSZ - 20)
276                 sp[BUFSZ - 20] = 0;
277
278         return (1);
279 }
280
281 void
282 save_engravings(int fd)
283 {
284         struct engr *ep = head_engr;
285
286         while (ep) {
287                 if (!ep->engr_lth || !ep->engr_txt[0]) {
288                         ep = ep->nxt_engr;
289                         continue;
290                 }
291                 bwrite(fd, (char *)&(ep->engr_lth), sizeof(ep->engr_lth));
292                 bwrite(fd, (char *)ep, sizeof(struct engr) + ep->engr_lth);
293                 ep = ep->nxt_engr;
294         }
295         bwrite(fd, (char *)nul, sizeof(unsigned));
296         head_engr = NULL;
297 }
298
299 void
300 rest_engravings(int fd)
301 {
302         struct engr *ep;
303         unsigned lth;
304
305         head_engr = NULL;
306         for (;;) {
307                 mread(fd, (char *)&lth, sizeof(unsigned));
308                 if (lth == 0)
309                         return;
310                 ep = alloc(sizeof(struct engr) + lth);
311                 mread(fd, (char *)ep, sizeof(struct engr) + lth);
312                 ep->nxt_engr = head_engr;
313                 ep->engr_txt = (char *)(ep + 1);        /* Andreas Bormann */
314                 head_engr = ep;
315         }
316 }
317
318 static void
319 del_engr(struct engr *ep)
320 {
321         struct engr *ept;
322
323         if (ep == head_engr)
324                 head_engr = ep->nxt_engr;
325         else {
326                 for (ept = head_engr; ept; ept = ept->nxt_engr) {
327                         if (ept->nxt_engr == ep) {
328                                 ept->nxt_engr = ep->nxt_engr;
329                                 goto fnd;
330                         }
331                 }
332                 impossible("Error in del_engr?");
333                 return;
334         }
335 fnd:
336         free(ep);
337 }