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