]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - hack/hack.engrave.c
PR/55693: Andreas Gustafsson: factor(6) lists factors in wrong order
[bsdgames-darwin.git] / hack / hack.engrave.c
1 /* $NetBSD: hack.engrave.c,v 1.14 2011/08/07 06:03:45 dholland Exp $ */
2
3 /*
4 * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
5 * Amsterdam
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met:
11 *
12 * - Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 *
15 * - Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * - Neither the name of the Stichting Centrum voor Wiskunde en
20 * Informatica, nor the names of its contributors may be used to endorse or
21 * promote products derived from this software without specific prior
22 * written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36
37 /*
38 * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39 * All rights reserved.
40 *
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. The name of the author may not be used to endorse or promote products
50 * derived from this software without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
55 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62 */
63
64 #include <sys/cdefs.h>
65 #ifndef lint
66 __RCSID("$NetBSD: hack.engrave.c,v 1.14 2011/08/07 06:03:45 dholland Exp $");
67 #endif /* not lint */
68
69 #include <stdlib.h>
70 #include "hack.h"
71 #include "extern.h"
72
73 struct engr {
74 struct engr *nxt_engr;
75 char *engr_txt;
76 xchar engr_x, engr_y;
77 unsigned engr_lth; /* for save & restore; not length of
78 * text */
79 long engr_time; /* moment engraving was (will be)
80 * finished */
81 xchar engr_type;
82 #define DUST 1
83 #define ENGRAVE 2
84 #define BURN 3
85 };
86
87 static struct engr *head_engr;
88
89 static void del_engr(struct engr *);
90
91 static struct engr *
92 engr_at(xchar x, xchar y)
93 {
94 struct engr *ep = head_engr;
95 while (ep) {
96 if (x == ep->engr_x && y == ep->engr_y)
97 return (ep);
98 ep = ep->nxt_engr;
99 }
100 return ((struct engr *) 0);
101 }
102
103 int
104 sengr_at(const char *s, xchar x, xchar y)
105 {
106 struct engr *ep = engr_at(x, y);
107 char *t;
108 size_t n;
109
110 if (ep && ep->engr_time <= moves) {
111 t = ep->engr_txt;
112 /*
113 if(!strcmp(s,t)) return(1);
114 */
115 n = strlen(s);
116 while (*t) {
117 if (!strncmp(s, t, n))
118 return (1);
119 t++;
120 }
121 }
122 return (0);
123 }
124
125 void
126 u_wipe_engr(int cnt)
127 {
128 if (!u.uswallow && !Levitation)
129 wipe_engr_at(u.ux, u.uy, cnt);
130 }
131
132 void
133 wipe_engr_at(xchar x, xchar y, xchar cnt)
134 {
135 struct engr *ep = engr_at(x, y);
136 int pos;
137 char ch;
138 size_t lth;
139
140 if (ep) {
141 if ((ep->engr_type != DUST) || Levitation) {
142 cnt = rn2(1 + 50 / (cnt + 1)) ? 0 : 1;
143 }
144 lth = strlen(ep->engr_txt);
145 if (lth && cnt > 0) {
146 while (cnt--) {
147 pos = rn2(lth);
148 if ((ch = ep->engr_txt[pos]) == ' ')
149 continue;
150 ep->engr_txt[pos] = (ch != '?') ? '?' : ' ';
151 }
152 }
153 while (lth && ep->engr_txt[lth - 1] == ' ')
154 ep->engr_txt[--lth] = 0;
155 while (ep->engr_txt[0] == ' ')
156 ep->engr_txt++;
157 if (!ep->engr_txt[0])
158 del_engr(ep);
159 }
160 }
161
162 void
163 read_engr_at(int x, int y)
164 {
165 struct engr *ep = engr_at(x, y);
166 if (ep && ep->engr_txt[0]) {
167 switch (ep->engr_type) {
168 case DUST:
169 pline("Something is written here in the dust.");
170 break;
171 case ENGRAVE:
172 pline("Something is engraved here on the floor.");
173 break;
174 case BURN:
175 pline("Some text has been burned here in the floor.");
176 break;
177 default:
178 impossible("Something is written in a very strange way.");
179 }
180 pline("You read: \"%s\".", ep->engr_txt);
181 }
182 }
183
184 void
185 make_engr_at(int x, int y, const char *s)
186 {
187 struct engr *ep;
188
189 if ((ep = engr_at(x, y)) != NULL)
190 del_engr(ep);
191 ep = alloc(sizeof(*ep) + strlen(s) + 1);
192
193 ep->nxt_engr = head_engr;
194 head_engr = ep;
195 ep->engr_x = x;
196 ep->engr_y = y;
197 ep->engr_txt = (char *) (ep + 1);
198 (void) strcpy(ep->engr_txt, s);
199 ep->engr_time = 0;
200 ep->engr_type = DUST;
201 ep->engr_lth = strlen(s) + 1;
202 }
203
204 int
205 doengrave(void)
206 {
207 int len;
208 char *sp;
209 struct engr *ep, *oep = engr_at(u.ux, u.uy);
210 char buf[BUFSZ];
211 xchar type;
212 int spct; /* number of leading spaces */
213 struct obj *otmp;
214 multi = 0;
215
216 if (u.uswallow) {
217 pline("You're joking. Hahaha!"); /* riv05!a3 */
218 return (0);
219 }
220 /* one may write with finger, weapon or wand */
221 otmp = getobj("#-)/", "write with");
222 if (!otmp)
223 return (0);
224
225 if (otmp == &zeroobj)
226 otmp = 0;
227 if (otmp && otmp->otyp == WAN_FIRE && otmp->spe) {
228 type = BURN;
229 otmp->spe--;
230 } else {
231 /* first wield otmp */
232 if (otmp != uwep) {
233 if (uwep && uwep->cursed) {
234 /* Andreas Bormann */
235 pline("Since your weapon is welded to your hand,");
236 pline("you use the %s.", aobjnam(uwep, NULL));
237 otmp = uwep;
238 } else {
239 if (!otmp)
240 pline("You are now empty-handed.");
241 else if (otmp->cursed)
242 pline("The %s %s to your hand!",
243 aobjnam(otmp, "weld"),
244 (otmp->quan == 1) ? "itself" : "themselves");
245 else
246 pline("You now wield %s.", doname(otmp));
247 setuwep(otmp);
248 }
249 }
250 if (!otmp)
251 type = DUST;
252 else if (otmp->otyp == DAGGER || otmp->otyp == TWO_HANDED_SWORD ||
253 otmp->otyp == CRYSKNIFE ||
254 otmp->otyp == LONG_SWORD || otmp->otyp == AXE) {
255 type = ENGRAVE;
256 if ((int) otmp->spe <= -3) {
257 type = DUST;
258 pline("Your %s too dull for engraving.",
259 aobjnam(otmp, "are"));
260 if (oep && oep->engr_type != DUST)
261 return (1);
262 }
263 } else
264 type = DUST;
265 }
266 if (Levitation && type != BURN) { /* riv05!a3 */
267 pline("You can't reach the floor!");
268 return (1);
269 }
270 if (oep && oep->engr_type == DUST) {
271 pline("You wipe out the message that was written here.");
272 del_engr(oep);
273 oep = 0;
274 }
275 if (type == DUST && oep) {
276 pline("You cannot wipe out the message that is %s in the rock.",
277 (oep->engr_type == BURN) ? "burned" : "engraved");
278 return (1);
279 }
280 pline("What do you want to %s on the floor here? ",
281 (type == ENGRAVE) ? "engrave" : (type == BURN) ? "burn" : "write");
282 getlin(buf);
283 clrlin();
284 spct = 0;
285 sp = buf;
286 while (*sp == ' ')
287 spct++, sp++;
288 len = strlen(sp);
289 if (!len || *buf == '\033') {
290 if (type == BURN)
291 otmp->spe++;
292 return (0);
293 }
294 switch (type) {
295 case DUST:
296 case BURN:
297 if (len > 15) {
298 multi = -(len / 10);
299 nomovemsg = "You finished writing.";
300 }
301 break;
302 case ENGRAVE: /* here otmp != 0 */
303 {
304 int len2 = (otmp->spe + 3) * 2 + 1;
305
306 pline("Your %s dull.", aobjnam(otmp, "get"));
307 if (len2 < len) {
308 len = len2;
309 sp[len] = 0;
310 otmp->spe = -3;
311 nomovemsg = "You cannot engrave more.";
312 } else {
313 otmp->spe -= len / 2;
314 nomovemsg = "You finished engraving.";
315 }
316 multi = -len;
317 }
318 break;
319 }
320 if (oep)
321 len += strlen(oep->engr_txt) + spct;
322 ep = alloc(sizeof(*ep) + len + 1);
323 ep->nxt_engr = head_engr;
324 head_engr = ep;
325 ep->engr_x = u.ux;
326 ep->engr_y = u.uy;
327 sp = (char *) (ep + 1); /* (char *)ep + sizeof(struct engr) */
328 ep->engr_txt = sp;
329 if (oep) {
330 (void) strcpy(sp, oep->engr_txt);
331 (void) strcat(sp, buf);
332 del_engr(oep);
333 } else
334 (void) strcpy(sp, buf);
335 ep->engr_lth = len + 1;
336 ep->engr_type = type;
337 ep->engr_time = moves - multi;
338
339 /* kludge to protect pline against excessively long texts */
340 if (len > BUFSZ - 20)
341 sp[BUFSZ - 20] = 0;
342
343 return (1);
344 }
345
346 void
347 save_engravings(int fd)
348 {
349 struct engr *ep = head_engr;
350 while (ep) {
351 if (!ep->engr_lth || !ep->engr_txt[0]) {
352 ep = ep->nxt_engr;
353 continue;
354 }
355 bwrite(fd, &(ep->engr_lth), sizeof(ep->engr_lth));
356 bwrite(fd, ep, sizeof(struct engr) + ep->engr_lth);
357 ep = ep->nxt_engr;
358 }
359 bwrite(fd, nul, sizeof(unsigned));
360 head_engr = 0;
361 }
362
363 void
364 rest_engravings(int fd)
365 {
366 struct engr *ep;
367 unsigned lth;
368 head_engr = 0;
369 while (1) {
370 mread(fd, &lth, sizeof(unsigned));
371 if (lth == 0)
372 return;
373 ep = alloc(sizeof(*ep) + lth);
374 mread(fd, ep, sizeof(*ep) + lth);
375 ep->nxt_engr = head_engr;
376 ep->engr_txt = (char *) (ep + 1); /* Andreas Bormann */
377 head_engr = ep;
378 }
379 }
380
381 static void
382 del_engr(struct engr *ep)
383 {
384 struct engr *ept;
385 if (ep == head_engr)
386 head_engr = ep->nxt_engr;
387 else {
388 for (ept = head_engr; ept; ept = ept->nxt_engr) {
389 if (ept->nxt_engr == ep) {
390 ept->nxt_engr = ep->nxt_engr;
391 goto fnd;
392 }
393 }
394 impossible("Error in del_engr?");
395 return;
396 fnd: ;
397 }
398 free(ep);
399 }