Skip to content
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

Fix throwing #25410

Merged
merged 8 commits into from
Sep 9, 2018
Merged

Fix throwing #25410

merged 8 commits into from
Sep 9, 2018

Conversation

alanbrady
Copy link
Contributor

@alanbrady alanbrady commented Sep 6, 2018

Summary

SUMMARY: Bugfixes "Fix OP throwing"

Purpose of change

Throwing is OP on the low end. A survivor with base 8/8/8/8 stats and zero throwing skill can fend off some zombies with nothing more than a pile of rocks. This should not be possible.

The end result of the changes here essentially re-orientates the throwing to be more heavily weighted on skill. This causes a decrease in damage output with zero skill and gives a significant boost to accuracy on the high end, without also increasing damage output significantly.

This PR also slightly changes the throwing dynamic by forcing you to be wielding whatever it is you're trying to throw.

Describe the solution

This is a multi-facet solution that is actually more about adding some basic tests and drawing a baseline for the current state of throwing. We know that on the very low end, throwing is over powered, beyond that there's some flexibility in interpretation and further balancing, but at a minimum we should address this case.

This addresses the problem by first templatizing the statistics class. This allows us to better utilize the great functionality in the class and extend it further. Most notably we can now gather regression stats on continuous data, not just discrete binary data. This also reinforces the class with some strictness to help prevent it from being using improperly in the future.

From there, we can create some baseline tests that model the current statistics for throwing.

Once complete, I tweaked the scenario test from range >= 10 down to 1, where it should be thus causing it to fail. From there I made some small modifications to the core model to then pass the scenario test. I then needed to redo the modelling tests to reflect the new values.

After fixing the tests, rebalance is complete.

Describe alternatives you've considered

More balancing may be required in the future since I did not attempt to do any kind of major overhaul and instead focused on addressing the greatest offender. However, now with tests in place and better infrastructure for statistics, this should be easier in the future.

Additional context

screenshot from 2018-09-06 20-14-47

Accuracy
Before

chart

After

chart 1

Damage
Before

chart 2

After

chart 3
*including misses

Closes #20414

@EirenexTheDragon
Copy link
Contributor

forcing to wield the item would make things like my hand grenade bandolier pr and the already released javelin bag more viable instead of just saving your inventory space, as activating both makes you wield the item anyway.

@alanbrady alanbrady changed the title Fix throwing [WIP] Fix throwing Sep 6, 2018
@cainiaowu
Copy link
Contributor

Force wielding seems like more keypress for tedium.
We can pop up a menu like the current ammo reloading menu with list of items and different movecosts depend on their locations.

@cainiaowu
Copy link
Contributor

Movecost is then calculated as if you wield them first then throwing of course.

@alanbrady
Copy link
Contributor Author

Force wielding seems like more keypress for tedium.
We can pop up a menu like the current ammo reloading menu with list of items and different movecosts depend on their locations.

You've misunderstood how this is implemented I think. If you're not wielding something and press 'T' to throw, you will automatically wield it and throw it. No additional keypresses required. Now, if you're already wielding something then you need to choose what to do with it, which would be no different than what you're suggesting.

Your suggestion does not improve the number of keypresses required to throw something and the only additional keypress required after this change is if you're wielding something already.

@logros13
Copy link

logros13 commented Sep 6, 2018

While throwing might be in need of a nerf does lowering the damage per attack for a close range low skill character from 15 to 0.9 (a factor 16) and at range 5 from 0625 to 0.015 (a factor 41!) bring it rather to far in the other direction? and that without taking into account the need to wield the items now... Unless there there is some other factor that is not clear from the table this seems to bring throwing from op to completely useless in the early game?

With this wont it essentially be impossible to level throwing through actually using it, forcing the player to find a skill book to actually make the skill useful? Well, either that or gaming the system by kiting a zombie around in a circle forever to grind throwing against it...

@alanbrady
Copy link
Contributor Author

While throwing might be in need of a nerf does lowering the damage per attack for a close range low skill character from 15 to 0.9 (a factor 16) and at range 5 from 0625 to 0.015 (a factor 41!) bring it rather to far in the other direction? and that without taking into account the need to wield the items now... Unless there there is some other factor that is not clear from the table this seems to bring throwing from op to completely useless in the early game?

Your concern is shared and others have convinced me it still needs work. This is WIP.

@mlangsdorf mlangsdorf added Game: Balance Balancing of (existing) in-game features. Code: Tests Measurement, self-control, statistics, balancing. [C++] Changes (can be) made in C++. Previously named `Code` Ranged Ranged (firearms, bows, crossbows, throwing), balance, tactics labels Sep 6, 2018
@kevingranade
Copy link
Member

While throwing might be in need of a nerf does lowering the damage per attack for a close range low skill character from 15 to 0.9

