domain: Nuke pfslowtimo.
[dragonfly.git] / games / hack / hack.c
blob56aa11fa3380477fba4822915d9430f0cf578547
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 $ */
5 #include "hack.h"
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);
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
18 void
19 unsee(void)
21 int x, y;
22 struct rm *lev;
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);
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
53 void
54 seeoff(bool mode)
56 int x, y;
57 struct rm *lev;
59 if (u.udispl && mode) {
60 u.udispl = 0;
61 levl[u.udisx][u.udisy].scrsym = news0(u.udisx, u.udisy);
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;
80 void
81 domove(void)
83 xchar oldx, oldy;
84 struct monst *mtmp = NULL;
85 struct rm *tmpr, *ust;
86 struct trap *trap = NULL;
87 struct obj *otmp;
89 u_wipe_engr(rnd(5));
91 if (inv_weight() > 0) {
92 pline("You collapse under your load.");
93 nomul(0);
94 return;
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));
107 if (!isok(u.ux + u.dx, u.uy + u.dy)) {
108 nomul(0);
109 return;
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;
134 if (u.uswallow || (mtmp = m_at(u.ux + u.dx, u.uy + u.dy))) {
135 /* attack monster */
137 nomul(0);
138 gethungry();
139 if (multi < 0) /* we just fainted */
140 return;
142 /* try to attack; note that it might evade */
143 if (attack(u.uswallow ? u.ustuck : mtmp))
144 return;
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--;
156 return;
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;
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;
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;
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;
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);
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;
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;
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;
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;
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;
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;
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: ;
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);
271 if (tmpr->typ == POOL && !Levitation)
272 drown(); /* not necessarily fatal */
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);
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);
303 nose1(oldx - u.dx, oldy - u.dy);
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);
317 static void
318 movobj(struct obj *obj, int ox, int oy)
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;
330 dopickup(void)
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);
336 if (Levitation) {
337 pline("You cannot reach the floor.");
338 return (1);
340 pickup(0);
341 return (1);
344 void
345 pickup(int all)
347 struct gold *gold;
348 struct obj *obj, *obj2;
349 int wt;
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);
364 /* check for more than one object */
365 if (!all) {
366 int ct = 0;
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.");
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);
384 /* do not pick up uchain */
385 if (Punished && obj == uchain)
386 continue;
388 if (!all) {
389 char c;
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;
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");
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;
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;
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);
449 goto lift_some;
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;
459 lift_some:
460 if (inv_cnt() >= 52) {
461 pline("Your knapsack cannot accommodate anymore items.");
462 break;
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 */
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;
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)
492 int x, y, i, x0, y0, m0, i0 = 9;
493 int corrct = 0, noturn = 0;
494 struct monst *mtmp;
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 /* fall into next case */
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;
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;
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 */
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;
602 /* something like lookaround, but we are not running */
603 /* react only to monsters that might hit us */
604 bool
605 monster_nearby(void)
607 int x, y;
608 struct monst *mtmp;
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);
623 return (0);
626 #ifdef QUEST
627 bool
628 cansee(xchar x, xchar y)
630 int dx, dy, adx, ady, sdx, sdy, dmax, d;
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);
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);
668 return (1);
672 static bool
673 rroom(int x, int y)
675 return (IS_ROOM(levl[u.ux + x][u.uy + y].typ));
678 #else
680 bool
681 cansee(xchar x, xchar y)
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);
692 #endif /* QUEST */
695 sgn(int a)
697 return ((a > 0) ? 1 : (a == 0) ? 0 : -1);
700 #ifdef QUEST
701 void
702 setsee(void)
704 int x, y;
706 if (Blind) {
707 pru();
708 return;
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);
717 #else
719 void
720 setsee(void)
722 int x, y;
724 if (Blind) {
725 pru();
726 return;
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++) ;
739 for (y = seely; y <= seehy; y++)
740 for (x = seelx; x <= seehx; x++)
741 prl(x, y);
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);
760 #endif /* QUEST */
762 void
763 nomul(int nval)
765 if (multi < 0)
766 return;
767 multi = nval;
768 flags.mv = flags.run = 0;
772 abon(void)
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);
791 dbon(void)
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);
811 /* may kill you; cause may be poison or monster like 'A' */
812 void
813 losestr(int num)
815 u.ustr -= num;
816 while (u.ustr < 3) {
817 u.ustr++;
818 u.uhp -= 6;
819 u.uhpmax -= 6;
821 flags.botl = 1;
824 void
825 losehp(int n, const char *knam)
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");
837 void
838 losehp_m(int n, struct monst *mtmp)
840 u.uhp -= n;
841 flags.botl = 1;
842 if (u.uhp < 1)
843 done_in_by(mtmp);
846 void
847 losexp(void) /* hit by V or W */
849 int num;
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;
863 inv_weight(void)
865 struct obj *otmp = invent;
866 int wt = (u.ugold + 500) / 1000;
867 int carrcap;
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;
880 while (otmp) {
881 wt += otmp->owt;
882 otmp = otmp->nobj;
884 return (wt - carrcap);
887 static int
888 inv_cnt(void)
890 struct obj *otmp = invent;
891 int ct = 0;
893 while (otmp) {
894 ct++;
895 otmp = otmp->nobj;
897 return (ct);
900 long
901 newuexp(void)
903 return (10 * (1L << (u.ulevel - 1)));