]> granicus.if.org Git - nethack/commitdiff
nerf potion alchemy (trunk only)
authornethack.rankin <nethack.rankin>
Sun, 19 Feb 2012 02:06:43 +0000 (02:06 +0000)
committernethack.rankin <nethack.rankin>
Sun, 19 Feb 2012 02:06:43 +0000 (02:06 +0000)
     Something I've had in mind for a long time:  make it harder to acquire
dozens of potions of full healing and thereby (8 * dozens) of extra hit
points.  When dipping a stack of more than 2 potions into another potion
other than water, first split the stack so that 2 to 9 potions are dipped
rather than all of them.  Alchemy still works but it will take more dips
(hence need more resources) to convert large amounts.  Dipping into water
isn't affected, nor is dipping non-potions.

     Also fix a bug where dipping a stack--now perhaps a subset stack after
splitting--which triggered an explosion was only using up one of the dipped
potions (plus the one being dipped into) instead of the whole stack.

doc/fixes35.0
src/potion.c

index 55fb6a337a0d0459108e9e997a0dbae2de1ffd32..a4e6b1bd2ca0167bd3377d90053cf36062f5c259 100644 (file)
@@ -409,6 +409,8 @@ theft of worn armor with wear/unwear delay would interfere with completion of
        (disrupted wear attempt for +N helm of brilliance would result in loss
        of N points of Int and Wis; gauntlets of dexterity had similar problem)
 #sit while swallowed would give the wrong message
+alchemical explosion or evaporation only used up one potion instead of all
+       the potions being dipped
 
 
 Platform- and/or Interface-Specific Fixes
@@ -558,6 +560,7 @@ display version and build information at startup
 repeatedly setting the fruit option will check to see if fruits have been
     created, so the user can't easily overflow the maximum this way
 bones files now include extra data to identify dead hero and reason for death
+dipping multiple potions in another potion may only dip part of their stack
 
 
 Platform- and/or Interface-Specific New Features
index 372554787e048ad41aa80913c727807d74435ffa..42124f28818cd92300d657ece41388b70cfcdd6e 100644 (file)
@@ -1815,14 +1815,14 @@ dodip()
                                potion : obj, 5, 95)) {
                pline1(nothing_happens);
            } else {
-               boolean was_wep = FALSE, was_swapwep = FALSE, was_quiver = FALSE;
+               boolean was_wep, was_swapwep, was_quiver;
                short save_otyp = obj->otyp;
                /* KMH, conduct */
                u.uconduct.polypiles++;
 
-               if (obj == uwep) was_wep = TRUE;
-               else if (obj == uswapwep) was_swapwep = TRUE;
-               else if (obj == uquiver) was_quiver = TRUE;
+               was_wep = (obj == uwep);
+               was_swapwep = (obj == uswapwep);
+               was_quiver = (obj == uquiver);
 
                obj = poly_obj(obj, STRANGE_OBJECT);
 
@@ -1842,66 +1842,98 @@ dodip()
            }
            potion->in_use = FALSE;     /* didn't go poof */
            return(1);
