]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - games/hack/hack.engrave.c
o Fix Y2K buffer overflow.
[FreeBSD/FreeBSD.git] / games / hack / hack.engrave.c
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 *) &lth, 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 }