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