-       } else if(obj->oclass == POTION_CLASS && obj->otyp != potion->otyp) {
-               /* Mixing potions is dangerous... */
-               pline_The("potions mix...");
-               /* KMH, balance patch -- acid is particularly unstable */
-               if (obj->cursed || obj->otyp == POT_ACID || !rn2(10)) {
-                       pline("BOOM!  They explode!");
-                       wake_nearto(u.ux, u.uy, (BOLT_LIM+1)*(BOLT_LIM+1));
-                       exercise(A_STR, FALSE);
-                       if (!breathless(youmonst.data) || haseyes(youmonst.data))
-                               potionbreathe(obj);
-                       useup(obj);
-                       useup(potion);
-                       losehp(rnd(10), "alchemic blast",  /* not physical damage */
-                                       KILLED_BY_AN);
-                       return(1);
+       } else if (obj->oclass == POTION_CLASS && obj->otyp != potion->otyp) {
+           long amt = obj->quan;
+
+           Strcpy(qbuf, "The");
+           if (amt > (objects[potion->otyp].oc_magic ? 2L : 9L)) {
+               /* trying to dip multiple potions will usually affect only a
+                  subset; pick an amount between 2 and min(N,9), inclusive */
+               amt -= 1L;
+               do {
+                   amt = (long)rnd((int)amt);
+               } while (amt >= 9L);
+               amt += 1L;
+               if (amt < obj->quan) {
+                   obj = splitobj(obj, amt);
+                   Sprintf(qbuf, "%ld of the", obj->quan);
                }
+           }
+           /* [N of] the {obj(s)} mix(es) with [one of] {the potion}... */
+           pline("%s %s %s with %s%s...", qbuf,
+                 simpleonames(obj), otense(obj, "mix"),
+                 (potion->quan > 1L) ? "one of " : "",
+                 thesimpleoname(potion));
+           /* Mixing potions is dangerous...
+              KMH, balance patch -- acid is particularly unstable */
+           if (obj->cursed || obj->otyp == POT_ACID || !rn2(10)) {
+               /* it would be better to use up the whole stack in advance
+                  of the message, but we can't because we need to keep it
+                  around for potionbreathe() [and we can't set obj->in_use
+                  to 'amt' because that's not implemented] */
+               obj->in_use = 1;
+               pline("BOOM!  They explode!");
+               wake_nearto(u.ux, u.uy, (BOLT_LIM+1)*(BOLT_LIM+1));
+               exercise(A_STR, FALSE);
+               if (!breathless(youmonst.data) || haseyes(youmonst.data))
+                   potionbreathe(obj);
+               useupall(obj);
+               useup(potion);
+               losehp((int)(amt + rnd(9)),     /* not physical damage */
+                      "alchemic blast", KILLED_BY_AN);
+               return 1;
+           }
 
-               obj->blessed = obj->cursed = obj->bknown = 0;
-               if (Blind || Hallucination) obj->dknown = 0;
-
-               if ((mixture = mixtype(obj, potion)) != 0) {
-                       obj->otyp = mixture;
-               } else {
-                   switch (obj->odiluted ? 1 : rnd(8)) {
-                       case 1:
-                               obj->otyp = POT_WATER;
-                               break;
-                       case 2:
-                       case 3:
-                               obj->otyp = POT_SICKNESS;
-                               break;
-                       case 4:
-                               {
-                                 struct obj *otmp;
-                                 otmp = mkobj(POTION_CLASS,FALSE);
-                                 obj->otyp = otmp->otyp;
-                                 obfree(otmp, (struct obj *)0);
-                               }
-                               break;
-                       default:
-                               if (!Blind)
-                         pline_The("mixture glows brightly and evaporates.");
-                               useup(obj);
-                               useup(potion);
-                               return(1);
-                   }
-               }
+           obj->blessed = obj->cursed = obj->bknown = 0;
+           if (Blind || Hallucination) obj->dknown = 0;
 
-               obj->odiluted = (obj->otyp != POT_WATER);
+           if ((mixture = mixtype(obj, potion)) != 0) {
+               obj->otyp = mixture;
+           } else {
+               switch (obj->odiluted ? 1 : rnd(8)) {
+               case 1:
+                   obj->otyp = POT_WATER;
+                   break;
+               case 2:
+               case 3:
+                   obj->otyp = POT_SICKNESS;
+                   break;
+               case 4:
+                 {
+                   struct obj *otmp = mkobj(POTION_CLASS, FALSE);
 
-               if (obj->otyp == POT_WATER && !Hallucination) {
-                       pline_The("mixture bubbles%s.",
-                               Blind ? "" : ", then clears");
-               } else if (!Blind) {
-                       pline_The("mixture looks %s.",
-                               hcolor(OBJ_DESCR(objects[obj->otyp])));
+                   obj->otyp = otmp->otyp;
+                   obfree(otmp, (struct obj *)0);
+                 }
+                   break;
+               default:
+                   useupall(obj);
+                   useup(potion);
+                   if (!Blind)
+                       pline_The("mixture glows brightly and evaporates.");
+                   return 1;
                }
+           }
+           obj->odiluted = (obj->otyp != POT_WATER);
 
-               useup(potion);
-               return(1);
+           if (obj->otyp == POT_WATER && !Hallucination) {
+               pline_The("mixture bubbles%s.", Blind ? "" : ", then clears");
+           } else if (!Blind) {
+               pline_The("mixture looks %s.",
+                         hcolor(OBJ_DESCR(objects[obj->otyp])));
+           }
+
+           useup(potion);
+           /* this is required when 'obj' was split off from a bigger stack,
+              so that 'obj' will now be assigned its own inventory slot;
+              it has a side-effect of merging 'obj' into another compatible
+              stack if there is one, so we do it even when no split has
+              been made in order to get the merge result for both cases;
+              as a consequence, mixing while Fumbling drops the mixture */
+           freeinv(obj);
+           (void) hold_another_object(obj, "You drop %s!", doname(obj),
+                                      (const char *)0);
+           return 1;
        }
 
 #ifdef INVISIBLE_OBJECTS