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