OSDN Git Service

update year to 2020
[jnethack/source.git] / src / attrib.c
index e2e4849..acd69a2 100644 (file)
@@ -1,10 +1,10 @@
-/* NetHack 3.6 attrib.c        $NHDT-Date: 1494034337 2017/05/06 01:32:17 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.62 $ */
+/* NetHack 3.6 attrib.c        $NHDT-Date: 1575245050 2019/12/02 00:04:10 $  $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.66 $ */
 /*      Copyright 1988, 1989, 1990, 1992, M. Stephenson           */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000  */
-/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2019            */
+/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2020            */
 /* JNetHack may be freely redistributed.  See license for details. */
 
 
 
 /* part of the output on gain or loss of attribute */
 static const char
-#if 0 /*JP*/
+#if 0 /*JP:T*/
     *const plusattr[] = { "strong", "smart", "wise",
                           "agile",  "tough", "charismatic" },
 #else
     *const plusattr[] = { "\8b­\82¢", "\8c«\96¾\82¾", "\8c«\82¢",
                           "\8b@\95q\82¾", "\8aæ\8fä\82¾", "\96£\97Í\93I\82¾" },
 #endif
-#if 0 /*JP*/
+#if 0 /*JP:T*/
     *const minusattr[] = { "weak",    "stupid",
                            "foolish", "clumsy",
                            "fragile", "repulsive" };
 #else
     *const minusattr[] = { "\8eã\82¢", "\8bð\82©\82¾",
                            "\8aÔ\94²\82¯\82¾", "\95s\8aí\97p\82¾",
-                           "\82Ð\8eã\82¾","\8fX\82¢" };
+                           "\82Ð\8eã\82¾", "\8fX\82¢" };
 #endif
 /* also used by enlightenment for non-abbreviated status info */
 const char
-#if 0 /*JP*/
+#if 0 /*JP:T*/
     *const attrname[] = { "strength", "intelligence", "wisdom",
                           "dexterity", "constitution", "charisma" };
 #else
@@ -120,7 +120,7 @@ static const struct innate {
 /*JP
                  { 17, &(HTeleport_control), "controlled", "uncontrolled" },
 */
-                 { 17, &(HTeleport_control), "\90§\8cä\97Í\82ð\93¾\82½","\90§\8cä\97Í\82ð\8e¸\82Á\82½" },
+                 { 17, &(HTeleport_control), "\90§\8cä\97Í\82ð\93¾\82½", "\90§\8cä\97Í\82ð\8e¸\82Á\82½" },
                  { 0, 0, 0, 0 } },
 
 /*JP
@@ -180,7 +180,7 @@ static const struct innate {
 /*JP
                  { 17, &(HTeleport_control), "controlled", "uncontrolled" },
 */
-                 { 17, &(HTeleport_control), "\90§\8cä\97Í\82ð\93¾\82½","\90§\8cä\97Í\82ð\8e¸\82Á\82½" },
+                 { 17, &(HTeleport_control), "\90§\8cä\97Í\82ð\93¾\82½", "\90§\8cä\97Í\82ð\8e¸\82Á\82½" },
                  { 0, 0, 0, 0 } },
 
   /* Intrinsics conferred by race */
