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