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