]> granicus.if.org Git - nethack/commitdiff
health recovery
authorPatR <rankin@nethack.org>
Sun, 16 Jul 2017 01:24:56 +0000 (18:24 -0700)
committerPatR <rankin@nethack.org>
Sun, 16 Jul 2017 01:24:56 +0000 (18:24 -0700)
This started out as just an attempt to remove some duplicated code,
but mutated.  Move health recovery into a separate routine to
streamline moveloop().

Intentional changes:
1) when poly'd hero is at max u.mh (hit points as a monster), do
   not recover lost u.uhp (hit points when in normal form).  That
   was caused by a missing !Upolyd check in the long if..elseif..
   elseif..endif logic.  If we want to make it deliberate, I think
   some u.uhp recovery in rehumanize() would be the way to go.
2) regeneration for poly'd hero in sea monster form (ring worn on
   left or right pectoral fin) now counteracts the loss of hit
   points for turns spent out of water.  [Do eels even have fins?]
3) poly'd hero with moderate or worse encumbrance and lacking
   regeneration wouldn't recover any health.  Now he/she will do so
   if not moving [on the magic (moves%20 == 0) turn when u.mh
   recovery takes place].

If there are any other changes in behavior, they're unintentional.

src/allmain.c

index 1ca917a74b367b80a29341311b5bca09e06d0c7a..2b006bf634e25b538419a289e6889b911d4395ee 100644 (file)
@@ -13,6 +13,7 @@
 #ifdef POSITIONBAR
 STATIC_DCL void NDECL(do_positionbar);
 #endif
+STATIC_DCL void FDECL(regen_hp, (int));
 STATIC_DCL void FDECL(interrupt_multi, (const char *));
 
 void
@@ -185,66 +186,20 @@ boolean resuming;
 
                     /* One possible result of prayer is healing.  Whether or
                      * not you get healed depends on your current hit points.
-                     * If you are allowed to regenerate during the prayer, the
-                     * end-of-prayer calculation messes up on this.
+                     * If you are allowed to regenerate during the prayer,
+                     * the end-of-prayer calculation messes up on this.
                      * Another possible result is rehumanization, which
-                     * requires
-                     * that encumbrance and movement rate be recalculated.
+                     * requires that encumbrance and movement rate be
+                     * recalculated.
                      */
                     if (u.uinvulnerable) {
                         /* for the moment at least, you're in tiptop shape */
                         wtcap = UNENCUMBERED;
-                    } else if (Upolyd && youmonst.data->mlet == S_EEL
-                               && !is_pool(u.ux, u.uy)
-                               && !Is_waterlevel(&u.uz)) {
-                        /* eel out of water loses hp, same as for monsters;
-                           as hp gets lower, rate of further loss slows down
-                           */
-                        if (u.mh > 1 && rn2(u.mh) > rn2(8)
-                            && (!Half_physical_damage || !(moves % 2L))) {
-                            u.mh--;
-                            context.botl = 1;
-                        } else if (u.mh < 1)
-                            rehumanize();
-                    } else if (Upolyd && u.mh < u.mhmax) {
-                        if (u.mh < 1)
-                            rehumanize();
-                        else if (Regeneration
-                                 || (wtcap < MOD_ENCUMBER && !(moves % 20))) {
-                            context.botl = 1;
-                            u.mh++;
-                            if (u.mh >= u.mhmax)
-                                interrupt_multi("You are in full health.");
-                        }
-                    } else if (u.uhp < u.uhpmax
-                               && (wtcap < MOD_ENCUMBER || !u.umoved
-                                   || Regeneration)) {
-                        if (u.ulevel > 9 && !(moves % 3)) {
-                            int heal, Con = (int) ACURR(A_CON);
-
-                            if (Con <= 12) {
-                                heal = 1;
-                            } else {
-                                heal = rnd(Con);
-                                if (heal > u.ulevel - 9)
-                                    heal = u.ulevel - 9;
-                            }
-                            context.botl = 1;
-                            u.uhp += heal;
-                            if (u.uhp > u.uhpmax)
-                                u.uhp = u.uhpmax;
-                            if (u.uhp >= u.uhpmax)
-                                interrupt_multi("You are in full health.");
-                        } else if (Regeneration
-                                   || (u.ulevel <= 9
-                                       && !(moves
-                                            % ((MAXULEV + 12) / (u.ulevel + 2)
-                                               + 1)))) {
-                            context.botl = 1;
-                            u.uhp++;
-                            if (u.uhp >= u.uhpmax)
-                                interrupt_multi("You are in full health.");
-                        }
+                    } else if (!Upolyd ? (u.uhp < u.uhpmax)
+                                       : (u.mh < u.mhmax
+                                          || youmonst.data->mlet == S_EEL)) {
+                        /* maybe heal */
+                        regen_hp(wtcap);
                     }
 
                     /* moving around while encumbered is hard work */
