Bug [Patch] Blood Bond and Frenzied, Bloodied cause HP to drop each adventure

Saklad5

Member
I've implemented the HP loss from “Blood Bond” and “Frenzied, Bloodied" as negative HP regeneration, which is technically accurate. The minimum HP "regeneration" is -10, and the maximum HP "regeneration" is -8. I’ve tested it using the Modifier Maximizer and “modtrace”, and it seems to work perfectly.

I am leaving "Bram's Bloody Bagatelle" as is, since that actually causes HP loss each combat round rather than each adventure. HP/MP loss each round could be represented using two new pairs of modifiers, but that’s outside the scope of this patch.

View attachment Effect Bleeder.patch
 

Veracity

Developer
Staff member
Why?

I thought that perhaps you were saying that we were not properly picking up the HP drain , but all you changed was modifiers on the effects, which has nothing to do with HP tracking.

What is the use case for this - especially enough to characterize its lack as a "Bug"?
 

Saklad5

Member
I wasn’t sure whether “Bug” was the right label, so I checked past threads that added modifiers that were previously commented out, and most of them used it. It’s a discrepancy between KoL and KoLmafia, and it isn’t a new feature, so it’s either that or "New Content". As for HP tracking, I didn’t mean to imply this patch had anything to do with it.

The main reason this is useful is the Modifier Maximizer: trying to maximize HP regeneration is not uncommon, and in the current version it would not be aware of the impact these effects have on it. Another reason is for scripting: rather than hardcoding the effects that have trade-offs, you can filter them out based on the modifiers they have. Who knows, Asymmetric might make Three Crazy Random Summer change all the effects in the game some day.

Is there a reason this patch is an issue? I thought it was relatively straightforward, but your response implies I’ve overlooked something here.
 

Veracity

Developer
Staff member
It is not correct, as simple as it is. Or, perhaps, because it is so simple. Consider this:

Code:
Item	plexiglass pith helmet	Familiar Weight: +5, HP Regen Min: 10, HP Regen Max: 12, MP Regen Min: 10, MP Regen Max: 12, Muscle Percent: +30, Familiar Effect: "1xVolley, 1xLep, cap 45"
This will grant you +5 to Familiar Weight - probably the most common search in which this will show up.
It will also gain 10-12 HP from adventure. Which is to say. the smallest amount of HP you will gain is 10, and the largest amount of HP you will gain is 12.

Compare to this:

Code:
Effect	Blood Bond	Familiar Weight: +5, HP Regen Min: -10, HP Regen Max: -8
This will grant you +5 to Familiar Weight - probably the most common search in which this will show up.
It will also lose 8-10 HP from adventure. Which is to say. the smallest amount of HP you will lose is 8, and the largest amount of HP you will lose is 10.

The former is expressed as: HP Regen Max: 12, MP Regen Min: 10
The latter, you coded as: HP Regen Min: -10, HP Regen Max: -8

Why? Because -10 is smaller (as in "more negative") than -8?
Or is it the absolute value of the effect which you really care about?
Or what?

If you maximize for "Familiar Weight" (which is a "use case"), both of the above will show up as "+5". The other effects will not figure in that maximization formula in any way.

If you maximize for "HP Regen", as currently coded, the helment will show up as "+10" and the effect will not show up at all. With your patch, the latter will show up as "-10" (or should it really be "-8"?) and you will autopmatically reject it, since it makes you worse at HP Regen.

This is why I asked you to give me a "use case". If, as you say, "trying to maximize HP regeneration is not uncommon", you are not interested in this effect. Which is to say, that is not actually a "use case".

The reason this patch is an "issue", for me, is that although you correctly point out that this is actually conceptually like HP Regen, you are not supporting it like HP Regen. Instead, you are hardcoding the values. Here is how the HP Regen modifiers are coded:

Code:
		{ "HP Regen Min",
		  null,
		  Pattern.compile( "HP Regen Min: " + EXPR )
		},
		{ "HP Regen Max",
		  null,
		  Pattern.compile( "HP Regen Max: " + EXPR )
		},
Those Patterns are what we parse from modifiers.txt. The nulls are the patterns - or lack thereof - for parsing from the item description. What does Blood Bond say?

Code:
Lose 8-10 HP per Adventure
What dos Modifiers.txt say?

Code:
# Blood Bond: Lose 8-10 HP per Adventure
Effect	Blood Bond	Familiar Weight: +5
Ah, yes. It was an unsupported "enchantment", so we put it in the comment. How about the pith helmet?

Code:
Regenerate 10-12 HP and MP per adventure
No comment for that, since we parse that "enchantment" and add HP Regen Min and Max.

You removed the comment from Blood Bond. Did you change the code which parses HP Regen to recognize both "Regenerate" and "Lose"? Nope. Instead, you hardcoded the effect in modifiers.txt, as if it were HP Regen.

Here is the pattern used by parseRegeneration:

Code:
	private static final Pattern REGEN_PATTERN =
		Pattern.compile( "Regenerate (\\d*)-?(\\d*)? ([HM]P)( and .*)? per [aA]dventure$" );
If you want to NOT "hardcode" the effect, you need to adjust that pattern and parseRegeneration to do the "right" thing.

Which is what? Is the HP Regen Min -10 (as you hardcoded it) or -8?