Just to point one thing out, the damage-per-hit is unchanged, the damage number is the average per throw, so when missing a lot it drops a great deal.

The ideal niche for early-game throwing IMO is that you use it to soften up an enemy as it approaches, but have little to no chance of killing it with just throwing attacks. That is the goal of this PR, because as stated in the description (and the linked issue), the current status quo trivializes early game encounters with zombies as long as you stock up on rocks first.

Later on, it could be used to safely deal with weak enemies at a bit greater than arms length, and soften up tougher enemies, but it should never be a main weapon (at high skill levels a sling becomes somewhat formidable, but it never approaches the effectiveness of a gun). This PR doesn't do anything for that scenario, it's substantially unchanged.

@cainiaowu
Copy link
Contributor

So how does it work in the game?
Did the player get feedback about the movecost and accuracy like the current firing interface?
Some screenshot please.

@kevingranade
Copy link
Member

The interface is completely unchanged, this only adjusts chance to hit and the wield on throw thing.

The goal here is to:
    a) give the statistics class more flexibility
    b) enforce some strictness in how the class is used in future tests
    c) try to automatically do the right thing depending on type

This does this foremost by giving the class a template definition such
that you must tell it what type of stats you're trying to take so that
when, for example, you take the margin of error, it uses the appropriate
function.

This also now provides the ability to specify a Z-level for the
particular stat you're taking.  The default is 99.9% confidence, which
was the previous behavior.

Lastly this provides a few new helper functions and structs which should
hopefully encourage more appropriate use of the statistics class and
eliminate code duplication.  There's a number of existing tests that
could likely take advantage of this new functionality but due to the
complexity of the some of the tests, it's better to refactor them
independently of this.
This adds a set of tests to model the current behavior of the throwing
skill.
Currently you can throw stuff without wielding it.  This fixes it so
that you must be wielding whatever you're trying to throw.

This makes more logical sense and nerfs throwing a bit.
Now that there's tests to model the current throwing behavior, we should
modify the test to match the behavior we want.

Here that is a simple matter of changing the range on
test_player_kills_monster from 10 to 1 which will cause it to fail until
the behavior is fixed.
The main thing we want to solve here to simply make a survivor with no
skills and no plan and just a pile of rocks not viable.

This solves this by tweaking the dispersion values according to skill
such that zero skill will have a higher chance of missing, but if you
master throwing there's a small boost.  This also modifies the damage
boost applied with strength depending on skill.

This forces throwing to scale more heavily with skill.
Now that intentional changes have been made to fix throwing balance, the
other tests need to be fixed to reflect the new values.
@alanbrady alanbrady changed the title [WIP] Fix throwing Fix throwing Sep 7, 2018
@alanbrady alanbrady changed the title Fix throwing [WIP] Fix throwing Sep 8, 2018
@alanbrady
Copy link
Contributor Author

I just realized the way I implemented the wielding thing has problems and I need little bit more complicated solution with how the thrown item gets removed. The pos index can be out of sync after u.wield. Fixing real quick.

@alanbrady
Copy link
Contributor Author

alanbrady commented Sep 8, 2018

That should do it.

EDIT: Nooope one more time.
EDIT2: Ok I think I got it now.

@alanbrady alanbrady changed the title [WIP] Fix throwing Fix throwing Sep 8, 2018
We remove the item after checking for wield which can invalidate the
'pos' index we're using to remove an item.  This could at best cause the
game to remove a random item and at worst cause a crash.
@alanbrady alanbrady changed the title Fix throwing [WIP] Fix throwing Sep 8, 2018
@alanbrady
Copy link
Contributor Author

alanbrady commented Sep 8, 2018

Neat travis failed on the scenario test. Apparently more nerf is needed.

EDIT:
I've run this test in a loop a bunch of times. In my own testing it's like a one in a million shot with where it's at right now. I haven't actually gotten it to fail. So I'm tweaking it just so slightly.

EDIT2: I fixed it, travis managed to fail on something unrelated. Calling it good here.

Somehow travis found a way to make this test fail once so I'm tweaking
it down slightly further.
@alanbrady alanbrady changed the title [WIP] Fix throwing Fix throwing Sep 8, 2018
@kevingranade
Copy link
Member

