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