AC and obj->spe limits: +127/-128 -> +99/-99

Cap overall AC at -99 instead of -128.  Put the same limit of 99
on enchantment and charge count of individual objects.

^X now reports if/when AC has reached its limit since players
could see that reaching that limit and then enchanting worn items
will change the worn items but not the total.  (Same thing would
have happened with -128, just without any explanation and less
likely to accomplish.)

Won't affect normal play for any reasonable definition of normal.
This commit is contained in:
PatR
2020-12-21 14:09:17 -08:00
parent 1c7420af7f
commit ae23330adc
8 changed files with 103 additions and 43 deletions

View File

@@ -2213,19 +2213,26 @@ find_ac()
uac -= u.ublessed;
uac -= u.uspellprot;
/* [The magic binary numbers 127 and -128 should be replaced with the
* mystic decimal numbers 99 and -99 which require no explanation to
* the uninitiated and would cap the width of a status line value at
* one less character.]
*/
if (uac < -128)
uac = -128; /* u.uac is an schar */
else if (uac > 127)
uac = 127; /* for completeness */
/* put a cap on armor class [3.7: was +127,-128, now reduced to +/- 99 */
if (abs(uac) > AC_MAX)
uac = sgn(uac) * AC_MAX;
if (uac != u.uac) {
u.uac = uac;
g.context.botl = 1;
#if 0
/* these could conceivably be achieved out of order (by being near
threshold and putting on +N dragon scale mail from bones, for
instance), but if that happens, that's the order it happened;
also, testing for these in the usual order would result in more
record_achievement() attempts and rejects for duplication */
if (u.uac <= -20)
record_achievement(ACH_AC_20);
else if (u.uac <= -10)
record_achievement(ACH_AC_10);
else if (u.uac <= 0)
record_achievement(ACH_AC_00);
#endif
}
}

View File

