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