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