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