1 /* $NetBSD: hack.apply.c,v 1.8 2004/01/27 20:30:29 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.apply.c,v 1.8 2004/01/27 20:30:29 jsm Exp $"); 67 #endif /* not lint */ 68 69 #include "hack.h" 70 #include "extern.h" 71 #include "def.edog.h" 72 #include "def.mkroom.h" 73 74 static void use_camera(struct obj *); 75 static int in_ice_box(struct obj *); 76 static int ck_ice_box(struct obj *); 77 static int out_ice_box(struct obj *); 78 static void use_ice_box(struct obj *); 79 static struct monst *bchit(int, int , int , int); 80 static void use_whistle(struct obj *); 81 static void use_magic_whistle(struct obj *); 82 static int dig(void); 83 static int use_pick_axe(struct obj *); 84 85 int 86 doapply() 87 { 88 struct obj *obj; 89 int res = 1; 90 91 obj = getobj("(", "use or apply"); 92 if (!obj) 93 return (0); 94 95 switch (obj->otyp) { 96 case EXPENSIVE_CAMERA: 97 use_camera(obj); 98 break; 99 case ICE_BOX: 100 use_ice_box(obj); 101 break; 102 case PICK_AXE: 103 res = use_pick_axe(obj); 104 break; 105 106 case MAGIC_WHISTLE: 107 if (pl_character[0] == 'W' || u.ulevel > 9) { 108 use_magic_whistle(obj); 109 break; 110 } 111 /* fall into next case */ 112 case WHISTLE: 113 use_whistle(obj); 114 break; 115 116 case CAN_OPENER: 117 if (!carrying(TIN)) { 118 pline("You have no can to open."); 119 goto xit; 120 } 121 pline("You cannot open a tin without eating its contents."); 122 pline("In order to eat, use the 'e' command."); 123 if (obj != uwep) 124 pline("Opening the tin will be much easier if you wield the can-opener."); 125 goto xit; 126 127 default: 128 pline("Sorry, I don't know how to use that."); 129 xit: 130 nomul(0); 131 return (0); 132 } 133 nomul(0); 134 return (res); 135 } 136 137 /* ARGSUSED */ 138 static void 139 use_camera(obj) /* */ 140 struct obj *obj __attribute__((__unused__)); 141 { 142 struct monst *mtmp; 143 if (!getdir(1)) { /* ask: in what direction? */ 144 flags.move = multi = 0; 145 return; 146 } 147 if (u.uswallow) { 148 pline("You take a picture of %s's stomach.", monnam(u.ustuck)); 149 return; 150 } 151 if (u.dz) { 152 pline("You take a picture of the %s.", 153 (u.dz > 0) ? "floor" : "ceiling"); 154 return; 155 } 156 if ((mtmp = bchit(u.dx, u.dy, COLNO, '!')) != NULL) { 157 if (mtmp->msleep) { 158 mtmp->msleep = 0; 159 pline("The flash awakens %s.", monnam(mtmp)); /* a3 */ 160 } else if (mtmp->data->mlet != 'y') 161 if (mtmp->mcansee || mtmp->mblinded) { 162 int tmp = dist(mtmp->mx, mtmp->my); 163 int tmp2; 164 if (cansee(mtmp->mx, mtmp->my)) 165 pline("%s is blinded by the flash!", Monnam(mtmp)); 166 setmangry(mtmp); 167 if (tmp < 9 && !mtmp->isshk && rn2(4)) { 168 mtmp->mflee = 1; 169 if (rn2(4)) 170 mtmp->mfleetim = rnd(100); 171 } 172 if (tmp < 3) 173 mtmp->mcansee = mtmp->mblinded = 0; 174 else { 175 tmp2 = mtmp->mblinded; 176 tmp2 += rnd(1 + 50 / tmp); 177 if (tmp2 > 127) 178 tmp2 = 127; 179 mtmp->mblinded = tmp2; 180 mtmp->mcansee = 0; 181 } 182 } 183 } 184 } 185 186 static 187 struct obj *current_ice_box;/* a local variable of use_ice_box, to be 188 * used by its local procedures in/ck_ice_box */ 189 static int 190 in_ice_box(obj) 191 struct obj *obj; 192 { 193 if (obj == current_ice_box || 194 (Punished && (obj == uball || obj == uchain))) { 195 pline("You must be kidding."); 196 return (0); 197 } 198 if (obj->owornmask & (W_ARMOR | W_RING)) { 199 pline("You cannot refrigerate something you are wearing."); 200 return (0); 201 } 202 if (obj->owt + current_ice_box->owt > 70) { 203 pline("It won't fit."); 204 return (1); /* be careful! */ 205 } 206 if (obj == uwep) { 207 if (uwep->cursed) { 208 pline("Your weapon is welded to your hand!"); 209 return (0); 210 } 211 setuwep((struct obj *) 0); 212 } 213 current_ice_box->owt += obj->owt; 214 freeinv(obj); 215 obj->o_cnt_id = current_ice_box->o_id; 216 obj->nobj = fcobj; 217 fcobj = obj; 218 obj->age = moves - obj->age; /* actual age */ 219 return (1); 220 } 221 222 static int 223 ck_ice_box(obj) 224 struct obj *obj; 225 { 226 return (obj->o_cnt_id == current_ice_box->o_id); 227 } 228 229 static int 230 out_ice_box(obj) 231 struct obj *obj; 232 { 233 struct obj *otmp; 234 if (obj == fcobj) 235 fcobj = fcobj->nobj; 236 else { 237 for (otmp = fcobj; otmp->nobj != obj; otmp = otmp->nobj) 238 if (!otmp->nobj) 239 panic("out_ice_box"); 240 otmp->nobj = obj->nobj; 241 } 242 current_ice_box->owt -= obj->owt; 243 obj->age = moves - obj->age; /* simulated point of time */ 244 (void) addinv(obj); 245 return 0; 246 } 247 248 static void 249 use_ice_box(obj) 250 struct obj *obj; 251 { 252 int cnt = 0; 253 struct obj *otmp; 254 current_ice_box = obj; /* for use by in/out_ice_box */ 255 for (otmp = fcobj; otmp; otmp = otmp->nobj) 256 if (otmp->o_cnt_id == obj->o_id) 257 cnt++; 258 if (!cnt) 259 pline("Your ice-box is empty."); 260 else { 261 pline("Do you want to take something out of the ice-box? [yn] "); 262 if (readchar() == 'y') 263 if (askchain(fcobj, (char *) 0, 0, out_ice_box, ck_ice_box, 0)) 264 return; 265 pline("That was all. Do you wish to put something in? [yn] "); 266 if (readchar() != 'y') 267 return; 268 } 269 /* call getobj: 0: allow cnt; #: allow all types; %: expect food */ 270 otmp = getobj("0#%", "put in"); 271 if (!otmp || !in_ice_box(otmp)) 272 flags.move = multi = 0; 273 } 274 275 static struct monst * 276 bchit(ddx, ddy, range, sym) 277 int ddx, ddy, range; 278 char sym; 279 { 280 struct monst *mtmp = (struct monst *) 0; 281 int bchx = u.ux, bchy = u.uy; 282 283 if (sym) 284 Tmp_at(-1, sym);/* open call */ 285 while (range--) { 286 bchx += ddx; 287 bchy += ddy; 288 if ((mtmp = m_at(bchx, bchy)) != NULL) 289 break; 290 if (!ZAP_POS(levl[bchx][bchy].typ)) { 291 bchx -= ddx; 292 bchy -= ddy; 293 break; 294 } 295 if (sym) 296 Tmp_at(bchx, bchy); 297 } 298 if (sym) 299 Tmp_at(-1, -1); 300 return (mtmp); 301 } 302 303 /* ARGSUSED */ 304 static void 305 use_whistle(obj) 306 struct obj *obj __attribute__((__unused__)); 307 { 308 struct monst *mtmp = fmon; 309 pline("You produce a high whistling sound."); 310 while (mtmp) { 311 if (dist(mtmp->mx, mtmp->my) < u.ulevel * 20) { 312 if (mtmp->msleep) 313 mtmp->msleep = 0; 314 if (mtmp->mtame) 315 EDOG(mtmp)->whistletime = moves; 316 } 317 mtmp = mtmp->nmon; 318 } 319 } 320 321 /* ARGSUSED */ 322 static void 323 use_magic_whistle(obj) 324 struct obj *obj __attribute__((__unused__)); 325 { 326 struct monst *mtmp = fmon; 327 pline("You produce a strange whistling sound."); 328 while (mtmp) { 329 if (mtmp->mtame) 330 mnexto(mtmp); 331 mtmp = mtmp->nmon; 332 } 333 } 334 335 static int dig_effort; /* effort expended on current pos */ 336 static uchar dig_level; 337 static coord dig_pos; 338 static boolean dig_down; 339 340 static int 341 dig() 342 { 343 struct rm *lev; 344 int dpx = dig_pos.x, dpy = dig_pos.y; 345 346 /* perhaps a nymph stole his pick-axe while he was busy digging */ 347 /* or perhaps he teleported away */ 348 if (u.uswallow || !uwep || uwep->otyp != PICK_AXE || 349 dig_level != dlevel || 350 ((dig_down && (dpx != u.ux || dpy != u.uy)) || 351 (!dig_down && dist(dpx, dpy) > 2))) 352 return (0); 353 354 dig_effort += 10 + abon() + uwep->spe + rn2(5); 355 if (dig_down) { 356 if (!xdnstair) { 357 pline("The floor here seems too hard to dig in."); 358 return (0); 359 } 360 if (dig_effort > 250) { 361 dighole(); 362 return (0); /* done with digging */ 363 } 364 if (dig_effort > 50) { 365 struct trap *ttmp = t_at(dpx, dpy); 366 367 if (!ttmp) { 368 ttmp = maketrap(dpx, dpy, PIT); 369 ttmp->tseen = 1; 370 pline("You have dug a pit."); 371 u.utrap = rn1(4, 2); 372 u.utraptype = TT_PIT; 373 return (0); 374 } 375 } 376 } else if (dig_effort > 100) { 377 const char *digtxt; 378 struct obj *obj; 379 380 lev = &levl[dpx][dpy]; 381 if ((obj = sobj_at(ENORMOUS_ROCK, dpx, dpy)) != NULL) { 382 fracture_rock(obj); 383 digtxt = "The rock falls apart."; 384 } else if (!lev->typ || lev->typ == SCORR) { 385 lev->typ = CORR; 386 digtxt = "You succeeded in cutting away some rock."; 387 } else if (lev->typ == HWALL || lev->typ == VWALL 388 || lev->typ == SDOOR) { 389 lev->typ = xdnstair ? DOOR : ROOM; 390 digtxt = "You just made an opening in the wall."; 391 } else 392 digtxt = "Now what exactly was it that you were digging in?"; 393 mnewsym(dpx, dpy); 394 prl(dpx, dpy); 395 pline(digtxt); /* after mnewsym & prl */ 396 return (0); 397 } else { 398 if (IS_WALL(levl[dpx][dpy].typ)) { 399 int rno = inroom(dpx, dpy); 400 401 if (rno >= 0 && rooms[rno].rtype >= 8) { 402 pline("This wall seems too hard to dig into."); 403 return (0); 404 } 405 } 406 pline("You hit the rock with all your might."); 407 } 408 return (1); 409 } 410 411 /* When will hole be finished? Very rough indication used by shopkeeper. */ 412 int 413 holetime() 414 { 415 return ((occupation == dig) ? (250 - dig_effort) / 20 : -1); 416 } 417 418 void 419 dighole() 420 { 421 struct trap *ttmp = t_at(u.ux, u.uy); 422 423 if (!xdnstair) { 424 pline("The floor here seems too hard to dig in."); 425 } else { 426 if (ttmp) 427 ttmp->ttyp = TRAPDOOR; 428 else 429 ttmp = maketrap(u.ux, u.uy, TRAPDOOR); 430 ttmp->tseen = 1; 431 pline("You've made a hole in the floor."); 432 if (!u.ustuck) { 433 if (inshop()) 434 shopdig(1); 435 pline("You fall through ..."); 436 if (u.utraptype == TT_PIT) { 437 u.utrap = 0; 438 u.utraptype = 0; 439 } 440 goto_level(dlevel + 1, FALSE); 441 } 442 } 443 } 444 445 static int 446 use_pick_axe(obj) 447 struct obj *obj; 448 { 449 char dirsyms[12]; 450 char *dsp = dirsyms, *sdp = sdir; 451 struct monst *mtmp; 452 struct rm *lev; 453 int rx, ry, res = 0; 454 455 if (obj != uwep) { 456 if (uwep && uwep->cursed) { 457 /* Andreas Bormann - ihnp4!decvax!mcvax!unido!ab */ 458 pline("Since your weapon is welded to your hand,"); 459 pline("you cannot use that pick-axe."); 460 return (0); 461 } 462 pline("You now wield %s.", doname(obj)); 463 setuwep(obj); 464 res = 1; 465 } 466 while (*sdp) { 467 (void) movecmd(*sdp); /* sets u.dx and u.dy and u.dz */ 468 rx = u.ux + u.dx; 469 ry = u.uy + u.dy; 470 if (u.dz > 0 || (u.dz == 0 && isok(rx, ry) && 471 (IS_ROCK(levl[rx][ry].typ) 472 || sobj_at(ENORMOUS_ROCK, rx, ry)))) 473 *dsp++ = *sdp; 474 sdp++; 475 } 476 *dsp = 0; 477 pline("In what direction do you want to dig? [%s] ", dirsyms); 478 if (!getdir(0)) /* no txt */ 479 return (res); 480 if (u.uswallow && attack(u.ustuck)) /* return(1) */ 481 ; 482 else if (u.dz < 0) 483 pline("You cannot reach the ceiling."); 484 else if (u.dz == 0) { 485 if (Confusion) 486 confdir(); 487 rx = u.ux + u.dx; 488 ry = u.uy + u.dy; 489 if ((mtmp = m_at(rx, ry)) && attack(mtmp)) 490 return (1); 491 if (!isok(rx, ry)) { 492 pline("Clash!"); 493 return (1); 494 } 495 lev = &levl[rx][ry]; 496 if (lev->typ == DOOR) 497 pline("Your %s against the door.", 498 aobjnam(obj, "clang")); 499 else if (!IS_ROCK(lev->typ) 500 && !sobj_at(ENORMOUS_ROCK, rx, ry)) { 501 /* ACCESSIBLE or POOL */ 502 pline("You swing your %s through thin air.", 503 aobjnam(obj, (char *) 0)); 504 } else { 505 if (dig_pos.x != rx || dig_pos.y != ry 506 || dig_level != dlevel || dig_down) { 507 dig_down = FALSE; 508 dig_pos.x = rx; 509 dig_pos.y = ry; 510 dig_level = dlevel; 511 dig_effort = 0; 512 pline("You start digging."); 513 } else 514 pline("You continue digging."); 515 occupation = dig; 516 occtxt = "digging"; 517 } 518 } else if (Levitation) { 519 pline("You cannot reach the floor."); 520 } else { 521 if (dig_pos.x != u.ux || dig_pos.y != u.uy 522 || dig_level != dlevel || !dig_down) { 523 dig_down = TRUE; 524 dig_pos.x = u.ux; 525 dig_pos.y = u.uy; 526 dig_level = dlevel; 527 dig_effort = 0; 528 pline("You start digging in the floor."); 529 if (inshop()) 530 shopdig(0); 531 } else 532 pline("You continue digging in the floor."); 533 occupation = dig; 534 occtxt = "digging"; 535 } 536 return (1); 537 } 538