URL:
<http://gna.org/bugs/?21619>
Summary: A better behavior for defense_weight
Project: Battle for Wesnoth
Submitted by: elvish_pillager
Submitted on: Sat 08 Feb 2014 04:36:32 PM UTC
Category: Feature Request
Severity: 1 - Wish
Priority: 5 - Normal
Item Group: WML
Status: None
Privacy: Public
Assigned to: None
Originator Email:
Open/Closed: Open
Discussion Lock: Any
Release: 1.11.8+dev
Operating System: Debian Linux
_______________________________________________________
Details:
Zero/nonzero defense_weight to determine whether an attack can be used on
defense is fine, although now also doable using [disable]. This request is not
about that; this request concerns the *differences between different nonzero
values (e.g. 1 vs 2)*.
By my reading of actions/attack.cpp 592-610, defense_weight has the following
behavior for two attacks A and B:
If A comes before B, has higher defense_weight, and does more (average_damage
* defense_weight) than B, then B will not be selected even if B has higher
chance to kill.
I believe the "if A comes before B" part is a bug: notice how the first
condition on line 605 is always false because of its ordering with 602.
Without the bug, the behavior would be:
If A has the highest defense_weight among all attacks, then no other attack
with lower (average_damage * defense_weight) will be selected.
This violates the "independence of irrelevant alternatives" principle. Imagine
a unit with two attacks:
A: 2-5 melee, 1 defense_weight
B: 8-2 melee, 1 defense_weight
and is being attacked in melee by a unit with 2 HP. Obviously, it will pick A.
But now suppose it has a third attack
C: 6-1 melee, 2 defense_weight
The "simple_rating" for this attack exceeds A, so A cannot now be chosen.
However, it is less than B, so *B* is chosen! This clearly isn't what it
should be doing.
So what should it be doing? Here are some use cases:
1) The sole mainline usage: Giant scorpions. For some reason, it should defend
with its stinger even when the game considers that less advantageous, but not
always. I'm not sure this is a desirable situation to use defense_weight - I
recommend that better_combat should simply value poisoning more highly. If
there is a thematic reason that it should favor the stinger even against
units that can't be poisoned, I recommend the other attack be disabled
completely on defense.
2) A UMC unit that has an [event]-based attack special that the game doesn't
consider. Most attack specials are less important than killing the unit, and
most such attack specials don't depend on the damage done. On the other hand,
there are attack specials that depend on the damage done (e.g. "take the same
amount of damage again in two turns"), and there are attack specials that
would be desirable only in the case of a kill (e.g. Plague). As an add-on
writer, I'd want to indicate any of those separately.
I recommend the following:
1) Make the code more consistent by replacing better_combat() with a single
weight function that takes one attack. It would return the difference in
CTK-CTBK times a large factor, plus difference in average-damage-plus-poison
weighted by maxHP (so that that summand doesn't gain more influence just
because the units have higher stats in general). (Side note: A fire dragon
attacked by a goblin spearman currently values its own chance to die equally
with its attacker's chance to die. CTK values should probably be multiplied by
the unit value function.) Then better_combat() is simply "Which attack's
weight is higher?"
2) For the new defense weight behavior to modify that weight function.
3) Since [disable] exists now in 1.11, for the defense_weight key and the
attack_weight key to be *deprecated* in favor of a second attack special:
[modify_weight].
As an attack special, the user could indicate whether it applies on offense
(mostly a cosmetic effect), defense (a mechanical effect), or both.
It would have the following keys:
[modify_weight]
add_damage = number or lua function (attack acts as if it deals this much
extra damage when choosing attacks)
multiply_damage = number or lua function (damage is multiplied by this much
when choosing attacks)
multiply_kills = number or lua function (multiply chance to kill by this much
when choosing attacks)
[/modify_weight]
Any non-numerical keys would be interpreted as lua functions in the global
namespace that take two units (the unit with the weapon and its opponent) and
return a number.
_______________________________________________________
Reply to this item at:
<http://gna.org/bugs/?21619>
_______________________________________________
Message sent via/by Gna!
http://gna.org/
_______________________________________________
Wesnoth-bugs mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-bugs