HP and Pw multiplication (trunk only)
Fix the problem pointed out by <email deleted>
where polymorphing into a new man at level 1 could be used to approximately
double or triple your hit points and spell power. With means to drain
level back down to 1 and with amulets of life saving to survive those times
you lose levels instead of gain, you could do this repeatedly and end up
with HP and Pw values in the millions.
This uses the earlier patch that records the HP and Pw increments from
level gains. Now when polymorphing into a new man, level based HP and Pw
are removed from the current values, remainder get multiplied by 80%, 90%,
100%, or 110% (average 95%, so tend to drop slightly), then a brand new set
of level gain increments (reflecting new man's Con and Wis) are added in.
Code for calculating spell energy is moved from pluslvl() and u_init()
into new routine newpw(). It and newhp() take over responsibility for
remembering the level based increments from pluslvl() which didn't deal
with the initial amount (stored in slot [0]; earlier patch didn't need it).
This commit is contained in:
@@ -85,6 +85,7 @@ various actions--such as enchanting--performed on an unpaid shop object
|
||||
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
|
||||
|
||||
@@ -620,6 +620,7 @@ E void FDECL(make_grave, (int,int,const char *));
|
||||
|
||||
/* ### 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 *));
|
||||
|
||||
49
src/attrib.c
49
src/attrib.c
@@ -1,4 +1,4 @@
|
||||
/* 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. */
|
||||
|
||||
@@ -789,40 +789,39 @@ newhp()
|
||||
{
|
||||
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
|
||||
|
||||
43
src/exper.c
43
src/exper.c
@@ -1,4 +1,4 @@
|
||||
/* 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. */
|
||||
|
||||
@@ -36,6 +36,32 @@ int en;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
@@ -184,7 +210,7 @@ void
|
||||
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.");
|
||||
|
||||
@@ -200,23 +226,12 @@ boolean incr; /* true iff via incremental experience growth */
|
||||
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);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* 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. */
|
||||
|
||||
@@ -136,24 +136,23 @@ change_sex()
|
||||
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();
|
||||
|
||||
@@ -163,41 +162,49 @@ newman()
|
||||
/* 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
|
||||
|
||||
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
|
||||
|
||||
/* set up new attribute points (particularly Con) */
|
||||
redist_attr();
|
||||
|
||||
/*
|
||||
* 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?] */
|
||||
|
||||
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.");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* 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. */
|
||||
|
||||
@@ -566,12 +566,7 @@ u_init()
|
||||
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user