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