redo fix for issue #1003 - energy drain

The fix in commit 14d003c4ba prevented
current energy from ending up 1 point above maximum energy but it
didn't preserve the intent of splitting the drain with up to half
coming out of maximum and the remainder out of current.  This restores
that intent but now only does so when maximum is more than the full
drain amount rather than when it is more than the up-to-half portion,
becoming less harsh when hero's max energy is very low.  If current
is also very low then max energy will be reduced anyway, but by less.

Some unrelated formatting of invent.c has gotten mixed in.

Revises #1003
This commit is contained in:
PatR
2023-04-08 16:40:21 -07:00
parent b61aa235c7
commit bbd76562b0
5 changed files with 58 additions and 26 deletions

View File

@@ -1575,7 +1575,8 @@ getobj(
cntgiven = TRUE;
goto need_more_cq; /* now, get CMDQ_KEY */
} else {
cmdq_clear(CQ_CANNED); /* this should maybe clear the CQ_REPEAT too? */
cmdq_clear(CQ_CANNED);
/* should maybe clear the CQ_REPEAT too? */
return NULL;
}
}
@@ -4345,21 +4346,18 @@ look_here(
There("are %s%s objects here.",
(obj_cnt == 2) ? "two"
: (obj_cnt < 5) ? "a few"
: (obj_cnt < 10) ? "several"
: "many",
: (obj_cnt < 10) ? "several"
: "many",
picked_some ? " more" : "");
for (; otmp; otmp = otmp->nexthere)
if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
pline("%s %s%s.",
(obj_cnt > 1)
? "Including"
: (otmp->quan > 1L)
? "They're"
: "It's",
(obj_cnt > 1) ? "Including"
: (otmp->quan > 1L) ? "They're"
: "It's",
corpse_xname(otmp, (const char *) 0, CXN_ARTICLE),
poly_when_stoned(gy.youmonst.data)
? ""
: ", unfortunately");
poly_when_stoned(gy.youmonst.data) ? ""
: ", unfortunately");
feel_cockatrice(otmp, FALSE);
break;
}
@@ -5354,7 +5352,10 @@ worn_wield_only(struct obj *obj)
* MINV_ALL - display all inventory
*/
struct obj *
display_minventory(struct monst *mon, int dflags, char *title)
display_minventory(
struct monst *mon, /* monster whose minvent we're showing */
int dflags, /* control over what to display */
char *title) /* menu title */
{
struct obj *ret;
char tmp[QBUFSZ];
@@ -5362,7 +5363,8 @@ display_minventory(struct monst *mon, int dflags, char *title)
menu_item *selected = 0;
int do_all = (dflags & MINV_ALL) != 0,
incl_hero = (do_all && engulfing_u(mon)),
have_inv = (mon->minvent != 0), have_any = (have_inv || incl_hero),
have_inv = (mon->minvent != 0),
have_any = (have_inv || incl_hero),
pickings = (dflags & MINV_PICKMASK);
Sprintf(tmp, "%s %s:", s_suffix(noit_Monnam(mon)),
@@ -5383,7 +5385,7 @@ display_minventory(struct monst *mon, int dflags, char *title)
iflags.suppress_price--;
/* was 'set_uasmon();' but that potentially has side-effects */
gy.youmonst.data = &mons[u.umonnum]; /* most basic part of set_uasmon */
gy.youmonst.data = &mons[u.umonnum]; /* basic part of set_uasmon() */
} else {
invdisp_nothing(title ? title : tmp, "(none)");
n = 0;

View File

@@ -1406,7 +1406,7 @@ gulpmu(struct monst *mtmp, struct attack *mattk)
case AD_DREN:
/* AC magic cancellation doesn't help when engulfed */
if (!mtmp->mcan && rn2(4)) /* 75% chance */
drain_en(tmp);
drain_en(tmp, FALSE);
tmp = 0;
break;
default:

View File

@@ -2115,8 +2115,8 @@ trapeffect_anti_magic(
unsigned int trflags UNUSED)
{
if (mtmp == &gy.youmonst) {
int drain = d(2, 6); /* 2d6 => 2..12 */
int halfd = rnd((drain + 1) / 2); /* 1..drain/2 (rounded up) */
int drain, halfd;
boolean exclaim_it = FALSE;
seetrap(trap);
if (Antimagic) {
@@ -2149,11 +2149,24 @@ trapeffect_anti_magic(
losehp(dmgval2, "anti-magic implosion", KILLED_BY_AN);
}
if (u.uenmax > halfd) {
/* if the drain amount is more than hero's maximum energy then up
to half of the amount comes directly out of maximum, the rest
comes out of current energy; drain_en() lowers the current
amount and when doing so it will take even more from maximum
if the new current value would drop below zero */
drain = d(2, 6); /* 2d6 => 2..12 */
halfd = rnd(drain / 2); /* 1..drain/2 (round down) */
if (u.uenmax > drain) { /* [was u.uenmax > halfd] */
/* note: since 'halfd' is no more than half, 'drain -= halfd'
is at least as big, so drain_en() is never asked to remove
less from current than what we're removing from maximum;
however, it might do that anyway (via its throttle check) so
it needs to make sure uen doesn't end up exceeding uenmax */
u.uenmax -= halfd; /* drain_en() will set context.botl */
drain = halfd;
drain -= halfd;
exclaim_it = TRUE;
}
drain_en(drain);
drain_en(drain, exclaim_it);
} else {
boolean trapkilled = FALSE;
boolean in_sight = canseemon(mtmp) || (mtmp == u.usteed);
@@ -4598,31 +4611,48 @@ drown(void)
}
void
drain_en(int n)
drain_en(int n, boolean max_already_drained)
{
const char *mesg;
char punct = max_already_drained ? '!' : '.';
/*
* FIXME?
* u.uenmax should probably have a higher mininum than 0;
* perhaps u.ulevel or (u.ulevel + 1) / 2
*/
if (!u.uenmax) {
if (u.uenmax < 1) {
/* energy is completely gone */
You_feel("momentarily lethargic.");
if (u.uen || u.uenmax) { /* paranoia */
u.uen = u.uenmax = 0;
gc.context.botl = TRUE;
}
mesg = "momentarily lethargic";
} else {
/* throttle further loss a bit when there's not much left to lose */
if (n > (u.uen + u.uenmax) / 3)
n = rnd(n);
You_feel("your magical energy drain away%c", (n > u.uen) ? '!' : '.');
mesg = "your magical energy drain away";
if (n > u.uen)
punct = '!';
u.uen -= n;
if (u.uen < 0) {
u.uenmax -= rnd(-u.uen);
if (u.uenmax < 0)
u.uenmax = 0;
u.uen = 0;
} else if (u.uen > u.uenmax) {
/* uen might be greater than uenmax if caller reduced uenmax
and then we throttled the loss being applied to current */
u.uen = u.uenmax;
}
gc.context.botl = TRUE;
}
/* after manipulating u.uen,uenmax and setting context.botl, so
that You_feel() -> pline() will update status before the message */
You_feel("%s%c", mesg, punct);
}
/* the #untrap command - disarm a trap */

View File

@@ -2224,7 +2224,7 @@ mhitm_ad_dren(
/* mhitu */
hitmsg(magr, mattk);
if (!negated && !rn2(4)) /* 25% chance */
drain_en(mhm->damage);
drain_en(mhm->damage, FALSE);
mhm->damage = 0;
} else {
/* mhitm */