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