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