increase the current bill (when its value is raised)
adjust health threshold where wounded hero will be healed by successful prayer
prevent lose-level+regain-level cycle from arbritrarily boosting HP and Pw
+prevent polymorphing into "new man" at low level from magnifying HP and Pw
Platform- and/or Interface-Specific Fixes
/* ### exper.c ### */
+E int NDECL(newpw);
E int FDECL(experience, (struct monst *,int));
E void FDECL(more_experienced, (int,int));
E void FDECL(losexp, (const char *));
-/* SCCS Id: @(#)attrib.c 3.5 2003/11/26 */
+/* SCCS Id: @(#)attrib.c 3.5 2005/09/19 */
/* Copyright 1988, 1989, 1990, 1992, M. Stephenson */
/* NetHack may be freely redistributed. See license for details. */
{
int hp, conplus;
-
if (u.ulevel == 0) {
/* Initialize hit points */
hp = urole.hpadv.infix + urace.hpadv.infix;
if (urole.hpadv.inrnd > 0) hp += rnd(urole.hpadv.inrnd);
if (urace.hpadv.inrnd > 0) hp += rnd(urace.hpadv.inrnd);
-
- /* Initialize alignment stuff */
- u.ualign.type = aligns[flags.initalign].value;
- u.ualign.record = urole.initrecord;
-
- return hp;
+ if (moves <= 1L) { /* initial hero; skip for polyself to new man */
+ /* Initialize alignment stuff */
+ u.ualign.type = aligns[flags.initalign].value;
+ u.ualign.record = urole.initrecord;
+ }
+ /* no Con adjustment for initial hit points */
} else {
if (u.ulevel < urole.xlev) {
- hp = urole.hpadv.lofix + urace.hpadv.lofix;
- if (urole.hpadv.lornd > 0) hp += rnd(urole.hpadv.lornd);
- if (urace.hpadv.lornd > 0) hp += rnd(urace.hpadv.lornd);
+ hp = urole.hpadv.lofix + urace.hpadv.lofix;
+ if (urole.hpadv.lornd > 0) hp += rnd(urole.hpadv.lornd);
+ if (urace.hpadv.lornd > 0) hp += rnd(urace.hpadv.lornd);
} else {
- hp = urole.hpadv.hifix + urace.hpadv.hifix;
- if (urole.hpadv.hirnd > 0) hp += rnd(urole.hpadv.hirnd);
- if (urace.hpadv.hirnd > 0) hp += rnd(urace.hpadv.hirnd);
+ hp = urole.hpadv.hifix + urace.hpadv.hifix;
+ if (urole.hpadv.hirnd > 0) hp += rnd(urole.hpadv.hirnd);
+ if (urace.hpadv.hirnd > 0) hp += rnd(urace.hpadv.hirnd);
}
+ if (ACURR(A_CON) <= 3) conplus = -2;
+ else if (ACURR(A_CON) <= 6) conplus = -1;
+ else if (ACURR(A_CON) <= 14) conplus = 0;
+ else if (ACURR(A_CON) <= 16) conplus = 1;
+ else if (ACURR(A_CON) == 17) conplus = 2;
+ else if (ACURR(A_CON) == 18) conplus = 3;
+ else conplus = 4;
+ hp += conplus;
}
-
- if (ACURR(A_CON) <= 3) conplus = -2;
- else if (ACURR(A_CON) <= 6) conplus = -1;
- else if (ACURR(A_CON) <= 14) conplus = 0;
- else if (ACURR(A_CON) <= 16) conplus = 1;
- else if (ACURR(A_CON) == 17) conplus = 2;
- else if (ACURR(A_CON) == 18) conplus = 3;
- else conplus = 4;
-
- hp += conplus;
- return((hp <= 0) ? 1 : hp);
+ if (hp <= 0) hp = 1;
+ if (u.ulevel < MAXULEV) u.uhpinc[u.ulevel] = (xchar)hp;
+ return hp;
}
schar
-/* SCCS Id: @(#)exper.c 3.5 2005/09/12 */
+/* SCCS Id: @(#)exper.c 3.5 2005/09/19 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
}
}
+/* calculate spell power/energy points for new level */
+int
+newpw()
+{
+ int en = 0, enrnd, enfix;
+
+ if (u.ulevel == 0) {
+ en = urole.enadv.infix + urace.enadv.infix;
+ if (urole.enadv.inrnd > 0) en += rnd(urole.enadv.inrnd);
+ if (urace.enadv.inrnd > 0) en += rnd(urace.enadv.inrnd);
+ } else {
+ enrnd = (int)ACURR(A_WIS) / 2;
+ if (u.ulevel < urole.xlev) {
+ enrnd += urole.enadv.lornd + urace.enadv.lornd;
+ enfix = urole.enadv.lofix + urace.enadv.lofix;
+ } else {
+ enrnd += urole.enadv.hirnd + urace.enadv.hirnd;
+ enfix = urole.enadv.hifix + urace.enadv.hifix;
+ }
+ en = enermod(rn1(enrnd, enfix));
+ }
+ if (en <= 0) en = 1;
+ if (u.ulevel < MAXULEV) u.ueninc[u.ulevel] = (xchar)en;
+ return en;
+}
+
int
experience(mtmp, nk) /* return # of exp points for mtmp after nk killed */
register struct monst *mtmp;
pluslvl(incr)
boolean incr; /* true iff via incremental experience growth */
{ /* (false for potion of gain level) */
- int hpinc, eninc, enrnd, enfix;
+ int hpinc, eninc;
if (!incr) You_feel("more experienced.");
u.uhp += hpinc;
/* increase spell power/energy points */
- enrnd = (int)ACURR(A_WIS) / 2;
- if (u.ulevel < urole.xlev) {
- enrnd += urole.enadv.lornd + urace.enadv.lornd;
- enfix = urole.enadv.lofix + urace.enadv.lofix;
- } else {
- enrnd += urole.enadv.hirnd + urace.enadv.hirnd;
- enfix = urole.enadv.hifix + urace.enadv.hifix;
- }
- eninc = enermod(rn1(enrnd, enfix)); /* M. Stephenson */
+ eninc = newpw();
u.uenmax += eninc;
u.uen += eninc;
/* increase level (unless already maxxed) */
if (u.ulevel < MAXULEV) {
- /* remember hp and pw/en gains in case this level is later lost */
- u.uhpinc[u.ulevel] = (xchar) hpinc;
- u.ueninc[u.ulevel] = (xchar) eninc;
/* increase experience points to reflect new level */
if (incr) {
long tmp = newuexp(u.ulevel + 1);
-/* SCCS Id: @(#)polyself.c 3.5 2005/06/21 */
+/* SCCS Id: @(#)polyself.c 3.5 2005/09/19 */
/* Copyright (C) 1987, 1988, 1989 by Ken Arromdee */
/* NetHack may be freely redistributed. See license for details. */
STATIC_OVL void
newman()
{
- int tmp, oldlvl;
+ int i, oldlvl, newlvl, hpmax, enmax;
- tmp = u.uhpmax;
oldlvl = u.ulevel;
- u.ulevel = u.ulevel + rn1(5, -2);
- if (u.ulevel > 127 || u.ulevel < 1) { /* level went below 0? */
- u.ulevel = oldlvl; /* restore old level in case they lifesave */
- goto dead;
+ newlvl = oldlvl + rn1(5, -2); /* new = old + {-2,-1,0,+1,+2} */
+ if (newlvl > 127 || newlvl < 1) { /* level went below 0? */
+ goto dead; /* old level is still intact (in case of lifesaving) */
}
- if (u.ulevel > MAXULEV) u.ulevel = MAXULEV;
+ if (newlvl > MAXULEV) newlvl = MAXULEV;
/* If your level goes down, your peak level goes down by
the same amount so that you can't simply use blessed
full healing to undo the decrease. But if your level
goes up, your peak level does *not* undergo the same
adjustment; you might end up losing out on the chance
to regain some levels previously lost to other causes. */
- if (u.ulevel < oldlvl) u.ulevelmax -= (oldlvl - u.ulevel);
- if (u.ulevelmax < u.ulevel) u.ulevelmax = u.ulevel;
+ if (newlvl < oldlvl) u.ulevelmax -= (oldlvl - newlvl);
+ if (u.ulevelmax < newlvl) u.ulevelmax = newlvl;
+ u.ulevel = newlvl;
if (!rn2(10)) change_sex();
/* random experience points for the new experience level */
u.uexp = rndexp(FALSE);
- /* u.uhpmax * u.ulevel / oldlvl: proportionate hit points to new level
- * -10 and +10: don't apply proportionate HP to 10 of a starting
- * character's hit points (since a starting character's hit points
- * are not on the same scale with hit points obtained through level
- * gain)
- * 9 - rn2(19): random change of -9 to +9 hit points
- */
-#ifndef LINT
- u.uhpmax = ((u.uhpmax - 10) * (long)u.ulevel / oldlvl + 10) +
- (9 - rn2(19));
-#endif
-
-#ifdef LINT
- u.uhp = u.uhp + tmp;
-#else
- u.uhp = u.uhp * (long)u.uhpmax/tmp;
-#endif
+ /* set up new attribute points (particularly Con) */
+ redist_attr();
- tmp = u.uenmax;
-#ifndef LINT
- u.uenmax = u.uenmax * (long)u.ulevel / oldlvl + 9 - rn2(19);
-#endif
- if (u.uenmax < 0) u.uenmax = 0;
-#ifndef LINT
- u.uen = (tmp ? u.uen * (long)u.uenmax / tmp : u.uenmax);
-#endif
+ /*
+ * New hit points:
+ * remove level-gain based HP from any extra HP accumulated
+ * (the "extra" might actually be negative);
+ * modify the extra, retaining {80%, 90%, 100%, or 110%};
+ * add in newly generated set of level-gain HP.
+ * (This used to calculate new HP in direct proportion to old HP,
+ * but that was subject to abuse: accumulate a large amount of
+ * extra HP, drain level down to 1, then polyself to level 2 or 3
+ * [lifesaving capability needed to handle level 0 and -1 cases]
+ * and the extra got multiplied by 2 or 3. Repeat the level
+ * drain and polyself steps until out of lifesaving capability.)
+ */
+ hpmax = u.uhpmax;
+ for (i = 0; i < oldlvl; i++) hpmax -= (int)u.uhpinc[i];
+ /* hpmax * rn1(4,8) / 10; 0.95*hpmax on average */
+ hpmax = rounddiv((long)hpmax * (long)rn1(4, 8), 10);
+ for (i = 0; (u.ulevel = i) < newlvl; i++) hpmax += newhp();
+ if (hpmax < u.ulevel) hpmax = u.ulevel; /* min of 1 HP per level */
+ /* retain same proportion for current HP; u.uhp * hpmax / u.uhpmax */
+ u.uhp = rounddiv((long)u.uhp * (long)hpmax, u.uhpmax);
+ u.uhpmax = hpmax;
+ /*
+ * Do the same for spell power.
+ */
+ enmax = u.uenmax;
+ for (i = 0; i < oldlvl; i++) enmax -= (int)u.ueninc[i];
+ enmax = rounddiv((long)enmax * (long)rn1(4, 8), 10);
+ for (i = 0; (u.ulevel = i) < newlvl; i++) enmax += newpw();
+ if (enmax < u.ulevel) enmax = u.ulevel;
+ u.uen = rounddiv((long)u.uen * (long)enmax, u.uenmax);
+ u.uenmax = enmax;
+ /* [should alignment record be tweaked too?] */
- redist_attr();
u.uhunger = rn1(500,500);
if (Sick) make_sick(0L, (char *) 0, FALSE, SICK_ALL);
if (Stoned) make_stoned(0L, (char *)0, 0, (char *)0);
- if (u.uhp <= 0 || u.uhpmax <= 0) {
+ if (u.uhp <= 0) {
if (Polymorph_control) {
if (u.uhp <= 0) u.uhp = 1;
- if (u.uhpmax <= 0) u.uhpmax = 1;
} else {
dead: /* we come directly here if their experience level went to 0 or less */
Your("new form doesn't seem healthy enough to survive.");
-/* SCCS Id: @(#)u_init.c 3.5 2002/10/22 */
+/* SCCS Id: @(#)u_init.c 3.5 2005/09/19 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
u.ulevel = 0; /* set up some of the initial attributes */
u.uhp = u.uhpmax = newhp();
- u.uenmax = urole.enadv.infix + urace.enadv.infix;
- if (urole.enadv.inrnd > 0)
- u.uenmax += rnd(urole.enadv.inrnd);
- if (urace.enadv.inrnd > 0)
- u.uenmax += rnd(urace.enadv.inrnd);
- u.uen = u.uenmax;
+ u.uen = u.uenmax = newpw();
u.uspellprot = 0;
adjabil(0,1);
u.ulevel = u.ulevelmax = 1;