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