@@ -215,7 +215,7 @@ adjattrib(ndx, incr, msgflg)
 int ndx, incr;
 int msgflg; /* positive => no message, zero => message, and */
 {           /* negative => conditional (msg if change made) */
-    int old_acurr, old_abase;
+    int old_acurr, old_abase, old_amax, decr;
     boolean abonflg;
     const char *attrstr;
 
@@ -233,23 +233,38 @@ int msgflg; /* positive => no message, zero => message, and */
 
     old_acurr = ACURR(ndx);
     old_abase = ABASE(ndx);
+    old_amax = AMAX(ndx);
+    ABASE(ndx) += incr; /* when incr is negative, this reduces ABASE() */
     if (incr > 0) {
-        ABASE(ndx) += incr;
         if (ABASE(ndx) > AMAX(ndx)) {
-            incr = ABASE(ndx) - AMAX(ndx);
-            AMAX(ndx) += incr;
+            AMAX(ndx) = ABASE(ndx);
             if (AMAX(ndx) > ATTRMAX(ndx))
-                AMAX(ndx) = ATTRMAX(ndx);
-            ABASE(ndx) = AMAX(ndx);
+                ABASE(ndx) = AMAX(ndx) = ATTRMAX(ndx);
         }
         attrstr = plusattr[ndx];
         abonflg = (ABON(ndx) < 0);
-    } else {
-        ABASE(ndx) += incr;
+    } else { /* incr is negative */
         if (ABASE(ndx) < ATTRMIN(ndx)) {
-            incr = ABASE(ndx) - ATTRMIN(ndx);
+            /*
+             * If base value has dropped so low that it is trying to be
+             * taken below the minimum, reduce max value (peak reached)
+             * instead.  That means that restore ability and repeated
+             * applications of unicorn horn will not be able to recover
+             * all the lost value.  As of 3.6.2, we only take away
+             * some (average half, possibly zero) of the excess from max
+             * instead of all of it, but without intervening recovery, it
+             * can still eventually drop to the minimum allowed.  After
+             * that, it can't be recovered, only improved with new gains.
+             *
+             * This used to assign a new negative value to incr and then
+             * add it, but that could affect messages below, possibly
+             * making a large decrease be described as a small one.
+             *
+             * decr = rn2(-(ABASE - ATTRMIN) + 1);
+             */
+            decr = rn2(ATTRMIN(ndx) - ABASE(ndx) + 1);
             ABASE(ndx) = ATTRMIN(ndx);
-            AMAX(ndx) += incr;
+            AMAX(ndx) -= decr;
             if (AMAX(ndx) < ATTRMIN(ndx))
                 AMAX(ndx) = ATTRMIN(ndx);
         }
@@ -258,22 +273,25 @@ int msgflg; /* positive => no message, zero => message, and */
     }
     if (ACURR(ndx) == old_acurr) {
         if (msgflg == 0 && flags.verbose) {
-            if (ABASE(ndx) == old_abase)
-#if 0 /*JP*/
+            if (ABASE(ndx) == old_abase && AMAX(ndx) == old_amax) {
+#if 0 /*JP:T*/
                 pline("You're %s as %s as you can get.",
                       abonflg ? "currently" : "already", attrstr);
 #else
                 You("%s\8f\\95ª\82É%s\81D",
                       abonflg ? "\8d¡\82Ì\82Æ\82±\82ë" : "\8aù\82É", attrstr);
 #endif
-            else /* current stayed the same but base value changed */
-#if 0 /*JP*/
+            } else {
+                /* current stayed the same but base value changed, or
+                   base is at minimum and reduction caused max to drop */
+#if 0 /*JP:T*/
                 Your("innate %s has %s.", attrname[ndx],
                      (incr > 0) ? "improved" : "declined");
 #else
                 Your("\96{\8e¿\93I\82È%s\82ª%s\82µ\82½\81D", attrname[ndx],
                      (incr > 0) ? "\8cü\8fã" : "\92á\89º");
 #endif
+            }
         }
         return FALSE;
     }
@@ -283,8 +301,8 @@ int msgflg; /* positive => no message, zero => message, and */
         You_feel("%s%s!", (incr > 1 || incr < -1) ? "very " : "", attrstr);
 */
         You("%s%s\82È\82Á\82½\82æ\82¤\82È\8bC\82ª\82µ\82½\81I", (incr > 1 || incr < -1) ? "\82Æ\82Ä\82à" : "", jconj_adj(attrstr));
-    context.botl = 1;
-    if (moves > 1 && (ndx == A_STR || ndx == A_CON))
+    context.botl = TRUE;
+    if (program_state.in_moveloop && (ndx == A_STR || ndx == A_CON))
         (void) encumber_msg();
     return TRUE;
 }
