1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 2 /* hack.do.c - version 1.0.3 */ 3 /* $FreeBSD: src/games/hack/hack.do.c,v 1.4 1999/11/16 10:26:36 marcel Exp $ */ 4 /* $DragonFly: src/games/hack/hack.do.c,v 1.5 2006/08/21 19:45:32 pavalos Exp $ */ 5 6 /* Contains code for 'd', 'D' (drop), '>', '<' (up, down) and 't' (throw) */ 7 8 #include "hack.h" 9 10 extern struct monst youmonst; 11 12 static int drop(struct obj *); 13 static void dropy(struct obj *); 14 15 int 16 dodrop(void) 17 { 18 return (drop(getobj("0$#", "drop"))); 19 } 20 21 static int 22 drop(struct obj *obj) 23 { 24 if (!obj) 25 return (0); 26 if (obj->olet == '$') { /* pseudo object */ 27 long amount = OGOLD(obj); 28 29 if (amount == 0) 30 pline("You didn't drop any gold pieces."); 31 else { 32 mkgold(amount, u.ux, u.uy); 33 pline("You dropped %ld gold piece%s.", 34 amount, plur(amount)); 35 if (Invisible) 36 newsym(u.ux, u.uy); 37 } 38 free(obj); 39 return (1); 40 } 41 if (obj->owornmask & (W_ARMOR | W_RING)) { 42 pline("You cannot drop something you are wearing."); 43 return (0); 44 } 45 if (obj == uwep) { 46 if (uwep->cursed) { 47 pline("Your weapon is welded to your hand!"); 48 return (0); 49 } 50 setuwep(NULL); 51 } 52 pline("You dropped %s.", doname(obj)); 53 dropx(obj); 54 return (1); 55 } 56 57 /* Called in several places - should not produce texts */ 58 void 59 dropx(struct obj *obj) 60 { 61 freeinv(obj); 62 dropy(obj); 63 } 64 65 static void 66 dropy(struct obj *obj) 67 { 68 if (obj->otyp == CRYSKNIFE) 69 obj->otyp = WORM_TOOTH; 70 obj->ox = u.ux; 71 obj->oy = u.uy; 72 obj->nobj = fobj; 73 fobj = obj; 74 if (Invisible) 75 newsym(u.ux, u.uy); 76 subfrombill(obj); 77 stackobj(obj); 78 } 79 80 /* drop several things */ 81 int 82 doddrop(void) 83 { 84 return (ggetobj("drop", drop, 0)); 85 } 86 87 int 88 dodown(void) 89 { 90 if (u.ux != xdnstair || u.uy != ydnstair) { 91 pline("You can't go down here."); 92 return (0); 93 } 94 if (u.ustuck) { 95 pline("You are being held, and cannot go down."); 96 return (1); 97 } 98 if (Levitation) { 99 pline("You're floating high above the stairs."); 100 return (0); 101 } 102 103 goto_level(dlevel + 1, TRUE); 104 return (1); 105 } 106 107 int 108 doup(void) 109 { 110 if (u.ux != xupstair || u.uy != yupstair) { 111 pline("You can't go up here."); 112 return (0); 113 } 114 if (u.ustuck) { 115 pline("You are being held, and cannot go up."); 116 return (1); 117 } 118 if (!Levitation && inv_weight() + 5 > 0) { 119 pline("Your load is too heavy to climb the stairs."); 120 return (1); 121 } 122 123 goto_level(dlevel - 1, TRUE); 124 return (1); 125 } 126 127 void 128 goto_level(int newlevel, boolean at_stairs) 129 { 130 int fd; 131 boolean up = (newlevel < dlevel); 132 133 if (newlevel <= 0) /* in fact < 0 is impossible */ 134 done("escaped"); 135 if (newlevel > MAXLEVEL) /* strange ... */ 136 newlevel = MAXLEVEL; 137 if (newlevel == dlevel) /* this can happen */ 138 return; 139 140 glo(dlevel); 141 fd = creat(lock, FMASK); 142 if (fd < 0) { 143 /* 144 * This is not quite impossible: e.g., we may have 145 * exceeded our quota. If that is the case then we 146 * cannot leave this level, and cannot save either. 147 * Another possibility is that the directory was not 148 * writable. 149 */ 150 pline("A mysterious force prevents you from going %s.", 151 up ? "up" : "down"); 152 return; 153 } 154 155 if (Punished) 156 unplacebc(); 157 u.utrap = 0; /* needed in level_tele */ 158 u.ustuck = 0; /* idem */ 159 keepdogs(); 160 seeoff(1); 161 if (u.uswallow) /* idem */ 162 u.uswldtim = u.uswallow = 0; 163 flags.nscrinh = 1; 164 u.ux = FAR; /* hack */ 165 inshop(); /* probably was a trapdoor */ 166 167 savelev(fd, dlevel); 168 close(fd); 169 170 dlevel = newlevel; 171 if (maxdlevel < dlevel) 172 maxdlevel = dlevel; 173 glo(dlevel); 174 175 if (!level_exists[dlevel]) 176 mklev(); 177 else { 178 if ((fd = open(lock, O_RDONLY)) < 0) { 179 pline("Cannot open %s .", lock); 180 pline("Probably someone removed it."); 181 done("tricked"); 182 } 183 getlev(fd, hackpid, dlevel); 184 close(fd); 185 } 186 187 if (at_stairs) { 188 if (up) { 189 u.ux = xdnstair; 190 u.uy = ydnstair; 191 if (!u.ux) { /* entering a maze from below? */ 192 u.ux = xupstair; /* this will confuse the player! */ 193 u.uy = yupstair; 194 } 195 if (Punished && !Levitation) { 196 pline("With great effort you climb the stairs."); 197 placebc(1); 198 } 199 } else { 200 u.ux = xupstair; 201 u.uy = yupstair; 202 if (inv_weight() + 5 > 0 || Punished) { 203 pline("You fall down the stairs."); /* %% */ 204 losehp(rnd(3), "fall"); 205 if (Punished) { 206 if (uwep != uball && rn2(3)) { 207 pline("... and are hit by the iron ball."); 208 losehp(rnd(20), "iron ball"); 209 } 210 placebc(1); 211 } 212 selftouch("Falling, you"); 213 } 214 } 215 { 216 struct monst *mtmp = m_at(u.ux, u.uy); 217 if (mtmp) 218 mnexto(mtmp); 219 } 220 } else { /* trapdoor or level_tele */ 221 do { 222 u.ux = rnd(COLNO - 1); 223 u.uy = rn2(ROWNO); 224 } while (levl[u.ux][u.uy].typ != ROOM || 225 m_at(u.ux, u.uy)); 226 if (Punished) { 227 if (uwep != uball && !up /* %% */ && rn2(5)) { 228 pline("The iron ball falls on your head."); 229 losehp(rnd(25), "iron ball"); 230 } 231 placebc(1); 232 } 233 selftouch("Falling, you"); 234 } 235 inshop(); 236 initrack(); 237 238 losedogs(); 239 { 240 struct monst *mtmp; 241 if ((mtmp = m_at(u.ux, u.uy))) /* riv05!a3 */ 242 mnexto(mtmp); 243 } 244 flags.nscrinh = 0; 245 setsee(); 246 seeobjs(); /* make old cadavers disappear - riv05!a3 */ 247 docrt(); 248 pickup(1); 249 read_engr_at(u.ux, u.uy); 250 } 251 252 int 253 donull(void) 254 { 255 return (1); /* Do nothing, but let other things happen */ 256 } 257 258 int 259 dopray(void) 260 { 261 nomovemsg = "You finished your prayer."; 262 nomul(-3); 263 return (1); 264 } 265 266 int 267 dothrow(void) 268 { 269 struct obj *obj; 270 struct monst *mon; 271 int tmp; 272 273 obj = getobj("#)", "throw"); /* it is also possible to throw food */ 274 /* (or jewels, or iron balls ... ) */ 275 if (!obj || !getdir(1)) /* ask "in what direction?" */ 276 return (0); 277 if (obj->owornmask & (W_ARMOR | W_RING)) { 278 pline("You can't throw something you are wearing."); 279 return (0); 280 } 281 282 u_wipe_engr(2); 283 284 if (obj == uwep) { 285 if (obj->cursed) { 286 pline("Your weapon is welded to your hand."); 287 return (1); 288 } 289 if (obj->quan > 1) 290 setuwep(splitobj(obj, 1)); 291 else 292 setuwep(NULL); 293 } else if (obj->quan > 1) 294 splitobj(obj, 1); 295 freeinv(obj); 296 if (u.uswallow) { 297 mon = u.ustuck; 298 bhitpos.x = mon->mx; 299 bhitpos.y = mon->my; 300 } else if (u.dz) { 301 if (u.dz < 0) { 302 pline("%s hits the ceiling, then falls back on top of your head.", 303 Doname(obj)); /* note: obj->quan == 1 */ 304 if (obj->olet == POTION_SYM) 305 potionhit(&youmonst, obj); 306 else { 307 if (uarmh) 308 pline("Fortunately, you are wearing a helmet!"); 309 losehp(uarmh ? 1 : rnd((int)(obj->owt)), 310 "falling object"); 311 dropy(obj); 312 } 313 } else { 314 pline("%s hits the floor.", Doname(obj)); 315 if (obj->otyp == EXPENSIVE_CAMERA) { 316 pline("It is shattered in a thousand pieces!"); 317 obfree(obj, NULL); 318 } else if (obj->otyp == EGG) { 319 pline("\"Splash!\""); 320 obfree(obj, NULL); 321 } else if (obj->olet == POTION_SYM) { 322 pline("The flask breaks, and you smell a peculiar odor ..."); 323 potionbreathe(obj); 324 obfree(obj, NULL); 325 } else 326 dropy(obj); 327 } 328 return (1); 329 } else if (obj->otyp == BOOMERANG) { 330 mon = boomhit(u.dx, u.dy); 331 if (mon == &youmonst) { /* the thing was caught */ 332 addinv(obj); 333 return (1); 334 } 335 } else { 336 if (obj->otyp == PICK_AXE && shkcatch(obj)) 337 return (1); 338 339 mon = bhit(u.dx, u.dy, (obj->otyp == ICE_BOX) ? 1 : 340 (!Punished || obj != uball) ? 8 : !u.ustuck ? 5 : 1, 341 obj->olet, (void (*)(struct monst *, struct obj *)) 0, 342 (bool (*)(struct obj *, struct obj *)) 0, obj); 343 } 344 if (mon) { 345 /* awake monster if sleeping */ 346 wakeup(mon); 347 348 if (obj->olet == WEAPON_SYM) { 349 tmp = -1 + u.ulevel + mon->data->ac + abon(); 350 if (obj->otyp < ROCK) { 351 if (!uwep || 352 uwep->otyp != obj->otyp + (BOW - ARROW)) 353 tmp -= 4; 354 else { 355 tmp += uwep->spe; 356 } 357 } else if (obj->otyp == BOOMERANG) 358 tmp += 4; 359 tmp += obj->spe; 360 if (u.uswallow || tmp >= rnd(20)) { 361 if (hmon(mon, obj, 1) == TRUE) { 362 /* mon still alive */ 363 #ifndef NOWORM 364 cutworm(mon, bhitpos.x, bhitpos.y, obj->otyp); 365 #endif /* NOWORM */ 366 } else 367 mon = 0; 368 /* weapons thrown disappear sometimes */ 369 if (obj->otyp < BOOMERANG && rn2(3)) { 370 /* check bill; free */ 371 obfree(obj, NULL); 372 return (1); 373 } 374 } else 375 miss(objects[obj->otyp].oc_name, mon); 376 } else if (obj->otyp == HEAVY_IRON_BALL) { 377 tmp = -1 + u.ulevel + mon->data->ac + abon(); 378 if (!Punished || obj != uball) 379 tmp += 2; 380 if (u.utrap) 381 tmp -= 2; 382 if (u.uswallow || tmp >= rnd(20)) { 383 if (hmon(mon, obj, 1) == FALSE) 384 mon = 0; /* he died */ 385 } else 386 miss("iron ball", mon); 387 } else if (obj->olet == POTION_SYM && u.ulevel > rn2(15)) { 388 potionhit(mon, obj); 389 return (1); 390 } else { 391 if (cansee(bhitpos.x, bhitpos.y)) 392 pline("You miss %s.", monnam(mon)); 393 else 394 pline("You miss it."); 395 if (obj->olet == FOOD_SYM && mon->data->mlet == 'd') 396 if (tamedog(mon, obj)) 397 return (1); 398 if (obj->olet == GEM_SYM && mon->data->mlet == 'u' && 399 !mon->mtame) { 400 if (obj->dknown && objects[obj->otyp].oc_name_known) { 401 if (objects[obj->otyp].g_val > 0) { 402 u.uluck += 5; 403 goto valuable; 404 } else 405 pline("%s is not interested in your junk.", 406 Monnam(mon)); 407 } else { /* value unknown to @ */ 408 u.uluck++; 409 valuable: 410 if (u.uluck > LUCKMAX) /* dan@ut-ngp */ 411 u.uluck = LUCKMAX; 412 pline("%s graciously accepts your gift.", 413 Monnam(mon)); 414 mpickobj(mon, obj); 415 rloc(mon); 416 return (1); 417 } 418 } 419 } 420 } 421 /* the code following might become part of dropy() */ 422 if (obj->otyp == CRYSKNIFE) 423 obj->otyp = WORM_TOOTH; 424 obj->ox = bhitpos.x; 425 obj->oy = bhitpos.y; 426 obj->nobj = fobj; 427 fobj = obj; 428 /* prevent him from throwing articles to the exit and escaping */ 429 /* subfrombill(obj); */ 430 stackobj(obj); 431 if (Punished && obj == uball && 432 (bhitpos.x != u.ux || bhitpos.y != u.uy)) { 433 freeobj(uchain); 434 unpobj(uchain); 435 if (u.utrap) { 436 if (u.utraptype == TT_PIT) 437 pline("The ball pulls you out of the pit!"); 438 else { 439 long side = rn2(3) ? LEFT_SIDE : RIGHT_SIDE; 440 pline("The ball pulls you out of the bear trap."); 441 pline("Your %s leg is severely damaged.", 442 (side == LEFT_SIDE) ? "left" : "right"); 443 set_wounded_legs(side, 500 + rn2(1000)); 444 losehp(2, "thrown ball"); 445 } 446 u.utrap = 0; 447 } 448 unsee(); 449 uchain->nobj = fobj; 450 fobj = uchain; 451 u.ux = uchain->ox = bhitpos.x - u.dx; 452 u.uy = uchain->oy = bhitpos.y - u.dy; 453 setsee(); 454 inshop(); 455 } 456 if (cansee(bhitpos.x, bhitpos.y)) 457 prl(bhitpos.x, bhitpos.y); 458 return (1); 459 } 460 461 /* split obj so that it gets size num */ 462 /* remainder is put in the object structure delivered by this call */ 463 struct obj * 464 splitobj(struct obj *obj, int num) 465 { 466 struct obj *otmp; 467 468 otmp = newobj(0); 469 *otmp = *obj; /* copies whole structure */ 470 otmp->o_id = flags.ident++; 471 otmp->onamelth = 0; 472 obj->quan = num; 473 obj->owt = weight(obj); 474 otmp->quan -= num; 475 otmp->owt = weight(otmp); /* -= obj->owt ? */ 476 obj->nobj = otmp; 477 if (obj->unpaid) 478 splitbill(obj, otmp); 479 return (otmp); 480 } 481 482 void 483 more_experienced(int exp, int rexp) 484 { 485 u.uexp += exp; 486 u.urexp += 4 * exp + rexp; 487 if (exp) 488 flags.botl = 1; 489 if (u.urexp >= ((pl_character[0] == 'W') ? 1000 : 2000)) 490 flags.beginner = 0; 491 } 492 493 void 494 set_wounded_legs(long side, int timex) 495 { 496 if (!Wounded_legs || (Wounded_legs & TIMEOUT)) 497 Wounded_legs |= side + timex; 498 else 499 Wounded_legs |= side; 500 } 501 502 void 503 heal_legs(void) 504 { 505 if (Wounded_legs) { 506 if ((Wounded_legs & BOTH_SIDES) == BOTH_SIDES) 507 pline("Your legs feel somewhat better."); 508 else 509 pline("Your leg feels somewhat better."); 510 Wounded_legs = 0; 511 } 512 } 513