Weird, I'm getting a crash:
Starting program: /home/ec2-user/Cataclysm-DDA/tests/cata_test
Missing separate debuginfos, use: debuginfo-install glibc-2.26-28.amzn2.0.1.x86_64
Starting the actual test at Sat Sep 8 23:44:47 2018
Can't display menu options, 1 0 available screen rows are occupied by
' Stop wielding metal tank (60L)? | Moves
(snip)
Stop wielding metal tank (60L)? | Moves '
This is probably a bug.

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7bbea98 in _nc_printf_string_sp () from /lib64/libncursesw.so.6
Missing separate debuginfos, use: debuginfo-install libgcc-7.3.1-5.amzn2.0.2.x86_64 libstdc++-7.3.1-5.amzn2.0.2.x86_64 ncurses-libs-6.0-8.20170212.amzn2.1.1.x86_64
(gdb) bt
#0 0x00007ffff7bbea98 in _nc_printf_string_sp () from /lib64/libncursesw.so.6
#1 0x00007ffff7bb8660 in vwprintw () from /lib64/libncursesw.so.6
#2 0x00007ffff7bb87f4 in wprintw () from /lib64/libncursesw.so.6
#3 0x0000000000d7a561 in catacurses::wprintw (win=..., text="…") at src/ncurses_def.cpp:110
#4 0x0000000000eba49d in wprintz (w=..., FG=..., text="…") at src/output.cpp:2164
#5 0x0000000000ec25b4 in print_colored_text (w=..., y=y@entry=1, x=x@entry=2, color=..., base_color=..., text="…") at src/output.cpp:130
#6 0x0000000000ec3602 in trim_and_print (w=..., begin_y=begin_y@entry=1, begin_x=begin_x@entry=2, width=-5, base_color=..., text=" Stop wielding metal tank (60L)? | Moves ") at src/output.cpp:179
#7 0x0000000001231333 in uimenu::show (this=this@entry=0x7fffffffba90) at src/ui.cpp:577
#8 0x000000000123390b in uimenu::query (this=this@entry=0x7fffffffba90, loop=loop@entry=true) at src/ui.cpp:812
#9 0x0000000001027629 in player::dispose_item (this=this@entry=0x1ddbde0, obj=..., prompt="Stop wielding metal tank (60L)?") at src/player.cpp:7837
#10 0x0000000000fe6cee in player::unwield (this=this@entry=0x1ddbde0) at src/player.cpp:7595
#11 0x000000000102b07d in player::wield (this=0x1ddbde0, target=...) at src/player.cpp:7533
#12 0x00000000004835d8 in test_throwing_player_versus (p=..., mon_id="mon_zombie", throw_id="rock", range=range@entry=1, pstats=..., hit_thresh=..., dmg_thresh=..., min_throws=, max_throws=)
at throwing_test.cpp:103
#13 0x000000000048a648 in ____C_A_T_C_H____T_E_S_T____13 () at throwing_test.cpp:170
#14 0x000000000043348b in Catch::FreeFunctionTestCase::invoke (this=) at catch/catch.hpp:7298
#15 0x00000000004235f9 in Catch::TestCase::invoke (this=) at catch/catch.hpp:8291
#16 0x0000000000469f12 in Catch::RunContext::invokeActiveTestCase (this=0x7fffffffddb0) at catch/catch.hpp:6852
#17 Catch::RunContext::runCurrentTest (redirectedCerr="", redirectedCout="", this=0x7fffffffddb0) at catch/catch.hpp:6819
#18 Catch::RunContext::runTest (this=this@entry=0x7fffffffddb0, testCase=...) at catch/catch.hpp:6632
#19 0x0000000000431960 in Catch::runTests (config=...) at catch/catch.hpp:6992
#20 0x000000000046fe3f in Catch::Session::run (this=this@entry=0x7fffffffe240) at catch/catch.hpp:7126
#21 0x00000000004330a3 in main (argc=, argv=) at test_main.cpp:162

@kevingranade
Copy link
Member

Simple fix:

diff --git a/tests/throwing_test.cpp b/tests/throwing_test.cpp
index f99cfbbb6e..dfa7e09bb7 100644
--- a/tests/throwing_test.cpp
+++ b/tests/throwing_test.cpp
@@ -65,6 +65,7 @@ static void reset_player( player &p, const throw_test_pstats &pstats, const trip
     p.set_dex_bonus( 0 );
     p.worn.clear();
     p.inv.clear();
+    p.remove_weapon();
     p.set_skill_level( skill_throw, pstats.skill_lvl );
 }

@kevingranade kevingranade merged commit d57b317 into CleverRaven:master Sep 9, 2018
@alanbrady
Copy link
Contributor Author

Ah ha, thanks. Dunno why it wasn't triggering for me, I'm guessing the ordering of tests happened to be slightly different from when I last rebased this.

@kevingranade
Copy link
Member

It didn't happen on travis either, I have no idea what sets test execution order.

@alanbrady alanbrady deleted the fix-throwing branch September 15, 2018 06:02
@alanbrady alanbrady mentioned this pull request Sep 15, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[C++] Changes (can be) made in C++. Previously named `Code` Code: Tests Measurement, self-control, statistics, balancing. Game: Balance Balancing of (existing) in-game features. Ranged Ranged (firearms, bows, crossbows, throwing), balance, tactics
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Throwing is too good
6 participants