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