1 /* $OpenBSD: hack.engrave.c,v 1.9 2016/01/09 21:54:11 mestre Exp $ */ 2 3 /* 4 * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica, 5 * Amsterdam 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions are 10 * met: 11 * 12 * - Redistributions of source code must retain the above copyright notice, 13 * this list of conditions and the following disclaimer. 14 * 15 * - Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * - Neither the name of the Stichting Centrum voor Wiskunde en 20 * Informatica, nor the names of its contributors may be used to endorse or 21 * promote products derived from this software without specific prior 22 * written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 25 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 27 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 28 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 30 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 31 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37 /* 38 * Copyright (c) 1982 Jay Fenlason <hack@gnu.org> 39 * All rights reserved. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 3. The name of the author may not be used to endorse or promote products 50 * derived from this software without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 53 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 54 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 55 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 56 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 57 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 58 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 59 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 60 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 61 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 62 */ 63 64 #include <stdlib.h> 65 66 #include "hack.h" 67 68 extern char *nomovemsg; 69 extern char nul[]; 70 extern struct obj zeroobj; 71 struct engr { 72 struct engr *nxt_engr; 73 char *engr_txt; 74 xchar engr_x, engr_y; 75 unsigned engr_lth; /* for save & restore; not length of text */ 76 long engr_time; /* moment engraving was (will be) finished */ 77 xchar engr_type; 78 #define DUST 1 79 #define ENGRAVE 2 80 #define BURN 3 81 } *head_engr; 82 83 static void del_engr(struct engr *); 84 85 struct engr * 86 engr_at(xchar x, xchar y) 87 { 88 struct engr *ep = head_engr; 89 90 while(ep) { 91 if(x == ep->engr_x && y == ep->engr_y) 92 return(ep); 93 ep = ep->nxt_engr; 94 } 95 return((struct engr *) 0); 96 } 97 98 int 99 sengr_at(char *s, xchar x, xchar y) 100 { 101 struct engr *ep = engr_at(x,y); 102 char *t; 103 int n; 104 105 if(ep && ep->engr_time <= moves) { 106 t = ep->engr_txt; 107 /* 108 if(!strcmp(s,t)) return(1); 109 */ 110 n = strlen(s); 111 while(*t) { 112 if(!strncmp(s,t,n)) return(1); 113 t++; 114 } 115 } 116 return(0); 117 } 118 119 void 120 u_wipe_engr(int cnt) 121 { 122 if(!u.uswallow && !Levitation) 123 wipe_engr_at(u.ux, u.uy, cnt); 124 } 125 126 void 127 wipe_engr_at(xchar x, xchar y, xchar cnt) 128 { 129 struct engr *ep = engr_at(x,y); 130 int lth,pos; 131 char ch; 132 133 if(ep){ 134 if((ep->engr_type != DUST) || Levitation) { 135 cnt = rn2(1 + 50/(cnt+1)) ? 0 : 1; 136 } 137 lth = strlen(ep->engr_txt); 138 if(lth && cnt > 0 ) { 139 while(cnt--) { 140 pos = rn2(lth); 141 if((ch = ep->engr_txt[pos]) == ' ') 142 continue; 143 ep->engr_txt[pos] = (ch != '?') ? '?' : ' '; 144 } 145 } 146 while(lth && ep->engr_txt[lth-1] == ' ') 147 ep->engr_txt[--lth] = 0; 148 while(ep->engr_txt[0] == ' ') 149 ep->engr_txt++; 150 if(!ep->engr_txt[0]) del_engr(ep); 151 } 152 } 153 154 void 155 read_engr_at(int x, int y) 156 { 157 struct engr *ep = engr_at(x,y); 158 159 if(ep && ep->engr_txt[0]) { 160 switch(ep->engr_type) { 161 case DUST: 162 pline("Something is written here in the dust."); 163 break; 164 case ENGRAVE: 165 pline("Something is engraved here on the floor."); 166 break; 167 case BURN: 168 pline("Some text has been burned here in the floor."); 169 break; 170 default: 171 impossible("Something is written in a very strange way."); 172 } 173 pline("You read: \"%s\".", ep->engr_txt); 174 } 175 } 176 177 void 178 make_engr_at(int x, int y, char *s) 179 { 180 struct engr *ep; 181 size_t len = strlen(s) + 1; 182 183 if ((ep = engr_at(x,y))) 184 del_engr(ep); 185 ep = (struct engr *) 186 alloc((unsigned)(sizeof(struct engr) + len)); 187 ep->nxt_engr = head_engr; 188 head_engr = ep; 189 ep->engr_x = x; 190 ep->engr_y = y; 191 ep->engr_txt = (char *)(ep + 1); 192 (void) strlcpy(ep->engr_txt, s, len); 193 ep->engr_time = 0; 194 ep->engr_type = DUST; 195 ep->engr_lth = len; 196 } 197 198 int 199 doengrave(void) 200 { 201 int len; 202 char *sp; 203 struct engr *ep, *oep = engr_at(u.ux,u.uy); 204 char buf[BUFSZ]; 205 xchar type; 206 int spct; /* number of leading spaces */ 207 struct obj *otmp; 208 209 multi = 0; 210 211 if(u.uswallow) { 212 pline("You're joking. Hahaha!"); /* riv05!a3 */ 213 return(0); 214 } 215 216 /* one may write with finger, weapon or wand */ 217 otmp = getobj("#-)/", "write with"); 218 if(!otmp) return(0); 219 220 if(otmp == &zeroobj) 221 otmp = 0; 222 if(otmp && otmp->otyp == WAN_FIRE && otmp->spe) { 223 type = BURN; 224 otmp->spe--; 225 } else { 226 /* first wield otmp */ 227 if(otmp != uwep) { 228 if(uwep && uwep->cursed) { 229 /* Andreas Bormann */ 230 pline("Since your weapon is welded to your hand,"); 231 pline("you use the %s.", aobjnam(uwep, NULL)); 232 otmp = uwep; 233 } else { 234 if(!otmp) 235 pline("You are now empty-handed."); 236 else if(otmp->cursed) 237 pline("The %s %s to your hand!", 238 aobjnam(otmp, "weld"), 239 (otmp->quan == 1) ? "itself" : "themselves"); 240 else 241 pline("You now wield %s.", doname(otmp)); 242 setuwep(otmp); 243 } 244 } 245 246 if(!otmp) 247 type = DUST; 248 else 249 if(otmp->otyp == DAGGER || otmp->otyp == TWO_HANDED_SWORD || 250 otmp->otyp == CRYSKNIFE || 251 otmp->otyp == LONG_SWORD || otmp->otyp == AXE) { 252 type = ENGRAVE; 253 if((int)otmp->spe <= -3) { 254 type = DUST; 255 pline("Your %s too dull for engraving.", 256 aobjnam(otmp, "are")); 257 if(oep && oep->engr_type != DUST) return(1); 258 } 259 } else type = DUST; 260 } 261 if(Levitation && type != BURN){ /* riv05!a3 */ 262 pline("You can't reach the floor!"); 263 return(1); 264 } 265 if(oep && oep->engr_type == DUST){ 266 pline("You wipe out the message that was written here."); 267 del_engr(oep); 268 oep = 0; 269 } 270 if(type == DUST && oep){ 271 pline("You cannot wipe out the message that is %s in the rock.", 272 (oep->engr_type == BURN) ? "burned" : "engraved"); 273 return(1); 274 } 275 276 pline("What do you want to %s on the floor here? ", 277 (type == ENGRAVE) ? "engrave" : (type == BURN) ? "burn" : "write"); 278 getlin(buf); 279 clrlin(); 280 spct = 0; 281 sp = buf; 282 while(*sp == ' ') spct++, sp++; 283 len = strlen(sp); 284 if(!len || *buf == '\033') { 285 if(type == BURN) otmp->spe++; 286 return(0); 287 } 288 289 switch(type) { 290 case DUST: 291 case BURN: 292 if(len > 15) { 293 multi = -(len/10); 294 nomovemsg = "You finished writing."; 295 } 296 break; 297 case ENGRAVE: /* here otmp != 0 */ 298 { int len2 = (otmp->spe + 3) * 2 + 1; 299 300 pline("Your %s dull.", aobjnam(otmp, "get")); 301 if(len2 < len) { 302 len = len2; 303 sp[len] = 0; 304 otmp->spe = -3; 305 nomovemsg = "You cannot engrave more."; 306 } else { 307 otmp->spe -= len/2; 308 nomovemsg = "You finished engraving."; 309 } 310 multi = -len; 311 } 312 break; 313 } 314 if(oep) len += strlen(oep->engr_txt) + spct; 315 ep = (struct engr *) alloc((unsigned)(sizeof(struct engr) + len + 1)); 316 ep->nxt_engr = head_engr; 317 head_engr = ep; 318 ep->engr_x = u.ux; 319 ep->engr_y = u.uy; 320 sp = (char *)(ep + 1); /* (char *)ep + sizeof(struct engr) */ 321 ep->engr_txt = sp; 322 if(oep) { 323 (void) strlcpy(sp, oep->engr_txt, len + 1); 324 (void) strlcat(sp, buf, len + 1); 325 del_engr(oep); 326 } else 327 (void) strlcpy(sp, buf, len + 1); 328 ep->engr_lth = len+1; 329 ep->engr_type = type; 330 ep->engr_time = moves-multi; 331 332 /* kludge to protect pline against excessively long texts */ 333 if(len > BUFSZ-20) sp[BUFSZ-20] = 0; 334 335 return(1); 336 } 337 338 void 339 save_engravings(int fd) 340 { 341 struct engr *ep = head_engr; 342 343 while(ep) { 344 if(!ep->engr_lth || !ep->engr_txt[0]){ 345 ep = ep->nxt_engr; 346 continue; 347 } 348 bwrite(fd, &(ep->engr_lth), sizeof(ep->engr_lth)); 349 bwrite(fd, ep, sizeof(struct engr) + ep->engr_lth); 350 ep = ep->nxt_engr; 351 } 352 bwrite(fd, nul, sizeof(unsigned)); 353 head_engr = 0; 354 } 355 356 void 357 rest_engravings(int fd) 358 { 359 struct engr *ep; 360 unsigned lth; 361 362 head_engr = 0; 363 while(1) { 364 mread(fd, (char *) <h, sizeof(unsigned)); 365 if(lth == 0) return; 366 ep = (struct engr *) alloc(sizeof(struct engr) + lth); 367 mread(fd, (char *) ep, sizeof(struct engr) + lth); 368 ep->nxt_engr = head_engr; 369 ep->engr_txt = (char *) (ep + 1); /* Andreas Bormann */ 370 head_engr = ep; 371 } 372 } 373 374 static void 375 del_engr(struct engr *ep) 376 { 377 struct engr *ept; 378 379 if(ep == head_engr) 380 head_engr = ep->nxt_engr; 381 else { 382 for(ept = head_engr; ept; ept = ept->nxt_engr) { 383 if(ept->nxt_engr == ep) { 384 ept->nxt_engr = ep->nxt_engr; 385 goto fnd; 386 } 387 } 388 impossible("Error in del_engr?"); 389 return; 390 fnd: ; 391 } 392 free(ep); 393 } 394