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