remaining resistance balance issues
Moderator: Forum Moderators
Having regained direct forum access, here is dr-1.11 with its analysis of the current aligned units.
The perl script dr (short for Damage Reporter) has full pod documentation, and it may be somewhat Unix/MacOSX specific but I'd be happy to modify it if Windows people can give me specific suggestions.
File dr.out contains the full damage tables for the game as it currently stands in 0.8.8, and dr-alt.out contains the damage tables with the modified DF calculations as discussed above. The changes are pretty trivial, but would fix some of the worst gameplay problems I've seen personally. If there is support for the principle, I'll post a suggested patch against CVS to Savannah.
It would be simple to tweak the code further to implement a "purist" additive bonus/multiplicative penalty, which does a fixed amount of additional damage for charging units, irrespective of the resistance of the defender. I'll leave that to the purists to check, personally I'm still forming an opinion as to charging/backstabbing units doing 225 vs 250% damage. A script like dr that generates comprehensive attack tables should help when discussing changes to the damage algorithm in the game. I certainly find it easier to use diff to compare the differences between dr.out and dr-alt.out than trying to stare at the game code, or making a modification and playing a couple of hundred games to get a feel for suggested changes.
The perl script dr (short for Damage Reporter) has full pod documentation, and it may be somewhat Unix/MacOSX specific but I'd be happy to modify it if Windows people can give me specific suggestions.
File dr.out contains the full damage tables for the game as it currently stands in 0.8.8, and dr-alt.out contains the damage tables with the modified DF calculations as discussed above. The changes are pretty trivial, but would fix some of the worst gameplay problems I've seen personally. If there is support for the principle, I'll post a suggested patch against CVS to Savannah.
It would be simple to tweak the code further to implement a "purist" additive bonus/multiplicative penalty, which does a fixed amount of additional damage for charging units, irrespective of the resistance of the defender. I'll leave that to the purists to check, personally I'm still forming an opinion as to charging/backstabbing units doing 225 vs 250% damage. A script like dr that generates comprehensive attack tables should help when discussing changes to the damage algorithm in the game. I certainly find it easier to use diff to compare the differences between dr.out and dr-alt.out than trying to stare at the game code, or making a modification and playing a couple of hundred games to get a feel for suggested changes.
- Attachments
-
- dr1-11.zip
- (46.39 KiB) Downloaded 393 times
-
- Posts: 873
- Joined: July 4th, 2004, 9:14 pm
- Location: My imagination
- Contact:
You're still wrong.ott wrote:It would be simple to tweak the code further to implement a "purist" additive bonus/multiplicative penalty, which does a fixed amount of additional damage for charging units, irrespective of the resistance of the defender.
10 damage attack
charge additional damage with no modifiers: 10
charge additional damage with defender resistance of 50%, "purist" calculation: 5
The calculation is, let me state again, (added bonuses and 100%) * (multiplied penalties). The penalties are multiplied by the bonuses. Multiplying the bonuses by each other or not does not change that. In fact, multiplying the bonus by 2 in this scheme can NEVER decrease the damage, only increase it.
If you think the scheme is (added bonuses) + (multiplied penalties), which you seem to, you're wrong. That may indeed have been the originally proposed scheme, but it is fundamentally flawed, as EP showed, and not what you implemented in your script.
Play a Silver Mage in the Wesvoid campaign.
I don't think that; my original dr-1.4 script was a faithful rendering of what the game currently does, which is additive.If you think the scheme is (added bonuses) + (multiplied penalties), which you seem to, you're wrong.
Please look at the code fragments I posted, from dr-1.11, which implements Darth Fool's additive-bonus TIMES multiplicative-penalty-factor. Bonuses are added, penalties are multiplied, then the whole lot is multiplied together. I currently do special case charge/backstab to avoid a huge change in calculated damages. If you don't like that then you could make a one line change (add 100 to $bonus instead of doubling it), rerun the script on the unit files you have lying around and see what you get. I'll add an option to do this when I get time.
-
- Posts: 873
- Joined: July 4th, 2004, 9:14 pm
- Location: My imagination
- Contact:
The change isn't that huge....ott wrote:I currently do special case charge/backstab to avoid a huge change in calculated damages.
Anyway here are the outlines of the possibilities, attempting to be unbiased:
- (0) Merely multiplying the bonus by 2 (before adding 100% to it) makes no sense. If there's no other bonus, which is normal, then charge would do nothing. This isn't a possibility, it's just something to avoid when programming.
(1) Multiplying the bonus by 2 and adding 100%, or equivalently multiplying it by 2 after adding the base 100% to it, is the same as multiplying the whole result by 2. If there are no other bonuses, this is the same as the new proposed scheme in its simplest form. If there is one or zero other bonus, it is the same as purely multiplicative damage calculations. The only time that the whole formula would ever have a result different from the multiplicative (less than, in particular) is when at least two of the following are true: it is being led, it is attacking a unit weak to its damage type, or it is a favorable time of day.
(2) Adding 100% to the bonuses section is equivalent to the previous possibility if there are no other bonuses. If there are other bonuses, it will do less damage (which decreases the damage range, on the whole, which I thought was good?).
(3) Adding 100% after everything else. This is how it was between 0.7.1 and 0.8.4. It means that it is not affected by resistances, which is probably why it was deservedly thrown out, although maybe not changed to a good alternative (at the time, the only alternative known was equivalent to (1), not (2), so naturally it became (1)).
[1] If whoever it was (Dave?) expressed an opinion of whether he thought that bonuses should still be additive, I would like that... or something else to resolve the controversy. Changing relevant but unnecessary things after so long seems odd, though. (version difference > .1, compared to how long it's been with the "new" charge calculations - we haven't even released a "stable" version since then)
Play a Silver Mage in the Wesvoid campaign.
Quite right. The differences only really become significant for units being led by a high-level unit (for instance, level 4 units in some of the custom campaigns), during its favourable time of day. Still, worth reviewing.Invisible Philosopher wrote:The change isn't that huge....
Aha. Please re-read my code. For the alternative (modified DF) scheme my code does not subtract 100 from the resistance modifier (which is usually 100 for 0% resistance, 200 for -100% resistance, 0 for 100% resistance). This gives the same result as the in-game code (before the recent CVS simplifications by Silene) which calculates a modifier by first subtracting 100 from the resistance modifier, then multiplies this by 2 and adds 100, and adds another 100% at the end (by adding the modifier to the original damage). That's why I wrote that you can change the multiplying by 2 to adding 100 if you don't like charge to double modifiers.(0) Merely multiplying the bonus by 2 (before adding 100% to it) makes no sense. If there's no other bonus, which is normal, then charge would do nothing.
Of course. My original post that started this thread, was to point out that the current additive model gives extremely crazy swings between good/bad times of day for aligned units, against high resistance opponents, even when unled. Swings of 1-3 during the day to 8-3 at night, for example.The only time that the whole formula would ever have a result different from the multiplicative (less than, in particular) is when at least two of the following are true: it is being led, it is attacking a unit weak to its damage type, or it is a favorable time of day.
My main concern so far has been not to open up a whole can of worms and trash the existing damage calculations, but to point out a specific flaw, and to seek ideas for improvement -- thankfully provided by Darth Fool and tweaked by everyone else contributing to this thread.
If we want to discuss redoing damage calculations, it would be useful to have input from someone who would be the one likely make the CVS commit: AFAIK that's probably Dave or Silene for this part of the code. Otherwise this is all just bluster.
Yes, this would be good. I recall Dave expressing dissatisfaction with the additive damage model a while back.[1] If whoever it was (Dave?) expressed an opinion of whether he thought that bonuses should still be additive, I would like that... or something else to resolve the controversy.
As promised, here is dr-1.12 with -p flag to do pure additive-bonus/multiplicative-penalty calculations. I've added file dr-pure.out to show the pure calculations. Every aligned unit I could find on my disk (this includes all the campaign server data) is covered, with one file listing unit damage tables for each of the three different calculation methods (0.8.8, alternative, pure). About 1MB of output, luckily it compresses well. Or you could just run the script yourself.
The existing damage model seems clearly problematic in some cases. We could go to an alternative additive/multiplicative model and keep charge as it is currently in 0.8.[4-8], which would iron out some of the worst corner cases without really affecting gameplay much in the general case. Or we could make more drastic changes, for instance to a pure additive/multiplicative model.
It's not my call. I'm merely supplying the data and the means for us to do further investigation, as my attempt to make a constructive contribution.
- Attachments
-
- dr1-12.zip
- (66.72 KiB) Downloaded 385 times
All right. I tweaked the calculations to round towards the baseline damage like the code currently does, eliminating a few funny cases (eg. a charging unit doing 17/20/25 night/dawn/day damage becomes a more sensible 15/20/25). Redid the damage tables, added more diagnostics and documentation, and made parsing more robust. dr now will happily accept to process every Wesnoth unit file on the disk.
Also did a patch against CVS to implement the pure additive bonus/multiplicative penalty method as relentlessly expounded by Invisible Philosopher based on Darth Fool's original idea.
The game feels a little less random, as would be expected from squishing day/night damage closer to the mean. I have not yet seen enough instances of charge/backstab to be able to comment on whether damage doubling ignoring resistance and bonuses is a good thing or not.
Any comments? Or am I the only one who thinks that 9-3 units doing 6-3 during the day and 1-3 at night is evidence that the current purely additive damage model needs to be tweaked?
Code: Select all
find / -wholename '*wesnoth/*.cfg' -print | xargs dr -vars
Also did a patch against CVS to implement the pure additive bonus/multiplicative penalty method as relentlessly expounded by Invisible Philosopher based on Darth Fool's original idea.
The game feels a little less random, as would be expected from squishing day/night damage closer to the mean. I have not yet seen enough instances of charge/backstab to be able to comment on whether damage doubling ignoring resistance and bonuses is a good thing or not.
Any comments? Or am I the only one who thinks that 9-3 units doing 6-3 during the day and 1-3 at night is evidence that the current purely additive damage model needs to be tweaked?
- Attachments
-
- dr1-16.zip
- (68.52 KiB) Downloaded 370 times
You're not, I always considered this very strange and sort of buggy. It doesn't feel right if the difference between dawn/dusk and night get's much higher then 25% or between day/night much higher then 50%. IMHO this even violates KISS as the damage is not in the expected region and it's somewhat hard to understand why from a users perspective.ott wrote: Any comments? Or am I the only one who thinks that 9-3 units doing 6-3 during the day and 1-3 at night is evidence that the current purely additive damage model needs to be tweaked?
Yeah, I too think that this difference is too drastic. I wondered about it a few times until I found out about purely additive damage model. I thought multiplicative was more logical and yielded better results.ott wrote: Any comments? Or am I the only one who thinks that 9-3 units doing 6-3 during the day and 1-3 at night is evidence that the current purely additive damage model needs to be tweaked?
Anyway, I think something has to be done to balance that better...
bxe Miq
Here is dr-1.17 with a new -q option to calculate damage additively but applying the resistance modifier last instead of first as is currently done. Thanks to miq for the idea. The file dr-rend.out has the damage tables for resistance-last.
This seems to fix the worst problems with the current damage model, and only seems to have one case which could be problematic.
To summarise, the case of high resistance enemies is fixed with this as well as the other two alternative schemes. The current damage model is seriously broken for high resistance defenders. This method fixes the huge day/night swings for aligned attackers against high resistance defenders that are seen in the current damage model; the two other alternative schemes also fix this problem.
A major advantage of resistance-last is that it is easy to explain (eg. in the "Show damage calculations" box). Damage is calculated by considering bonuses and penalties, adding them together, and then multiplying the damage by the result. The final damage is modified by any resistances or vulnerabilities a defender may have.
The resistance-last scheme doesn't suffer from the problem of the other two alternatives of 125%*75% ending up as 93.75% when people expect 100%.
I think mostly pluses, with only one negative, and a qualified one at that. The case of very low resistance is the only corner case for resistance-last, since it increases the already large damage even further.
The main practical demonstration of this is against undead in HttT, Valley of Death, if a Horseman gets one of the holy water bottles and is led by an Elvish Marshal or lvl 3 Konrad. The current method yields 49 damage, resistance-last yields 63.
I think this could be worked around, for instance by making undead -80% resistant to holy attacks instead of the current -100%. It does seem to be a specific, fairly narrow case that would have to be looked at as opposed to the many cases with the current damage model which are creating a push towards making all resistances similar.
Comments would be welcome, especially those based on the specifics of the script or the tables.
This seems to fix the worst problems with the current damage model, and only seems to have one case which could be problematic.
To summarise, the case of high resistance enemies is fixed with this as well as the other two alternative schemes. The current damage model is seriously broken for high resistance defenders. This method fixes the huge day/night swings for aligned attackers against high resistance defenders that are seen in the current damage model; the two other alternative schemes also fix this problem.
A major advantage of resistance-last is that it is easy to explain (eg. in the "Show damage calculations" box). Damage is calculated by considering bonuses and penalties, adding them together, and then multiplying the damage by the result. The final damage is modified by any resistances or vulnerabilities a defender may have.
The resistance-last scheme doesn't suffer from the problem of the other two alternatives of 125%*75% ending up as 93.75% when people expect 100%.
I think mostly pluses, with only one negative, and a qualified one at that. The case of very low resistance is the only corner case for resistance-last, since it increases the already large damage even further.
The main practical demonstration of this is against undead in HttT, Valley of Death, if a Horseman gets one of the holy water bottles and is led by an Elvish Marshal or lvl 3 Konrad. The current method yields 49 damage, resistance-last yields 63.
I think this could be worked around, for instance by making undead -80% resistant to holy attacks instead of the current -100%. It does seem to be a specific, fairly narrow case that would have to be looked at as opposed to the many cases with the current damage model which are creating a push towards making all resistances similar.
Comments would be welcome, especially those based on the specifics of the script or the tables.
- Attachments
-
- dr1-17.zip
- (91.16 KiB) Downloaded 346 times
-
- Posts: 873
- Joined: July 4th, 2004, 9:14 pm
- Location: My imagination
- Contact:
125% * 75% never happens in-game. I don't think that is so much of a problem, although it could be a tie-breaker if we have two otherwise equivalent solutions. EDIT: Wait... Leadership and bad time of day. It'll be considered near the end of my analysis here.ott wrote:The resistance-last scheme doesn't suffer from the problem of the other two alternatives of 125%*75% ending up as 93.75% when people expect 100%.
If I understood the suggestion correctly, it would mean that in the nighttime, a lone holy-watered horseman would do less damage than currently as well, because the nighttime would reduce the extra holy damage. This would increase the current damage range for low and high. It does not seem good to keep any restriction on resistances, whether they are highly resistant or very weak.ott wrote:I think mostly pluses, with only one negative, and a qualified one at that. The case of very low resistance is the only corner case for resistance-last, since it increases the already large damage even further.
The main practical demonstration of this is against undead in HttT, Valley of Death, if a Horseman gets one of the holy water bottles and is led by an Elvish Marshal or lvl 3 Konrad. The current method yields 49 damage, resistance-last yields 63.
I think this could be worked around, for instance by making undead -80% resistant to holy attacks instead of the current -100%. It does seem to be a specific, fairly narrow case that would have to be looked at as opposed to the many cases with the current damage model which are creating a push towards making all resistances similar.
I will start a chart of advantages and disadvantages of reasonable proposals. I would only mention being different from the current model if it seems so different that it would seriously unbalance the current scenarios (for [ridiculous] example, after adding up all bonuses and penalties, divide them by 2 before applying them). If a few current scenarios have been balanced for an unbalanced damage calculator, I do not think this is sufficient reason to keep it unbalanced. Wherever I say "Charge", it applies to backstab as well for conciseness.
Code: Select all
Description |High Damage| Low Damage |Other | Formula
| | | | B=bonus, p=penalty
--------------------+-----------+------------+-----------------------+--------------------------------
Pure multiplication | too much | good |Simple |dam*mod1*mod2...=dam*(1)*mod1...
--------------------+-----------+------------+-----------------------+--------------------------------
Pure addition | good | too little |Simple; unintuitive | dam*(1+mod1+mod2...)=
| | | Charge and resistance| dam+(dam*mod1)+(dam*mod2)...
--------------------+-----------+------------+-----------------------+--------------------------------
Pure bonus=add, | good | good |unintuitive Charge | dam*(1+B1+B2...)*(p1*p2...)=
penalty=multiply, | | | | (dam*p1*p2...)+
and then multiply | | | | (dam*B1*p1*p2...)+
boni and penalties| | | | (dam*B2*p1*p2...)...
--------------------+-----------+------------+-----------------------+--------------------------------
Mod of previous | okay* | good |*charge is marginal | dam*(1+(resist - 100% if B)
bad resist, good ToD, leadership=add | | +(ToD if B)+(leadership))*
everything else (including Charge)=multiply| | ((2 if charge)*P1*P2...)
--------------------+-----------+------------+-----------------------+--------------------------------
Additive except | okay* | good |*holy vs undead | dam*(1+mod1+mod2...)*
charge, steadfast, and all resistances, good or bad | ((2 if charge)*(.5:steadfast)
| | | | *resistance)
Every proposal can be formatted as
- damage*(1+additive things)*(multiplicative things)
- damage*multiplicative_things*1
+
damage*multiplicative_things*first additive mod
+
damage*multiplicative_things*second additive mod
...
If we use the distributed form, I think we can decide for each pair of effects, what the operation between them is, by deciding which multiplicative_things to include for each line, specific to what kind of additive mod it is. Seems too complicated to do if we can find a reasonable alternative.
Making more than one penalty additive makes damages too low.
Making any bonus multiplicative makes damages high, because that bonus will end up multiplied with other bonuses. As few bonuses as possible should be multiplicative.
Charge, if it is to keep the description of doubling damage, will be unintuitive unless it is multiplicative, contributing to high damage. My current opinion is that said high damage is acceptable.
Steadfast for the same reason should be multiplicative, but it does not suffer from high-damage problems because it reduces damage.
A summary of conclusions so far:
- additive: Leadership, defender weakness, good time of day
multiplicative: charge/backstab, steadfast
unknown: bad time of day, defender resistance
Let us analyze the effects of each decision:
- bad ToD=* ; resist=+
Bad time of day reduces extra damage from leadership and defenders with weaknesses. This causes the "125%*75%" problem.
- bad ToD=+ ; resist=+
An alternative to the previous that is a little better.
- bad ToD=+ ; resist=*
Resistances reduce damage from leadership and good time of day. Seems good: for (unlikely but helpful) example, if resistances are not multiplicative, a 75% resistant unit would take twice the damage in its opponent's favorable time of day. Units with alignments would on average do more damage against resistant enemies than units without alignments, and leadership would be similarly overpowered against them.
- additive: Leadership, defender weakness, good and bad time of day
multiplicative: defender resistance, charge/backstab, steadfast
Last edited by Invisible Philosopher on January 25th, 2005, 8:29 pm, edited 5 times in total.
Play a Silver Mage in the Wesvoid campaign.
- Elvish_Pillager
- Posts: 8137
- Joined: May 28th, 2004, 10:21 am
- Location: Everywhere you think, nowhere you can possibly imagine.
- Contact:
What about one level of leadership + bad alignment?Invisible Philosopher wrote:125% * 75% never happens in-game.
It's all fun and games until someone loses a lawsuit. Oh, and by the way, sending me private messages won't work. :/ If you must contact me, there's an e-mail address listed on the website in my profile.
I'm tending to think that the current system is okay. We just need to make sure that units don't get too good resistance against any attacks.
The main problem I have with pure multiplicative is that positives and negatives don't mesh together well: there's a bias toward the negatives to cause low damage. The very high potential damage with multiplicative isn't that big an issue imo.
David
The main problem I have with pure multiplicative is that positives and negatives don't mesh together well: there's a bias toward the negatives to cause low damage. The very high potential damage with multiplicative isn't that big an issue imo.
David
“At Gambling, the deadly sin is to mistake bad play for bad luck.” -- Ian Fleming
This seems to prove my point -- the current damage model is pushing all resistances to become similar, not too high, not too low, to avoid weird corner cases.Dave wrote:I'm tending to think that the current system is okay. We just need to make sure that units don't get too good resistance against any attacks.
To be very clear -- I like the current damage values, in at least 95% of cases. The problems are with aligned units fighting against high resistance defenders. Having written the TDH campaign walkthrough and most of the HttT one, I would like the current damage model to be tweaked, but in such a way as to leave alone those 95% of cases that are not problematic. I'm sure campaign authors would also prefer any changes to leave the bulk of damage values untouched!
Since people probably find it a chore to wade through over 1MB of damage tables between the four damage models, let's just work with a few illustrations.
With the current damage model, let's look at two different common defenders: a Ghost and a Troll, and let's look at some aligned units trying to attack these defenders, first at night then during the day. The important statistic to consider is swing in damage between day and night against each type of defender.
Code: Select all
Ghost Troll Day/night factors
Thief 5-3/1-3 8-3/4-3 5 vs 2
Orcish Grunt 6-2/1-2 9-2/5-2 6 vs 1.8
Mage 5-3/9-3 5-3/9-3 1.8 vs 1.8
Ancient Wose 4-2/16-2 19-2/31-2 4 vs 1.6
and is saying "but a factor 6 difference isn't 25%! 1.25/.75=1.67, not 6!".Lawful units get +25% damage in daytime, and -25% damage at night. Chaotic units get +25% damage at night, and -25% damage in daytime.
(Please note: if day/night damage always swung in a consistent manner between different opponents, I would have no problem with swings, even of 10 or more. I am arguing here that the problem is the inconsistency between different opponents: the Grunt's damage swings wildly against the Ghost but not the Troll.)
Sure, now we could reduce the resistance of the ghost, upping its hitpoints to keep it balanced. But doing this, the Ghost starts to look awfully similar to every other unit. Making all units very similar would certainly be an easy way to get rid of anomalies in damage calculations.
I think the majority of us playing Wesnoth feel that the variety of units is a great strength of The Battle for Wesnoth. Let's not destroy that variety because we ignore ways of ironing out corner cases, other than the shortcut of making all units similar.
Moving to a scheme like miq's "resistance at the end" (RATE) could alleviate these high resistance problems very simply, retaining all the benefits of the current "additive" damage modifiers, and allowing use of the full spectrum of resistance modifiers, from 0 to 200 (and outside these values if desired, making possible currently unsupported effects like "hit this unit and it will heal" or "treble damage").
For reference, the current model calculates damage as
Code: Select all
finaldam = (100 + tod_bonus + led_bonus + resistance_modifier - 100)/100 * charge_multiplier * backstab_multiplier * steadfast_multiplier * base_damage
Note that this looks quite multiplicative, but currently only one of the specials multipliers can take a non-unit value, so there is only one multiplier in there.
The final value is then rounded towards the original base_damage : if base_damage is 10, then a finaldam of 6.5 is rounded to 7, a finaldam of 6.49 to 6, a finaldam of 13.5 is rounded to 13, and 13.51 to 14.
In comparison, RATE does the calculation as
Code: Select all
finaldam = (100 + tod_bonus + led_bonus)/100 * charge_multiplier * backstab_multiplier * steadfast_multiplier * (resistance_modifier/100) * base_damage
In closing, let's just look at that table from before, this time with RATE calculations:
Code: Select all
Ghost Troll Day/night factors
Thief 4-3/2-3 8-3/5-3 2 vs 1.6
Orcish Grunt 5-2/3-2 9-2/5-2 1.67 vs 1.8
Mage 5-3/9-3 5-3/9-3 1.8 vs 1.8
Ancient Wose 8-2/13-2 19-2/31-2 1.63 vs 1.6
Agreed completely. Which is why I'm now proposing RATE, a KISS solution to the problems with the current damage model.The main problem I have with pure multiplicative is that positives and negatives don't mesh together well:
What do people of think of RATE, which is really just a trivial tweak to the current additive model? It retains all the advantages while fixing the few corner cases which (for me at least) detract from the enjoyment of playing with or against chaotic or lawful units.
By the way, I have posted the RATE patch to http://savannah.nongnu.org/patch/?func= ... em_id=3671 with a Mages and Elves savegame to help people compare RATE against the current model, as well as a replay which was played using a RATEd binary. The patch should apply cleanly against 0.8.9, and to address previous criticism, uses integer arithmetic only. This Mages and Elves save has lots of Lawful and Chaotic units battling each other, including charging Paladins, a backstabbing Shadow, high hitting Shock Troopers, and some Necromancers and Lichs.