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