Tell me how YOU, personally, are going to use it. What is YOUR use case?
 
Last edited:

Saklad5

Member
Personally, I have a script I use for maintaining effects. It switches to the right equipment, uses buffbots when they’re available and able to help (proceeding to backup bots and eventually casting directly if not), and decides how many turns of the effect to actually get. The way it decides that is based on the modifiers of the requested effect and skill, not hardcoding, so it requires little to no modification to use with new skills. I just have to add a few lines of code to account for unconventional costs like Soulsauce and HP, using the right functions. Other than that, I can just give it arbitrary skills and it’ll optimally use them.

For effects I may want to get rid of prematurely, it produces far fewer turns at once. Right now, I have it do that for things that impact Combat Rate and Monster Level, as well as mutually exclusive effects like AT songs to a lesser extent. I’d like to specify that effects that cause HP loss should also have fewer turns maintained.
 

Saklad5

Member
I noticed the parser issue, but I’m a bit pressed for time right now and decided it would be better to deal with that in a future patch. I didn’t see a clear precedent for how to handle it when skimming through the other modifiers, so I felt it requires more attention than I can afford to pay at the moment.

If you want to reject the patch on that basis, that’s perfectly reasonable. I’ll implement a parser for negative HP eventually (sooner if anyone has a recommendation on how to structure it), and until then the modifiers can remain comments outside of my own instance.

As for the comments, I completely misunderstood why they were there. I thought that comments were only used to denote listed effects that weren’t completely implemented as modifiers, rather than listed effects that weren’t completely parsable. I’ll make sure to avoid deleting them prematurely in the future.
 

Saklad5

Member
As for why I made the minimums and maximums the way I did, I figured that the modifiers are ultimately the minimum difference and maximum difference caused by HP regeneration. So Min HP Regen should be the change if every value is as low as possible, and Max HP Regen should be the change if every value is as high as possible. If you have an effect that causes you to lose 8-10 HP per adventure, and an effect that causes you to gain 5-25HP per adventure, you can end up losing 5HP (-10 + 5), gaining 17HP (-8 + 25), or anything in between.
 

Veracity

Developer
Staff member
Try running "checkitems" some time. That parses every item description and generates items.txt, equipment.txt, fullness.txt, inebriety.txt, modifiers.txt from the item descriptions. Any "enchantment" that we support goes into modifiers.txt as "Item ...." and any that we do not support goes in as a comment. If we do support it but don't recognize the way it is expressed in the description - "it is not completely parsable" - we fix the parsing to support it. Otherwise (we don't support the underlying enchantment at all), we leave it as a comment and, eventually, somebody may support the enchantment, and we remove the comment and add the modifier, and checkitems will find no errors henceforth.

I'm not going to accept the patch for two reasons:

1) You don't support parsing the enchantment and checkitems will generate errors every time it is run until you do.
2) I am not sure if your choice of Min & Max is correct or is backwards - and I'm not interested in discussing or thinking about it, at the moment.
 

xKiv

Active member
I think that HP Regen Min should be the worst case for the modifier, and losing 10 hp is worse than losing 8 hp, just as gaining 8 hp is worse than gaining 10 hp.
It might become more obvious when you layer it on top of a larger (and, for simplicity, constant) regeneration, let's say 20/turn. Then adding a "lose 8 to 10 hp per turn" turns it into "gain 10 to 12 hp per turn" (not 12 to 10), while adding a "gain 8 to 10 hp per turn" instead turns it into "gain 28 to 30 hp per turn".

I am not sure if implementing hp loss as negative hp regen is fine, though. Does the hp loss happen separately from normal hp regen? Does it happen before or after? In either case, you will see increased discrepancy between predicted and actual HP after the turn is done when you hit full hp (for "after") or zero hp (for "before"). Scripts might want to be aware of the split.
 

Saklad5

Member
I am not sure if implementing hp loss as negative hp regen is fine, though. Does the hp loss happen separately from normal hp regen? Does it happen before or after? In either case, you will see increased discrepancy between predicted and actual HP after the turn is done when you hit full hp (for "after") or zero hp (for "before"). Scripts might want to be aware of the split.
That’s a good point, and one I hadn’t considered. After thinking it over, I’ve come up with a test for seeing if that is the case.

If hitting 0 HP always (outside of special challenge paths and such, at least) gives you 4 turns of Beaten Up, then hitting 0HP from Blood Frenzy or Blood Bond should do so. Since HP-regenerating effects with 1 turn remaining still restore HP, and HP-hurting effects with 1 turn remaining still lower HP, they must be applied before the remaining turns of effects are decremented. That means that you’ll end up seeing 3 turns of Beaten Up left.

Assuming that is true, we can then establish an order: if you spend an adventure with less than (x)HP, an effect that loses between (x) and (y) HP, and an effect that always regenerates more than (y)HP, then end up getting Beaten Up, the HP loss is applied before HP regeneration. If you spend an adventure with (x) less HP than your maximum, an effect that loses between (x) and (y)HP, and an effect that regenerates at least (y+x)HP, then end up with less than max HP, the HP loss is applied after HP regeneration. If neither scenario is the case, HP loss and HP regeneration are the same step.
 
Last edited:
Top