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