@@ -334,32 +352,32 @@ static const struct poison_effect_message {
     void VDECL((*delivery_func), (const char *, ...));
     const char *effect_msg;
 } poiseff[] = {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
     { You_feel, "weaker" },             /* A_STR */
 #else
     { You_feel, "\8eã\82­\82È\82Á\82½" },         /* A_STR */
 #endif
-#if 0 /*JP*/
+#if 0 /*JP:T*/
     { Your, "brain is on fire" },       /* A_INT */
 #else
     { You, "\93ª\82É\8c\8c\82ª\82Ì\82Ú\82Á\82½" },        /* A_INT */
 #endif
-#if 0 /*JP*/
+#if 0 /*JP:T*/
     { Your, "judgement is impaired" },  /* A_WIS */
 #else
     { You, "\94»\92f\97Í\82ð\8e¸\82Á\82½" },          /* A_WIS */
 #endif
-#if 0 /*JP*/
+#if 0 /*JP:T*/
     { Your, "muscles won't obey you" }, /* A_DEX */
 #else
     { You, "\8ev\82¤\82æ\82¤\82É\93®\82¯\82È\82¢" },      /* A_DEX */
 #endif
-#if 0 /*JP*/
+#if 0 /*JP:T*/
     { You_feel, "very sick" },          /* A_CON */
 #else
     { You_feel, "\82Æ\82Ä\82à\8bC\95ª\82ª\88«\82­\82È\82Á\82½" }, /* A_CON */
 #endif
-#if 0 /*JP*/
+#if 0 /*JP:T*/
     { You, "break out in hives" }       /* A_CHA */
 #else
     { You, "\82\82ñ\82Ü\82µ\82ñ\82ª\82 \82ç\82í\82ê\82½" }   /* A_CHA */
@@ -412,7 +430,7 @@ boolean thrown_weapon; /* thrown weapons are less deadly */
     /* inform player about being poisoned unless that's already been done;
        "blast" has given a "blast of poison gas" message; "poison arrow",
        "poison dart", etc have implicitly given poison messages too... */
-#if 0 /*JP*/
+#if 0 /*JP:T*/
     if (strcmp(reason, "blast") && !strstri(reason, "poison")) {
 #else
     if (strcmp(reason, "\95\97") && strcmp(reason, "\91§") && !strstri(reason, "\93Å")) {
@@ -422,7 +440,7 @@ boolean thrown_weapon; /* thrown weapons are less deadly */
 #endif
 
         /* avoid "The" Orcus's sting was poisoned... */
-#if 0 /*JP*/
+#if 0 /*JP:T*/
         pline("%s%s %s poisoned!",
               isupper((uchar) *reason) ? "" : "The ", reason,
               plural ? "were" : "was");
@@ -554,7 +572,7 @@ restore_attrib()
         if (ATEMP(i) != equilibrium && ATIME(i) != 0) {
             if (!(--(ATIME(i)))) { /* countdown for change */
                 ATEMP(i) += (ATEMP(i) > 0) ? -1 : 1;
-                context.botl = 1;
+                context.botl = TRUE;
                 if (ATEMP(i)) /* reset timer */
                     ATIME(i) = 100 / ACURR(A_CON);
             }
@@ -672,7 +690,7 @@ exerper()
 /* exercise/abuse text (must be in attribute order, not botl order);
    phrased as "You must have been [][0]." or "You haven't been [][1]." */
 static NEARDATA const char *const exertext[A_MAX][2] = {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
     { "exercising diligently", "exercising properly" },           /* Str */
     { 0, 0 },                                                     /* Int */
     { "very observant", "paying attention" },                     /* Wis */
@@ -762,7 +780,7 @@ exerchk()
                 /* if you actually changed an attrib - zero accumulation */
                 AEXE(i) = ax = 0;
                 /* then print an explanation */
-#if 0 /*JP*/
+#if 0 /*JP:T*/
                 You("%s %s.",
                     (mod_val > 0) ? "must have been" : "haven't been",
                     exertext[i][(mod_val > 0) ? 0 : 1]);
@@ -771,7 +789,7 @@ exerchk()
                     exertext[i][(mod_val > 0) ? 0 : 1]);
 #endif
             }
       nextattrib:
+ nextattrib:
             /* this used to be ``AEXE(i) /= 2'' but that would produce
                platform-dependent rounding/truncation for negative vals */
             AEXE(i) = (abs(ax) / 2) * mod_val;
@@ -1053,7 +1071,7 @@ int propidx; /* special cases can have negative values */
 */
                 Strcpy(buf, "\8c»\8dÝ\82Ì\8ep\82É\82æ\82Á\82Ä");
             else if (propidx == FAST && Very_fast)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
                 Sprintf(buf, because_of,
                         ((HFast & TIMEOUT) != 0L) ? "a potion or spell"
                           : ((EFast & W_ARMF) != 0L && uarmf->dknown
@@ -1372,15 +1390,17 @@ int reason; /* 0==conversion, 1==helm-of-OA on, 2==helm-of-OA off */
 {
     aligntyp oldalign = u.ualign.type;
 
-    u.ublessed = 0;   /* lose divine protection */
-    context.botl = 1; /* status line needs updating */
+    u.ublessed = 0; /* lose divine protection */
+    /* You/Your/pline message with call flush_screen(), triggering bot(),
+       so the actual data change needs to come before the message */
+    context.botl = TRUE; /* status line needs updating */
     if (reason == 0) {
         /* conversion via altar */
         u.ualignbase[A_CURRENT] = (aligntyp) newalign;
         /* worn helm of opposite alignment might block change */
         if (!uarmh || uarmh->otyp != HELM_OF_OPPOSITE_ALIGNMENT)
             u.ualign.type = u.ualignbase[A_CURRENT];
-#if 0 /*JP*/
+#if 0 /*JP:T*/
         You("have a %ssense of a new direction.",
             (u.ualign.type != oldalign) ? "sudden " : "");
 #else
@@ -1396,7 +1416,7 @@ int reason; /* 0==conversion, 1==helm-of-OA on, 2==helm-of-OA off */
 */
             You("%s\90Q\95Ô\82Á\82½\81D", Hallucination ? "\8dr\82Á\82Û\82­" : "\82 \82Á\82³\82è\82Æ");
         else if (reason == 2)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
             Your("mind is %s.", Hallucination
                                     ? "much of a muchness"
                                     : "back in sync with your body");
@@ -1406,7 +1426,6 @@ int reason; /* 0==conversion, 1==helm-of-OA on, 2==helm-of-OA off */
                                     : "\8dÄ\82Ñ\91Ì\82Æ\88ê\92v\82·\82é\82æ\82¤\82É\82È\82Á\82½");
 #endif
     }
-
     if (u.ualign.type != oldalign) {
         u.ualign.record = 0; /* slate is wiped clean */
         retouch_equipment(0);