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) { 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 = (char *)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: }