@@ -590,7 +590,11 @@ int final;
you_have(buf, "");
}
find_ac(); /* enforces AC_MAX cap */
Sprintf(buf, "%d", u.uac);
if (abs(u.uac) == AC_MAX)
Sprintf(eos(buf), ", the %s possible",
(u.uac < 0) ? "best" : "worst");
enl_msg("Your armor class ", "is ", "was ", buf, "");
/* gold; similar to doprgold(#seegold) but without shop billing info;

View File

@@ -3431,8 +3431,11 @@ struct _readobjnam_data *d;
{
if (strlen(d->bp) > 1 && (d->p = rindex(d->bp, '(')) != 0) {
boolean keeptrailingchars = TRUE;
int idx = 0;
d->p[(d->p > d->bp && d->p[-1] == ' ') ? -1 : 0] = '\0'; /*terminate bp */
if (d->p > d->bp && d->p[-1] == ' ')
idx = -1;
d->p[idx] = '\0'; /* terminate bp */
++d->p; /* advance past '(' */
if (!strncmpi(d->p, "lit)", 4)) {
d->islit = 1;
@@ -3478,8 +3481,9 @@ struct _readobjnam_data *d;
d->spesgn = -1; /* cheaters get what they deserve */
d->spe = abs(d->spe);
}
if (d->spe > SCHAR_LIM)
d->spe = SCHAR_LIM;
/* cap on obj->spe is independent of (and less than) SCHAR_LIM */
if (d->spe > SPE_LIM)
d->spe = SPE_LIM; /* slime mold uses d.ftype, so not affected */
if (d->rechrg < 0 || d->rechrg > 7)
d->rechrg = 7; /* recharge_limit */
}
@@ -4225,13 +4229,11 @@ struct obj *no_wish;
|| d.typ == ROCK || is_missile(d.otmp)))))
d.otmp->quan = (long) d.cnt;
if (d.oclass == VENOM_CLASS)
d.otmp->spe = 1;
if (d.spesgn == 0) {
/* spe not specifed; retain the randomly assigned value */
d.spe = d.otmp->spe;
} else if (wizard) {
; /* no alteration to spe */
; /* no restrictions except SPE_LIM */
} else if (d.oclass == ARMOR_CLASS || d.oclass == WEAPON_CLASS
|| is_weptool(d.otmp)
|| (d.oclass == RING_CLASS && objects[d.typ].oc_charged)) {
@@ -4240,7 +4242,8 @@ struct obj *no_wish;
if (d.spe > 2 && Luck < 0)
d.spesgn = -1;
} else {
if (d.oclass == WAND_CLASS) {
/* crystal ball cancels like a wand, to (n:-1) */
if (d.oclass == WAND_CLASS || d.typ == CRYSTAL_BALL) {
if (d.spe > 1 && d.spesgn == -1)
d.spe = 1;
} else {
@@ -4281,12 +4284,16 @@ struct obj *no_wish;
/* otmp->cobj already done in mksobj() */
break;
#ifdef MAIL_STRUCTURES
/* scroll of mail: 0: delivered in-game via external event (or randomly
for fake mail); 1: from bones or wishing; 2: written with marker */
case SCR_MAIL:
/* 0: delivered in-game via external event (or randomly for fake mail);
1: from bones or wishing; 2: written with marker */
/*FALLTHRU*/
#endif
/* splash of venom: 0: normal, and transitory; 1: wishing */
case ACID_VENOM:
case BLINDING_VENOM:
d.otmp->spe = 1;
break;
#endif
case WAN_WISHING:
if (!wizard) {
d.otmp->spe = (rn2(10) ? -1 : 0);

View File

@@ -17,6 +17,7 @@ static NEARDATA const char readable[] = { ALL_CLASSES, SCROLL_CLASS,
static const char all_count[] = { ALLOW_COUNT, ALL_CLASSES, 0 };
static boolean FDECL(learnscrolltyp, (SHORT_P));
static void FDECL(cap_spe, (struct obj *));
static char *FDECL(erode_obj_text, (struct obj *, char *));
static void FDECL(stripspe, (struct obj *));
static void FDECL(p_glow1, (struct obj *));
@@ -54,6 +55,17 @@ struct obj *sobj;
(void) learnscrolltyp(sobj->otyp);
}
/* max spe is +99, min is -99 */
static void
cap_spe(obj)
struct obj *obj;
{
if (obj) {
if (abs(obj->spe) > SPE_LIM)
obj->spe = sgn(obj->spe) * SPE_LIM;
}
}
static char *
erode_obj_text(otmp, buf)
struct obj *otmp;
@@ -679,11 +691,10 @@ int curse_bless;
case MAGIC_MARKER:
case TINNING_KIT:
case EXPENSIVE_CAMERA:
if (is_cursed)
if (is_cursed) {
stripspe(obj);
else if (rechrg
&& obj->otyp
== MAGIC_MARKER) { /* previously recharged */
} else if (rechrg && obj->otyp == MAGIC_MARKER) {
/* previously recharged */
obj->recharged = 1; /* override increment done above */
if (obj->spe < 3)
Your("marker seems permanently dried out.");
@@ -709,8 +720,9 @@ int curse_bless;
obj->spe = 50;
else {
int chrg = (int) obj->spe;
if ((chrg + n) > 127)
obj->spe = 127;
if (chrg + n > SPE_LIM)
obj->spe = SPE_LIM;
else
obj->spe += n;
}
@@ -824,9 +836,12 @@ int curse_bless;
} /* switch */
} else {
not_chargable:
not_chargable:
You("have a feeling of loss.");
}
/* prevent enchantment from getting out of range */
cap_spe(obj);
}
/*
@@ -1039,6 +1054,7 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
otmp->otyp += GRAY_DRAGON_SCALE_MAIL - GRAY_DRAGON_SCALES;
if (sblessed) {
otmp->spe++;
cap_spe(otmp);
if (!otmp->blessed)
bless(otmp);
} else if (otmp->cursed)
@@ -1050,7 +1066,7 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
break;
}
pline("%s %s%s%s%s for a %s.", Yname2(otmp),
s == 0 ? "violently " : "",
(s == 0) ? "violently " : "",
otense(otmp, Blind ? "vibrate" : "glow"),
(!Blind && !same_color) ? " " : "",
(Blind || same_color)
@@ -1067,8 +1083,15 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
else if (!scursed && otmp->cursed)
uncurse(otmp);
if (s) {
int oldspe = otmp->spe;
/* despite being schar, it shouldn't be possible for spe to wrap
here because it has been capped at 99 and s is quite small;
however, might need to change s if it takes spe past 99 */
otmp->spe += s;
adj_abon(otmp, s);
cap_spe(otmp); /* make sure that it doesn't exceed SPE_LIM */
s = otmp->spe - oldspe; /* cap_spe() might have throttled 's' */
if (s) /* skip if it got changed to 0 */
adj_abon(otmp, s); /* adjust armor bonus for Dex or Int+Wis */
g.known = otmp->known;
/* update shop bill to reflect new higher price */
if (s > 0 && otmp->unpaid)
@@ -1331,6 +1354,8 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
: sblessed ? rnd(3 - uwep->spe / 3)
: 1))
sobj = 0; /* nothing enchanted: strange_feeling -> useup */
if (uwep)
cap_spe(uwep);
break;
case SCR_TAMING:
case SPE_CHARM_MONSTER: {

View File

@@ -472,6 +472,9 @@ register struct monst *mon;
/* since ARM_BONUS is positive, subtracting it increases AC */
}
}
/* same cap as for hero [find_ac(do_wear.c)] */
if (abs(base) > AC_MAX)
base = sgn(base) * AC_MAX;
return base;
}