1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 2 /* hack.c - version 1.0.3 */ 3 /* $FreeBSD: src/games/hack/hack.c,v 1.4 1999/11/16 10:26:35 marcel Exp $ */ 4 5 #include "hack.h" 6 7 static void movobj(struct obj *, int, int); 8 #ifdef QUEST 9 static bool rroom(int, int); 10 #endif 11 static int inv_cnt(void); 12 13 /* called on movement: 14 * 1. when throwing ball+chain far away 15 * 2. when teleporting 16 * 3. when walking out of a lit room 17 */ 18 void 19 unsee(void) 20 { 21 int x, y; 22 struct rm *lev; 23 24 #ifndef QUEST 25 if (seehx) 26 seehx = 0; 27 else 28 #endif /* QUEST */ 29 for (x = u.ux - 1; x < u.ux + 2; x++) 30 for (y = u.uy - 1; y < u.uy + 2; y++) { 31 if (!isok(x, y)) 32 continue; 33 lev = &levl[x][y]; 34 if (!lev->lit && lev->scrsym == '.') { 35 lev->scrsym = ' '; 36 lev->new = 1; 37 on_scr(x, y); 38 } 39 } 40 } 41 42 /* called: 43 * in hack.eat.c: seeoff(0) - blind after eating rotten food 44 * in hack.mon.c: seeoff(0) - blinded by a yellow light 45 * in hack.mon.c: seeoff(1) - swallowed 46 * in hack.do.c: seeoff(0) - blind after drinking potion 47 * in hack.do.c: seeoff(1) - go up or down the stairs 48 * in hack.trap.c:seeoff(1) - fall through trapdoor 49 * mode: 50 * 1 to redo @, 0 to leave them *//* 1 means 51 * misc movement, 0 means blindness 52 */ 53 void 54 seeoff(bool mode) 55 { 56 int x, y; 57 struct rm *lev; 58 59 if (u.udispl && mode) { 60 u.udispl = 0; 61 levl[u.udisx][u.udisy].scrsym = news0(u.udisx, u.udisy); 62 } 63 #ifndef QUEST 64 if (seehx) 65 seehx = 0; 66 else 67 #endif /* QUEST */ 68 if (!mode) { 69 for (x = u.ux - 1; x < u.ux + 2; x++) 70 for (y = u.uy - 1; y < u.uy + 2; y++) { 71 if (!isok(x, y)) 72 continue; 73 lev = &levl[x][y]; 74 if (!lev->lit && lev->scrsym == '.') 75 lev->seen = 0; 76 } 77 } 78 } 79 80 void 81 domove(void) 82 { 83 xchar oldx, oldy; 84 struct monst *mtmp = NULL; 85 struct rm *tmpr, *ust; 86 struct trap *trap = NULL; 87 struct obj *otmp; 88 89 u_wipe_engr(rnd(5)); 90 91 if (inv_weight() > 0) { 92 pline("You collapse under your load."); 93 nomul(0); 94 return; 95 } 96 if (u.uswallow) { 97 u.dx = u.dy = 0; 98 u.ux = u.ustuck->mx; 99 u.uy = u.ustuck->my; 100 } else { 101 if (Confusion) { 102 do { 103 confdir(); 104 } while (!isok(u.ux + u.dx, u.uy + u.dy) || 105 IS_ROCK(levl[u.ux + u.dx][u.uy + u.dy].typ)); 106 } 107 if (!isok(u.ux + u.dx, u.uy + u.dy)) { 108 nomul(0); 109 return; 110 } 111 } 112 113 ust = &levl[u.ux][u.uy]; 114 oldx = u.ux; 115 oldy = u.uy; 116 if (!u.uswallow && 117 (trap = t_at(u.ux + u.dx, u.uy + u.dy)) && trap->tseen) 118 nomul(0); 119 if (u.ustuck && !u.uswallow && (u.ux + u.dx != u.ustuck->mx || 120 u.uy + u.dy != u.ustuck->my)) { 121 if (dist(u.ustuck->mx, u.ustuck->my) > 2) { 122 /* perhaps it fled (or was teleported or ... ) */ 123 u.ustuck = 0; 124 } else { 125 if (Blind) 126 pline("You cannot escape from it!"); 127 else 128 pline("You cannot escape from %s!", 129 monnam(u.ustuck)); 130 nomul(0); 131 return; 132 } 133 } 134 if (u.uswallow || (mtmp = m_at(u.ux + u.dx, u.uy + u.dy))) { 135 /* attack monster */ 136 137 nomul(0); 138 gethungry(); 139 if (multi < 0) /* we just fainted */ 140 return; 141 142 /* try to attack; note that it might evade */ 143 if (attack(u.uswallow ? u.ustuck : mtmp)) 144 return; 145 } 146 /* not attacking an animal, so we try to move */ 147 if (u.utrap) { 148 if (u.utraptype == TT_PIT) { 149 pline("You are still in a pit."); 150 u.utrap--; 151 } else { 152 pline("You are caught in a beartrap."); 153 if ((u.dx && u.dy) || !rn2(5)) 154 u.utrap--; 155 } 156 return; 157 } 158 tmpr = &levl[u.ux + u.dx][u.uy + u.dy]; 159 if (IS_ROCK(tmpr->typ) || 160 (u.dx && u.dy && (tmpr->typ == DOOR || ust->typ == DOOR))) { 161 flags.move = 0; 162 nomul(0); 163 return; 164 } 165 while ((otmp = sobj_at(ENORMOUS_ROCK, u.ux + u.dx, u.uy + u.dy)) != NULL) { 166 struct trap *ttmp; 167 xchar rx = u.ux + 2 * u.dx, ry = u.uy + 2 * u.dy; 168 nomul(0); 169 if (isok(rx, ry) && !IS_ROCK(levl[rx][ry].typ) && 170 (levl[rx][ry].typ != DOOR || !(u.dx && u.dy)) && 171 !sobj_at(ENORMOUS_ROCK, rx, ry)) { 172 if (m_at(rx, ry)) { 173 pline("You hear a monster behind the rock."); 174 pline("Perhaps that's why you cannot move it."); 175 goto cannot_push; 176 } 177 if ((ttmp = t_at(rx, ry)) != NULL) 178 switch (ttmp->ttyp) { 179 case PIT: 180 pline("You push the rock into a pit!"); 181 deltrap(ttmp); 182 delobj(otmp); 183 pline("It completely fills the pit!"); 184 continue; 185 case TELEP_TRAP: 186 pline("You push the rock and suddenly it disappears!"); 187 delobj(otmp); 188 continue; 189 } 190 if (levl[rx][ry].typ == POOL) { 191 levl[rx][ry].typ = ROOM; 192 mnewsym(rx, ry); 193 prl(rx, ry); 194 pline("You push the rock into the water."); 195 pline("Now you can cross the water!"); 196 delobj(otmp); 197 continue; 198 } 199 otmp->ox = rx; 200 otmp->oy = ry; 201 if (cansee(rx, ry)) 202 atl(rx, ry, otmp->olet); 203 if (Invisible) 204 newsym(u.ux + u.dx, u.uy + u.dy); 205 206 { 207 static long lastmovetime; 208 /* note: this var contains garbage initially and 209 * after a restore */ 210 if (moves > lastmovetime + 2 || moves < lastmovetime) 211 pline("With great effort you move the enormous rock."); 212 lastmovetime = moves; 213 } 214 } else { 215 pline("You try to move the enormous rock, but in vain."); 216 cannot_push: 217 if ((!invent || inv_weight() + 90 <= 0) && 218 (!u.dx || !u.dy || 219 (IS_ROCK(levl[u.ux][u.uy + u.dy].typ) 220 && IS_ROCK(levl[u.ux + u.dx][u.uy].typ)))) { 221 pline("However, you can squeeze yourself into a small opening."); 222 break; 223 } else 224 return; 225 } 226 } 227 if (u.dx && u.dy && IS_ROCK(levl[u.ux][u.uy + u.dy].typ) && 228 IS_ROCK(levl[u.ux + u.dx][u.uy].typ) && 229 invent && inv_weight() + 40 > 0) { 230 pline("You are carrying too much to get through."); 231 nomul(0); 232 return; 233 } 234 if (Punished && 235 DIST(u.ux + u.dx, u.uy + u.dy, uchain->ox, uchain->oy) > 2) { 236 if (carried(uball)) { 237 movobj(uchain, u.ux, u.uy); 238 goto nodrag; 239 } 240 241 if (DIST(u.ux + u.dx, u.uy + u.dy, uball->ox, uball->oy) < 3) { 242 /* leave ball, move chain under/over ball */ 243 movobj(uchain, uball->ox, uball->oy); 244 goto nodrag; 245 } 246 247 if (inv_weight() + (int)uball->owt / 2 > 0) { 248 pline("You cannot %sdrag the heavy iron ball.", 249 invent ? "carry all that and also " : ""); 250 nomul(0); 251 return; 252 } 253 254 movobj(uball, uchain->ox, uchain->oy); 255 unpobj(uball); /* BAH %% */ 256 uchain->ox = u.ux; 257 uchain->oy = u.uy; 258 nomul(-2); 259 nomovemsg = ""; 260 nodrag: ; 261 } 262 u.ux += u.dx; 263 u.uy += u.dy; 264 if (flags.run) { 265 if (tmpr->typ == DOOR || 266 (xupstair == u.ux && yupstair == u.uy) || 267 (xdnstair == u.ux && ydnstair == u.uy)) 268 nomul(0); 269 } 270 271 if (tmpr->typ == POOL && !Levitation) 272 drown(); /* not necessarily fatal */ 273 274 if (!Blind) { 275 #ifdef QUEST 276 setsee(); 277 #else 278 if (ust->lit) { 279 if (tmpr->lit) { 280 if (tmpr->typ == DOOR) 281 prl1(u.ux + u.dx, u.uy + u.dy); 282 else if (ust->typ == DOOR) 283 nose1(oldx - u.dx, oldy - u.dy); 284 } else { 285 unsee(); 286 prl1(u.ux + u.dx, u.uy + u.dy); 287 } 288 } else { 289 if (tmpr->lit) 290 setsee(); 291 else { 292 prl1(u.ux + u.dx, u.uy + u.dy); 293 if (tmpr->typ == DOOR) { 294 if (u.dy) { 295 prl(u.ux - 1, u.uy); 296 prl(u.ux + 1, u.uy); 297 } else { 298 prl(u.ux, u.uy - 1); 299 prl(u.ux, u.uy + 1); 300 } 301 } 302 } 303 nose1(oldx - u.dx, oldy - u.dy); 304 } 305 #endif /* QUEST */ 306 } else 307 pru(); 308 if (!flags.nopick) 309 pickup(1); 310 if (trap) 311 dotrap(trap); /* fall into pit, arrow trap, etc. */ 312 inshop(); 313 if (!Blind) 314 read_engr_at(u.ux, u.uy); 315 } 316 317 static void 318 movobj(struct obj *obj, int ox, int oy) 319 { 320 /* Some dirty programming to get display right */ 321 freeobj(obj); 322 unpobj(obj); 323 obj->nobj = fobj; 324 fobj = obj; 325 obj->ox = ox; 326 obj->oy = oy; 327 } 328 329 int 330 dopickup(void) 331 { 332 if (!g_at(u.ux, u.uy) && !o_at(u.ux, u.uy)) { 333 pline("There is nothing here to pick up."); 334 return (0); 335 } 336 if (Levitation) { 337 pline("You cannot reach the floor."); 338 return (1); 339 } 340 pickup(0); 341 return (1); 342 } 343 344 void 345 pickup(int all) 346 { 347 struct gold *gold; 348 struct obj *obj, *obj2; 349 int wt; 350 351 if (Levitation) 352 return; 353 while ((gold = g_at(u.ux, u.uy))) { 354 pline("%ld gold piece%s.", gold->amount, plur(gold->amount)); 355 u.ugold += gold->amount; 356 flags.botl = 1; 357 freegold(gold); 358 if (flags.run) 359 nomul(0); 360 if (Invisible) 361 newsym(u.ux, u.uy); 362 } 363 364 /* check for more than one object */ 365 if (!all) { 366 int ct = 0; 367 368 for (obj = fobj; obj; obj = obj->nobj) 369 if (obj->ox == u.ux && obj->oy == u.uy) 370 if (!Punished || obj != uchain) 371 ct++; 372 if (ct < 2) 373 all++; 374 else 375 pline("There are several objects here."); 376 } 377 378 for (obj = fobj; obj; obj = obj2) { 379 obj2 = obj->nobj; /* perhaps obj will be picked up */ 380 if (obj->ox == u.ux && obj->oy == u.uy) { 381 if (flags.run) 382 nomul(0); 383 384 /* do not pick up uchain */ 385 if (Punished && obj == uchain) 386 continue; 387 388 if (!all) { 389 char c; 390 391 pline("Pick up %s ? [ynaq]", doname(obj)); 392 while (!strchr("ynaq ", (c = readchar()))) 393 bell(); 394 if (c == 'q') 395 return; 396 if (c == 'n') 397 continue; 398 if (c == 'a') 399 all = 1; 400 } 401 402 if (obj->otyp == DEAD_COCKATRICE && !uarmg) { 403 pline("Touching the dead cockatrice is a fatal mistake."); 404 pline("You turn to stone."); 405 killer = "cockatrice cadaver"; 406 done("died"); 407 } 408 409 if (obj->otyp == SCR_SCARE_MONSTER) { 410 if (!obj->spe) 411 obj->spe = 1; 412 else { 413 /* Note: perhaps the 1st pickup failed: you cannot 414 * carry anymore, and so we never dropped it - 415 * let's assume that treading on it twice also 416 * destroys the scroll */ 417 pline("The scroll turns to dust as you pick it up."); 418 delobj(obj); 419 continue; 420 } 421 } 422 423 wt = inv_weight() + obj->owt; 424 if (wt > 0) { 425 if (obj->quan > 1) { 426 /* see how many we can lift */ 427 int savequan = obj->quan; 428 int iw = inv_weight(); 429 int qq; 430 for (qq = 1; qq < savequan; qq++) { 431 obj->quan = qq; 432 if (iw + weight(obj) > 0) 433 break; 434 } 435 obj->quan = savequan; 436 qq--; 437 /* we can carry qq of them */ 438 if (!qq) 439 goto too_heavy; 440 pline("You can only carry %s of the %s lying here.", 441 (qq == 1) ? "one" : "some", 442 doname(obj)); 443 splitobj(obj, qq); 444 /* note: obj2 is set already, so we'll never 445 * encounter the other half; if it should be 446 * otherwise then write 447 * obj2 = splitobj(obj, qq); 448 */ 449 goto lift_some; 450 } 451 too_heavy: 452 pline("There %s %s here, but %s.", 453 (obj->quan == 1) ? "is" : "are", 454 doname(obj), 455 !invent ? "it is too heavy for you to lift" 456 : "you cannot carry anymore"); 457 break; 458 } 459 lift_some: 460 if (inv_cnt() >= 52) { 461 pline("Your knapsack cannot accommodate anymore items."); 462 break; 463 } 464 if (wt > -5) 465 pline("You have a little trouble lifting"); 466 freeobj(obj); 467 if (Invisible) 468 newsym(u.ux, u.uy); 469 addtobill(obj); /* sets obj->unpaid if necessary */ 470 { 471 int pickquan = obj->quan; 472 int mergquan; 473 if (!Blind) /* this is done by prinv(), */ 474 obj->dknown = 1;/* but addinv() needs it */ 475 /* already for merging */ 476 obj = addinv(obj); /* might merge it with other objects */ 477 mergquan = obj->quan; 478 obj->quan = pickquan; /* to fool prinv() */ 479 prinv(obj); 480 obj->quan = mergquan; 481 } 482 } 483 } 484 } 485 486 /* stop running if we see something interesting */ 487 /* turn around a corner if that is the only way we can proceed */ 488 /* do not turn left or right twice */ 489 void 490 lookaround(void) 491 { 492 int x, y, i, x0, y0, m0, i0 = 9; 493 int corrct = 0, noturn = 0; 494 struct monst *mtmp; 495 496 /* suppress "used before set" message */ 497 x0 = y0 = m0 = 0; 498 if (Blind || flags.run == 0) 499 return; 500 if (flags.run == 1 && levl[u.ux][u.uy].typ == ROOM) 501 return; 502 #ifdef QUEST 503 if (u.ux0 == u.ux + u.dx && u.uy0 == u.uy + u.dy) 504 goto stop; 505 #endif /* QUEST */ 506 for (x = u.ux - 1; x <= u.ux + 1; x++) 507 for (y = u.uy - 1; y <= u.uy + 1; y++) { 508 if (x == u.ux && y == u.uy) 509 continue; 510 if (!levl[x][y].typ) 511 continue; 512 if ((mtmp = m_at(x, y)) && !mtmp->mimic && 513 (!mtmp->minvis || See_invisible)) { 514 if (!mtmp->mtame || 515 (x == u.ux + u.dx && y == u.uy + u.dy)) 516 goto stop; 517 } else /* invisible M cannot influence us */ 518 mtmp = NULL; 519 if (x == u.ux - u.dx && y == u.uy - u.dy) 520 continue; 521 switch (levl[x][y].scrsym) { 522 case '|': 523 case '-': 524 case '.': 525 case ' ': 526 break; 527 case '+': 528 if (x != u.ux && y != u.uy) 529 break; 530 if (flags.run != 1) 531 goto stop; 532 /* FALLTHROUGH */ 533 case CORR_SYM: 534 corr: 535 if (flags.run == 1 || flags.run == 3) { 536 i = DIST(x, y, u.ux + u.dx, u.uy + u.dy); 537 if (i > 2) 538 break; 539 if (corrct == 1 && 540 DIST(x, y, x0, y0) != 1) 541 noturn = 1; 542 if (i < i0) { 543 i0 = i; 544 x0 = x; 545 y0 = y; 546 m0 = mtmp ? 1 : 0; 547 } 548 } 549 corrct++; 550 break; 551 case '^': 552 if (flags.run == 1) /* if you must */ 553 goto corr; 554 if (x == u.ux + u.dx && y == u.uy + u.dy) 555 goto stop; 556 break; 557 default: /* e.g. objects or trap or stairs */ 558 if (flags.run == 1) 559 goto corr; 560 if (mtmp) /* d */ 561 break; 562 stop: 563 nomul(0); 564 return; 565 } 566 } 567 #ifdef QUEST 568 if (corrct > 0 && (flags.run == 4 || flags.run == 5)) 569 goto stop; 570 #endif /* QUEST */ 571 if (corrct > 1 && flags.run == 2) 572 goto stop; 573 if ((flags.run == 1 || flags.run == 3) && !noturn && !m0 && i0 && 574 (corrct == 1 || (corrct == 2 && i0 == 1))) { 575 /* make sure that we do not turn too far */ 576 if (i0 == 2) { 577 if (u.dx == y0 - u.uy && u.dy == u.ux - x0) 578 i = 2; /* straight turn right */ 579 else 580 i = -2; /* straight turn left */ 581 } else if (u.dx && u.dy) { 582 if ((u.dx == u.dy && y0 == u.uy) || 583 (u.dx != u.dy && y0 != u.uy)) 584 i = -1; /* half turn left */ 585 else 586 i = 1; /* half turn right */ 587 } else { 588 if ((x0 - u.ux == y0 - u.uy && !u.dy) || 589 (x0 - u.ux != y0 - u.uy && u.dy)) 590 i = 1; /* half turn right */ 591 else 592 i = -1; /* half turn left */ 593 } 594 i += u.last_str_turn; 595 if (i <= 2 && i >= -2) { 596 u.last_str_turn = i; 597 u.dx = x0 - u.ux, u.dy = y0 - u.uy; 598 } 599 } 600 } 601 602 /* something like lookaround, but we are not running */ 603 /* react only to monsters that might hit us */ 604 bool 605 monster_nearby(void) 606 { 607 int x, y; 608 struct monst *mtmp; 609 610 if (!Blind) 611 for (x = u.ux - 1; x <= u.ux + 1; x++) 612 for (y = u.uy - 1; y <= u.uy + 1; y++) { 613 if (x == u.ux && y == u.uy) 614 continue; 615 if ((mtmp = m_at(x, y)) && !mtmp->mimic && 616 !mtmp->mtame && 617 !mtmp->mpeaceful && 618 !strchr("Ea", mtmp->data->mlet) && 619 !mtmp->mfroz && !mtmp->msleep && /* aplvax!jcn */ 620 (!mtmp->minvis || See_invisible)) 621 return (1); 622 } 623 return (0); 624 } 625 626 #ifdef QUEST 627 bool 628 cansee(xchar x, xchar y) 629 { 630 int dx, dy, adx, ady, sdx, sdy, dmax, d; 631 632 if (Blind) 633 return (0); 634 if (!isok(x, y)) 635 return (0); 636 d = dist(x, y); 637 if (d < 3) 638 return (1); 639 if (d > u.uhorizon * u.uhorizon) 640 return (0); 641 if (!levl[x][y].lit) 642 return (0); 643 dx = x - u.ux; 644 adx = abs(dx); 645 sdx = sgn(dx); 646 dy = y - u.uy; 647 ady = abs(dy); 648 sdy = sgn(dy); 649 if (dx == 0 || dy == 0 || adx == ady) { 650 dmax = (dx == 0) ? ady : adx; 651 for (d = 1; d <= dmax; d++) 652 if (!rroom(sdx * d, sdy * d)) 653 return (0); 654 return (1); 655 } else if (ady > adx) { 656 for (d = 1; d <= ady; d++) { 657 if (!rroom(sdx * ((d * adx) / ady), sdy * d) || 658 !rroom(sdx * ((d * adx - 1) / ady + 1), sdy * d)) 659 return (0); 660 } 661 return (1); 662 } else { 663 for (d = 1; d <= adx; d++) { 664 if (!rroom(sdx * d, sdy * ((d * ady) / adx)) || 665 !rroom(sdx * d, sdy * ((d * ady - 1) / adx + 1))) 666 return (0); 667 } 668 return (1); 669 } 670 } 671 672 static bool 673 rroom(int x, int y) 674 { 675 return (IS_ROOM(levl[u.ux + x][u.uy + y].typ)); 676 } 677 678 #else 679 680 bool 681 cansee(xchar x, xchar y) 682 { 683 if (Blind || u.uswallow) 684 return (0); 685 if (dist(x, y) < 3) 686 return (1); 687 if (levl[x][y].lit && seelx <= x && x <= seehx && seely <= y && 688 y <= seehy) 689 return (1); 690 return (0); 691 } 692 #endif /* QUEST */ 693 694 int 695 sgn(int a) 696 { 697 return ((a > 0) ? 1 : (a == 0) ? 0 : -1); 698 } 699 700 #ifdef QUEST 701 void 702 setsee(void) 703 { 704 int x, y; 705 706 if (Blind) { 707 pru(); 708 return; 709 } 710 for (y = u.uy - u.uhorizon; y <= u.uy + u.uhorizon; y++) 711 for (x = u.ux - u.uhorizon; x <= u.ux + u.uhorizon; x++) { 712 if (cansee(x, y)) 713 prl(x, y); 714 } 715 } 716 717 #else 718 719 void 720 setsee(void) 721 { 722 int x, y; 723 724 if (Blind) { 725 pru(); 726 return; 727 } 728 if (!levl[u.ux][u.uy].lit) { 729 seelx = u.ux - 1; 730 seehx = u.ux + 1; 731 seely = u.uy - 1; 732 seehy = u.uy + 1; 733 } else { 734 for (seelx = u.ux; levl[seelx - 1][u.uy].lit; seelx--) ; 735 for (seehx = u.ux; levl[seehx + 1][u.uy].lit; seehx++) ; 736 for (seely = u.uy; levl[u.ux][seely - 1].lit; seely--) ; 737 for (seehy = u.uy; levl[u.ux][seehy + 1].lit; seehy++) ; 738 } 739 for (y = seely; y <= seehy; y++) 740 for (x = seelx; x <= seehx; x++) 741 prl(x, y); 742 743 if (!levl[u.ux][u.uy].lit) /* seems necessary elsewhere */ 744 seehx = 0; 745 else { 746 if (seely == u.uy) 747 for (x = u.ux - 1; x <= u.ux + 1; x++) 748 prl(x, seely - 1); 749 if (seehy == u.uy) 750 for (x = u.ux - 1; x <= u.ux + 1; x++) 751 prl(x, seehy + 1); 752 if (seelx == u.ux) 753 for (y = u.uy - 1; y <= u.uy + 1; y++) 754 prl(seelx - 1, y); 755 if (seehx == u.ux) 756 for (y = u.uy - 1; y <= u.uy + 1; y++) 757 prl(seehx + 1, y); 758 } 759 } 760 #endif /* QUEST */ 761 762 void 763 nomul(int nval) 764 { 765 if (multi < 0) 766 return; 767 multi = nval; 768 flags.mv = flags.run = 0; 769 } 770 771 int 772 abon(void) 773 { 774 if (u.ustr == 3) 775 return (-3); 776 else if (u.ustr < 6) 777 return (-2); 778 else if (u.ustr < 8) 779 return (-1); 780 else if (u.ustr < 17) 781 return (0); 782 else if (u.ustr < 69) /* up to 18/50 */ 783 return (1); 784 else if (u.ustr < 118) 785 return (2); 786 else 787 return (3); 788 } 789 790 int 791 dbon(void) 792 { 793 if (u.ustr < 6) 794 return (-1); 795 else if (u.ustr < 16) 796 return (0); 797 else if (u.ustr < 18) 798 return (1); 799 else if (u.ustr == 18) /* up to 18 */ 800 return (2); 801 else if (u.ustr < 94) /* up to 18/75 */ 802 return (3); 803 else if (u.ustr < 109) /* up to 18/90 */ 804 return (4); 805 else if (u.ustr < 118) /* up to 18/99 */ 806 return (5); 807 else 808 return (6); 809 } 810 811 /* may kill you; cause may be poison or monster like 'A' */ 812 void 813 losestr(int num) 814 { 815 u.ustr -= num; 816 while (u.ustr < 3) { 817 u.ustr++; 818 u.uhp -= 6; 819 u.uhpmax -= 6; 820 } 821 flags.botl = 1; 822 } 823 824 void 825 losehp(int n, const char *knam) 826 { 827 u.uhp -= n; 828 if (u.uhp > u.uhpmax) 829 u.uhpmax = u.uhp; /* perhaps n was negative */ 830 flags.botl = 1; 831 if (u.uhp < 1) { 832 killer = knam; /* the thing that killed you */ 833 done("died"); 834 } 835 } 836 837 void 838 losehp_m(int n, struct monst *mtmp) 839 { 840 u.uhp -= n; 841 flags.botl = 1; 842 if (u.uhp < 1) 843 done_in_by(mtmp); 844 } 845 846 void 847 losexp(void) /* hit by V or W */ 848 { 849 int num; 850 851 if (u.ulevel > 1) 852 pline("Goodbye level %u.", u.ulevel--); 853 else 854 u.uhp = -1; 855 num = rnd(10); 856 u.uhp -= num; 857 u.uhpmax -= num; 858 u.uexp = newuexp(); 859 flags.botl = 1; 860 } 861 862 int 863 inv_weight(void) 864 { 865 struct obj *otmp = invent; 866 int wt = (u.ugold + 500) / 1000; 867 int carrcap; 868 869 if (Levitation) /* pugh@cornell */ 870 carrcap = MAX_CARR_CAP; 871 else { 872 carrcap = 5 * (((u.ustr > 18) ? 20 : u.ustr) + u.ulevel); 873 if (carrcap > MAX_CARR_CAP) 874 carrcap = MAX_CARR_CAP; 875 if (Wounded_legs & LEFT_SIDE) 876 carrcap -= 10; 877 if (Wounded_legs & RIGHT_SIDE) 878 carrcap -= 10; 879 } 880 while (otmp) { 881 wt += otmp->owt; 882 otmp = otmp->nobj; 883 } 884 return (wt - carrcap); 885 } 886 887 static int 888 inv_cnt(void) 889 { 890 struct obj *otmp = invent; 891 int ct = 0; 892 893 while (otmp) { 894 ct++; 895 otmp = otmp->nobj; 896 } 897 return (ct); 898 } 899 900 long 901 newuexp(void) 902 { 903 return (10 * (1L << (u.ulevel - 1))); 904 } 905