-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
melee: Make sure that melee weapon accuracy improves hit rates #39564
melee: Make sure that melee weapon accuracy improves hit rates #39564
Conversation
/* | ||
* statistics data for melee attacks, used for test purposes | ||
*/ | ||
struct melee_statistic_data { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These melee stats are a good candidate to migrate to the event bus, then the tests can hook in to the hit events that way. I'm not asking you to do that in this PR, because melee events aren't a thing yet; this is more of a note-to-self.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds great =)
clang-tidy errors are not my fault; code had them already. |
Yep, that's pending #39562 |
This pull request fixes 1 alert when merging 0b459de into 32e6aab - view on LGTM.com fixed alerts:
|
0b459de
to
b9463f9
Compare
This pull request fixes 1 alert when merging b9463f9 into 5db5df0 - view on LGTM.com fixed alerts:
|
WTF, Xcode on MacOS 10.1, why are you consistently failing the accuracy tests:
|
ab44527
to
b9463f9
Compare
This pull request fixes 1 alert when merging 93296d2 into 5dd7e74 - view on LGTM.com fixed alerts:
|
72770fb
to
977e3fb
Compare
977e3fb
to
e20aa3a
Compare
This pull request fixes 1 alert when merging e20aa3a into 5dd7e74 - view on LGTM.com fixed alerts:
|
e20aa3a
to
0e7c596
Compare
fris0uman inadvertently added a regression with his recent refactoring of melee.cpp to move things from player:: to Character::, which the test caught erratically. A bugfix was added. |
This pull request fixes 1 alert when merging 0e7c596 into f94cfe1 - view on LGTM.com fixed alerts:
|
Results are closer to expectations now, though not quite there yet. ex. trench knife vs. debug monster: Actual 13.0157, Expected 20.160
commit 8ef3706 moved a bunch of melee related functions out of player:: and into Character::, but failed to call the new renamed version of get_hit() correctly.
Fix some long lines and use std:: functions in place of math.h functions in a few places.
Move the accuracy bonus out of the avatar's hit bonuses where they may or may not be set correctly via reset() and into get_hit_weapon() where they are definitely set and applied correctly. Add some statistics counters to the melee code to make writing test cases easier. Add unit tests to verify that increase a weapon's accuracy increases to hit rates and DPS.
Don't calculate dps for monsters that aren't going to be displayed. Adjust the unit tests based on relative values (epsilon) instead of fixed values (margin).
use average of effective dps against evaluation monsters in melee_value(), with an additional bonus for reach weapons and for weapons that work with a martial art the NPC knows.
Include the Melee Evaluation spreadsheet and a description of it, and update GAME_BALANCE.md with the new formulas.
21a9d19
to
cedb55f
Compare
This pull request fixes 1 alert when merging cedb55f into 074dd18 - view on LGTM.com fixed alerts:
|
Yay! |
Summary
SUMMARY: Bugfixes "melee: Make sure that melee weapon accuracy improves hit rates"
Purpose of change
jtbw suggested in #39362 that unit tests would be helpful for ensuring that the simplified DPS
calculation would match the actual DPS values observed by going through the melee attack code.
In the process of implementing that suggestion, it became apparent that melee weapon accuracy
had little or no bearing on the chance to hit with a weapon.
weapon.type->m_to_hit
was only being applied viamod_hit_bonus()
inavatar::reset_stats()
which was called fromavatar::reset()
, so it seemed unlikely that changing weapons would necessarily change thehit bonus.
Fix that bug, so that melee weapon accuracy clearly effects hit rates, and add unit test cases to make sure that future regressions will be caught. Then go back to the original point of the exercise and add unit test cases for effective dps, and fix effective_dps to match the results of those test cases. Finally, extend effective_dps so that NPCs will use it to value weapons.
Describe the solution
There are a lot of moving parts here:
wapcaplet wrote the initial effective DPS test cases based on some pseudo-code I wrote. Those are in #39476 and this PR includes and supersedes that one.
The melee weapon accuracy fix moves
weapon.type->m_to_hit
out ofget_hit_bonus()
and intoget_hit_weapon()
as a static bonus after calculating skill bonuses. Adding unit tests cases for that required the ability to easily count the number of successful attacks, and after considering the options, I decided that adding an out-of-band set of statistic counters was easier than rewriting the melee attack sequence to be accessible for test cases.The effective DPS test cases demonstrated that the algorithm for effective_dps had a lot of problems, so parts of it were rewritten to correctly calculate critical hit chances and the damage calculation was rewritten to more closely match the melee code. At the same time, the code was adjusted so that callers could specify if they wanted monsters for display or monsters for evaluation, and calculations for unneeded monsters were skipped.
The DPS unit tests repeat running trials in blocks of 1000 until 100 crits occur in an effort to reduce the burstiness of the results without requiring that the tests run for 90 seconds.
Finally, there was no reason to keep an alternate set of melee DPS calculations in
weapon_value()
, so that got removed and replaced by using theeffective_dps()
infrastructure.Describe alternatives you've considered
player::melee_attack()
has an extremely weird structure, with code flow jumping back and forth between the attacker and defender in weird ways. Restructuring it to have a more logical flow and to be easier to test would be great, but it would also be a large project. It should be easier now that there are unit test cases to confirm that changes are just refactors and don't have accidental semantic changes.Testing
I spent hours and hours running test cases to make all this work. The proof is that the test cases mostly work. Actual calculated dps over 1000s of trials can still vary by more than 20% in extreme cases, and I'm not sure what to do about that.