@@ -263,7 +218,7 @@ boolean resuming;
                         }
                     }
 
-                    if ((u.uen < u.uenmax)
+                    if (u.uen < u.uenmax
                         && ((wtcap < MOD_ENCUMBER
                              && (!(moves % ((MAXULEV + 8 - u.ulevel)
                                             * (Role_if(PM_WIZARD) ? 3 : 4)
@@ -273,7 +228,7 @@ boolean resuming;
                         if (u.uen > u.uenmax)
                             u.uen = u.uenmax;
                         context.botl = 1;
-                        if (u.uen >= u.uenmax)
+                        if (u.uen == u.uenmax)
                             interrupt_multi("You feel full of energy.");
                     }
 
@@ -485,6 +440,76 @@ boolean resuming;
     }
 }
 
+/* maybe recover some lost health (or lose some when an eel out of water) */
+STATIC_OVL void
+regen_hp(wtcap)
+int wtcap;
+{
+    int heal = 0;
+    boolean reached_full = FALSE,
+            encumbrance_ok = (wtcap < MOD_ENCUMBER || !u.umoved);
+
+    if (Upolyd) {
+        if (u.mh < 1) { /* shouldn't happen... */
+            rehumanize();
+        } else if (youmonst.data->mlet == S_EEL
+                   && !is_pool(u.ux, u.uy) && !Is_waterlevel(&u.uz)) {
+            /* eel out of water loses hp, similar to monster eels;
+               as hp gets lower, rate of further loss slows down */
+            if (u.mh > 1 && !Regeneration && rn2(u.mh) > rn2(8)
+                && (!Half_physical_damage || !(moves % 2L)))
+                heal = -1;
+        } else if (u.mh < u.mhmax) {
+            if (Regeneration || (encumbrance_ok && !(moves % 20L)))
+                heal = 1;
+        }
+        if (heal) {
+            context.botl = 1;
+            u.mh += heal;
+            reached_full = (u.mh == u.mhmax);
+        }
+
+    /* !Upolyd */
+    } else {
+        /* [when this code was in-line within moveloop(), there was
+           no !Upolyd check here, so poly'd hero recovered lost u.uhp
+           once u.mh reached u.mhmax; that may have been convenient
+           for the player, but it didn't make sense for gameplay...] */
+        if (u.uhp < u.uhpmax && (encumbrance_ok || Regeneration)) {
+            if (u.ulevel > 9) {
+                if (!(moves % 3L)) {
+                    int Con = (int) ACURR(A_CON);
+
+                    if (Con <= 12) {
+                        heal = 1;
+                    } else {
+                        heal = rnd(Con);
+                        if (heal > u.ulevel - 9)
+                            heal = u.ulevel - 9;
+                    }
+                }
+            } else { /* u.ulevel <= 9 */
+                if (!(moves % (long) ((MAXULEV + 12) / (u.ulevel + 2) + 1)))
+                    heal = 1;
+            }
+            if (Regeneration && !heal)
+                heal = 1;
+
+            if (heal) {
+                context.botl = 1;
+                u.uhp += heal;
+                if (u.uhp > u.uhpmax)
+                    u.uhp = u.uhpmax;
+                /* stop voluntary multi-turn activity if now fully healed */
+                reached_full = (u.uhp == u.uhpmax);
+            }
+        }
+    }
+
+    if (reached_full)
+        interrupt_multi("You are in full health.");
+}
+
 void
 stop_occupation()
 {