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