From e1dce8a7d1284dee67628aaa2effc6846f220eff Mon Sep 17 00:00:00 2001 From: SlackingSleeper Date: Wed, 2 Oct 2019 07:57:44 +0200 Subject: [PATCH] JSONify range_with_even_chance_of_good_hit (#34089) --- data/json/hit_range.json | 67 ++++++++++++++++++++++++++++++++++++++++ src/creature.cpp | 18 +++++++++++ src/creature.h | 4 +++ src/init.cpp | 2 ++ src/ranged.cpp | 14 ++------- tests/ranged_balance.cpp | 33 ++++++++++++++++++-- 6 files changed, 124 insertions(+), 14 deletions(-) create mode 100644 data/json/hit_range.json diff --git a/data/json/hit_range.json b/data/json/hit_range.json new file mode 100644 index 0000000000000..e14ab934f7895 --- /dev/null +++ b/data/json/hit_range.json @@ -0,0 +1,67 @@ +[ + { + "type": "hit_range", + "even_good": [ + 1724, + 860, + 573, + 429, + 343, + 286, + 245, + 214, + 191, + 171, + 156, + 141, + 127, + 122, + 114, + 102, + 101, + 95, + 90, + 85, + 81, + 78, + 74, + 71, + 68, + 66, + 63, + 61, + 59, + 57, + 55, + 53, + 52, + 50, + 49, + 47, + 46, + 45, + 44, + 42, + 41, + 40, + 39, + 39, + 38, + 37, + 36, + 35, + 35, + 34, + 33, + 33, + 32, + 31, + 31, + 30, + 30, + 29, + 29, + 28 + ] + } +] diff --git a/src/creature.cpp b/src/creature.cpp index de92bfd47de7f..a34791530e0c4 100644 --- a/src/creature.cpp +++ b/src/creature.cpp @@ -13,6 +13,7 @@ #include "event_bus.h" #include "field.h" #include "game.h" +#include "json.h" #include "map.h" #include "messages.h" #include "monster.h" @@ -1717,3 +1718,20 @@ void Creature::add_msg_player_or_say( game_message_type type, const translation { return add_msg_player_or_say( type, pc.translated(), npc.translated() ); } + +std::vector Creature::dispersion_for_even_chance_of_good_hit = { { + 1731, 859, 573, 421, 341, 286, 245, 214, 191, 175, + 151, 143, 129, 118, 114, 107, 101, 94, 90, 78, + 78, 78, 74, 71, 68, 66, 62, 61, 59, 57, + 46, 46, 46, 46, 46, 46, 45, 45, 44, 42, + 41, 41, 39, 39, 38, 37, 36, 35, 34, 34, + 33, 33, 32, 30, 30, 30, 30, 29, 28 + } +}; + +void Creature::load_hit_range( JsonObject &jo ) +{ + if( jo.has_array( "even_good" ) ) { + jo.read( "even_good", dispersion_for_even_chance_of_good_hit ); + } +} diff --git a/src/creature.h b/src/creature.h index fbb55a9ba73a0..872d2864a9dd6 100644 --- a/src/creature.h +++ b/src/creature.h @@ -773,6 +773,10 @@ class Creature public: body_part select_body_part( Creature *source, int hit_roll ) const; + + static void load_hit_range( JsonObject & ); + // Empirically determined by "synthetic_range_test" in tests/ranged_balance.cpp. + static std::vector dispersion_for_even_chance_of_good_hit; /** * This function replaces the "" substring with the @ref disp_name of this creature. * diff --git a/src/init.cpp b/src/init.cpp index 614de00a33d6b..69a29f999bc56 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -18,6 +18,7 @@ #include "bionics.h" #include "construction.h" #include "crafting_gui.h" +#include "creature.h" #include "debug.h" #include "dialogue.h" #include "effect.h" @@ -211,6 +212,7 @@ void DynamicDataLoader::initialize() add( "start_location", &start_location::load_location ); add( "skill_boost", &skill_boost::load_boost ); add( "enchantment", &enchantment::load_enchantment ); + add( "hit_range", &Creature::load_hit_range ); // json/colors.json would be listed here, but it's loaded before the others (see init_colors()) // Non Static Function Access diff --git a/src/ranged.cpp b/src/ranged.cpp index c078a09f82121..cc8cf62a24ec1 100644 --- a/src/ranged.cpp +++ b/src/ranged.cpp @@ -124,20 +124,10 @@ double Creature::ranged_target_size() const int range_with_even_chance_of_good_hit( int dispersion ) { - // Empirically determined by "synthetic_range_test" in tests/ranged_balance.cpp. - static const std::array dispersion_for_even_chance_of_good_hit = {{ - 1731, 859, 573, 421, 341, 286, 245, 214, 191, 175, - 151, 143, 129, 118, 114, 107, 101, 94, 90, 78, - 78, 78, 74, 71, 68, 66, 62, 61, 59, 57, - 46, 46, 46, 46, 46, 46, 45, 45, 44, 42, - 41, 41, 39, 39, 38, 37, 36, 35, 34, 34, - 33, 33, 32, 30, 30, 30, 30, 29, 28 - } - }; int even_chance_range = 0; while( static_cast( even_chance_range ) < - dispersion_for_even_chance_of_good_hit.size() && - dispersion < dispersion_for_even_chance_of_good_hit[ even_chance_range ] ) { + Creature::dispersion_for_even_chance_of_good_hit.size() && + dispersion < Creature::dispersion_for_even_chance_of_good_hit[ even_chance_range ] ) { even_chance_range++; } return even_chance_range; diff --git a/tests/ranged_balance.cpp b/tests/ranged_balance.cpp index 607208a219075..d3283a806d5e1 100644 --- a/tests/ranged_balance.cpp +++ b/tests/ranged_balance.cpp @@ -5,7 +5,9 @@ #include #include "catch/catch.hpp" +#include "cata_utility.h" #include "ballistics.h" +#include "creature.h" #include "dispersion.h" #include "map_helpers.h" #include "npc.h" @@ -17,6 +19,7 @@ #include "inventory.h" #include "item.h" #include "item_location.h" +#include "json.h" #include "player.h" #include "material.h" #include "type_id.h" @@ -303,8 +306,9 @@ TEST_CASE( "expert_shooter_accuracy", "[ranged] [balance]" ) } } -static void range_test( const std::array &test_thresholds ) +static void range_test( const std::array &test_thresholds, bool write_data = false ) { + std::vector data; int index = 0; for( index = 0; index < static_cast( accuracy_levels.size() ); ++index ) { if( test_thresholds[index] >= 0 ) { @@ -334,8 +338,33 @@ static void range_test( const std::array &test_thresholds ) WARN( "No matching dispersion found" ); } else { WARN( "Range: " << r << " Dispersion: " << found_dispersion ); + data.push_back( found_dispersion ); } } + if( write_data ) { + const bool similar_to_previous_test_results = + std::equal( data.begin(), data.end(), + Creature::dispersion_for_even_chance_of_good_hit.begin(), + Creature::dispersion_for_even_chance_of_good_hit.end(), + []( const int a, const int b ) -> bool { + return a > 0 && b > 0 && std::abs( static_cast( a - b ) / b ) < 0.15; + } ); + + if( similar_to_previous_test_results == false ) { + write_to_file( "./data/json/hit_range.json", [&]( std::ostream & fsa ) { + JsonOut j_out( fsa ); + j_out.start_array(); + j_out.start_object(); + j_out.member( "type", "hit_range" ); + j_out.member( "even_good", data ); + j_out.end_object(); + j_out.end_array(); + }, _( "hit_range file" ) ); + } else { + WARN( "Didn't write. Data too similar to previous test results." ); + } + REQUIRE( similar_to_previous_test_results ); + } } // I added this to find inflection points where accuracy at a particular range crosses a threshold. @@ -349,6 +378,6 @@ TEST_CASE( "synthetic_range_test", "[.]" ) range_test( {{ -1, -1, 0.1, -1, -1 }} ); } SECTION( "good hit thresholds" ) { - range_test( {{ -1, -1, 0.5, -1, -1 }} ); + range_test( {{ -1, -1, 0.5, -1, -1 }}, true ); } }