1 /* $NetBSD: hack.engrave.c,v 1.9 2009/08/12 07:28:40 dholland 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 <sys/cdefs.h> 65 #ifndef lint 66 __RCSID("$NetBSD: hack.engrave.c,v 1.9 2009/08/12 07:28:40 dholland Exp $"); 67 #endif /* not lint */ 68 69 #include <stdlib.h> 70 #include "hack.h" 71 #include "extern.h" 72 73 struct engr { 74 struct engr *nxt_engr; 75 char *engr_txt; 76 xchar engr_x, engr_y; 77 unsigned engr_lth; /* for save & restore; not length of 78 * text */ 79 long engr_time; /* moment engraving was (will be) 80 * finished */ 81 xchar engr_type; 82 #define DUST 1 83 #define ENGRAVE 2 84 #define BURN 3 85 }; 86 87 static struct engr *head_engr; 88 89 static void del_engr(struct engr *); 90 91 static struct engr * 92 engr_at(xchar x, xchar y) 93 { 94 struct engr *ep = head_engr; 95 while (ep) { 96 if (x == ep->engr_x && y == ep->engr_y) 97 return (ep); 98 ep = ep->nxt_engr; 99 } 100 return ((struct engr *) 0); 101 } 102 103 int 104 sengr_at(const char *s, xchar x, xchar y) 105 { 106 struct engr *ep = engr_at(x, y); 107 char *t; 108 int n; 109 if (ep && ep->engr_time <= moves) { 110 t = ep->engr_txt; 111 /* 112 if(!strcmp(s,t)) return(1); 113 */ 114 n = strlen(s); 115 while (*t) { 116 if (!strncmp(s, t, n)) 117 return (1); 118 t++; 119 } 120 } 121 return (0); 122 } 123 124 void 125 u_wipe_engr(int cnt) 126 { 127 if (!u.uswallow && !Levitation) 128 wipe_engr_at(u.ux, u.uy, cnt); 129 } 130 131 void 132 wipe_engr_at(xchar x, xchar y, xchar cnt) 133 { 134 struct engr *ep = engr_at(x, y); 135 int lth, pos; 136 char ch; 137 if (ep) { 138 if ((ep->engr_type != DUST) || Levitation) { 139 cnt = rn2(1 + 50 / (cnt + 1)) ? 0 : 1; 140 } 141 lth = strlen(ep->engr_txt); 142 if (lth && cnt > 0) { 143 while (cnt--) { 144 pos = rn2(lth); 145 if ((ch = ep->engr_txt[pos]) == ' ') 146 continue; 147 ep->engr_txt[pos] = (ch != '?') ? '?' : ' '; 148 } 149 } 150 while (lth && ep->engr_txt[lth - 1] == ' ') 151 ep->engr_txt[--lth] = 0; 152 while (ep->engr_txt[0] == ' ') 153 ep->engr_txt++; 154 if (!ep->engr_txt[0]) 155 del_engr(ep); 156 } 157 } 158 159 void 160 read_engr_at(int x, int y) 161 { 162 struct engr *ep = engr_at(x, y); 163 if (ep && ep->engr_txt[0]) { 164 switch (ep->engr_type) { 165 case DUST: 166 pline("Something is written here in the dust."); 167 break; 168 case ENGRAVE: 169 pline("Something is engraved here on the floor."); 170 break; 171 case BURN: 172 pline("Some text has been burned here in the floor."); 173 break; 174 default: 175 impossible("Something is written in a very strange way."); 176 } 177 pline("You read: \"%s\".", ep->engr_txt); 178 } 179 } 180 181 void 182 make_engr_at(int x, int y, const char *s) 183 { 184 struct engr *ep; 185 186 if ((ep = engr_at(x, y)) != NULL) 187 del_engr(ep); 188 ep = (struct engr *) 189 alloc((unsigned) (sizeof(struct engr) + strlen(s) + 1)); 190 ep->nxt_engr = head_engr; 191 head_engr = ep; 192 ep->engr_x = x; 193 ep->engr_y = y; 194 ep->engr_txt = (char *) (ep + 1); 195 (void) strcpy(ep->engr_txt, s); 196 ep->engr_time = 0; 197 ep->engr_type = DUST; 198 ep->engr_lth = strlen(s) + 1; 199 } 200 201 int 202 doengrave(void) 203 { 204 int len; 205 char *sp; 206 struct engr *ep, *oep = engr_at(u.ux, u.uy); 207 char buf[BUFSZ]; 208 xchar type; 209 int spct; /* number of leading spaces */ 210 struct obj *otmp; 211 multi = 0; 212 213 if (u.uswallow) { 214 pline("You're joking. Hahaha!"); /* riv05!a3 */ 215 return (0); 216 } 217 /* one may write with finger, weapon or wand */ 218 otmp = getobj("#-)/", "write with"); 219 if (!otmp) 220 return (0); 221 222 if (otmp == &zeroobj) 223 otmp = 0; 224 if (otmp && otmp->otyp == WAN_FIRE && otmp->spe) { 225 type = BURN; 226 otmp->spe--; 227 } else { 228 /* first wield otmp */ 229 if (otmp != uwep) { 230 if (uwep && uwep->cursed) { 231 /* Andreas Bormann */ 232 pline("Since your weapon is welded to your hand,"); 233 pline("you use the %s.", aobjnam(uwep, (char *) 0)); 234 otmp = uwep; 235 } else { 236 if (!otmp) 237 pline("You are now empty-handed."); 238 else if (otmp->cursed) 239 pline("The %s %s to your hand!", 240 aobjnam(otmp, "weld"), 241 (otmp->quan == 1) ? "itself" : "themselves"); 242 else 243 pline("You now wield %s.", doname(otmp)); 244 setuwep(otmp); 245 } 246 } 247 if (!otmp) 248 type = DUST; 249 else 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) 258 return (1); 259 } 260 } else 261 type = DUST; 262 } 263 if (Levitation && type != BURN) { /* riv05!a3 */ 264 pline("You can't reach the floor!"); 265 return (1); 266 } 267 if (oep && oep->engr_type == DUST) { 268 pline("You wipe out the message that was written here."); 269 del_engr(oep); 270 oep = 0; 271 } 272 if (type == DUST && oep) { 273 pline("You cannot wipe out the message that is %s in the rock.", 274 (oep->engr_type == BURN) ? "burned" : "engraved"); 275 return (1); 276 } 277 pline("What do you want to %s on the floor here? ", 278 (type == ENGRAVE) ? "engrave" : (type == BURN) ? "burn" : "write"); 279 getlin(buf); 280 clrlin(); 281 spct = 0; 282 sp = buf; 283 while (*sp == ' ') 284 spct++, sp++; 285 len = strlen(sp); 286 if (!len || *buf == '\033') { 287 if (type == BURN) 288 otmp->spe++; 289 return (0); 290 } 291 switch (type) { 292 case DUST: 293 case BURN: 294 if (len > 15) { 295 multi = -(len / 10); 296 nomovemsg = "You finished writing."; 297 } 298 break; 299 case ENGRAVE: /* here otmp != 0 */ 300 { 301 int len2 = (otmp->spe + 3) * 2 + 1; 302 303 pline("Your %s dull.", aobjnam(otmp, "get")); 304 if (len2 < len) { 305 len = len2; 306 sp[len] = 0; 307 otmp->spe = -3; 308 nomovemsg = "You cannot engrave more."; 309 } else { 310 otmp->spe -= len / 2; 311 nomovemsg = "You finished engraving."; 312 } 313 multi = -len; 314 } 315 break; 316 } 317 if (oep) 318 len += strlen(oep->engr_txt) + spct; 319 ep = (struct engr *) alloc((unsigned) (sizeof(struct engr) + len + 1)); 320 ep->nxt_engr = head_engr; 321 head_engr = ep; 322 ep->engr_x = u.ux; 323 ep->engr_y = u.uy; 324 sp = (char *) (ep + 1); /* (char *)ep + sizeof(struct engr) */ 325 ep->engr_txt = sp; 326 if (oep) { 327 (void) strcpy(sp, oep->engr_txt); 328 (void) strcat(sp, buf); 329 del_engr(oep); 330 } else 331 (void) strcpy(sp, buf); 332 ep->engr_lth = len + 1; 333 ep->engr_type = type; 334 ep->engr_time = moves - multi; 335 336 /* kludge to protect pline against excessively long texts */ 337 if (len > BUFSZ - 20) 338 sp[BUFSZ - 20] = 0; 339 340 return (1); 341 } 342 343 void 344 save_engravings(int fd) 345 { 346 struct engr *ep = head_engr; 347 while (ep) { 348 if (!ep->engr_lth || !ep->engr_txt[0]) { 349 ep = ep->nxt_engr; 350 continue; 351 } 352 bwrite(fd, &(ep->engr_lth), sizeof(ep->engr_lth)); 353 bwrite(fd, ep, sizeof(struct engr) + ep->engr_lth); 354 ep = ep->nxt_engr; 355 } 356 bwrite(fd, nul, sizeof(unsigned)); 357 head_engr = 0; 358 } 359 360 void 361 rest_engravings(int fd) 362 { 363 struct engr *ep; 364 unsigned lth; 365 head_engr = 0; 366 while (1) { 367 mread(fd, (char *) <h, sizeof(unsigned)); 368 if (lth == 0) 369 return; 370 ep = (struct engr *) alloc(sizeof(struct engr) + lth); 371 mread(fd, (char *) ep, sizeof(struct engr) + lth); 372 ep->nxt_engr = head_engr; 373 ep->engr_txt = (char *) (ep + 1); /* Andreas Bormann */ 374 head_engr = ep; 375 } 376 } 377 378 static void 379 del_engr(struct engr *ep) 380 { 381 struct engr *ept; 382 if (ep == head_engr) 383 head_engr = ep->nxt_engr; 384 else { 385 for (ept = head_engr; ept; ept = ept->nxt_engr) { 386 if (ept->nxt_engr == ep) { 387 ept->nxt_engr = ep->nxt_engr; 388 goto fnd; 389 } 390 } 391 impossible("Error in del_engr?"); 392 return; 393 fnd: ; 394 } 395 free((char *) ep); 396 } 397