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