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