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 *) <h, 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 } 307