From 4ed1b3c6cac0932063f05948ad908d48eecce7ee Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Thu, 14 Sep 2023 14:37:56 -0500 Subject: [PATCH 1/5] Adjust body part hit difficulty to make critical hits matter for NPCs --- data/json/body_parts.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/data/json/body_parts.json b/data/json/body_parts.json index 8814df467454..667e2cb672f8 100644 --- a/data/json/body_parts.json +++ b/data/json/body_parts.json @@ -39,7 +39,7 @@ "essential": true, "hit_size": 6, "hit_size_relative": [ 0, 2.33, 5.71 ], - "hit_difficulty": 1.35, + "hit_difficulty": 1.4, "stylish_bonus": 3, "hot_morale_mod": 2, "cold_morale_mod": 2, @@ -57,7 +57,7 @@ "main_part": "head", "hit_size": 1, "hit_size_relative": [ 0, 0.33, 0.57 ], - "hit_difficulty": 1.15, + "hit_difficulty": 1.2, "stylish_bonus": 2, "squeamish_penalty": 8, "bionic_slots": 4 @@ -95,7 +95,7 @@ "opposite_part": "arm_r", "hit_size": 9, "hit_size_relative": [ 15, 20, 22.86 ], - "hit_difficulty": 0.95, + "hit_difficulty": 0.75, "side": "left", "hot_morale_mod": 0.5, "cold_morale_mod": 0.5, @@ -117,7 +117,7 @@ "opposite_part": "arm_l", "hit_size": 9, "hit_size_relative": [ 15, 20, 22.86 ], - "hit_difficulty": 0.95, + "hit_difficulty": 0.75, "side": "right", "hot_morale_mod": 0.5, "cold_morale_mod": 0.5, @@ -183,7 +183,7 @@ "opposite_part": "leg_r", "hit_size": 9, "hit_size_relative": [ 25, 12, 5.71 ], - "hit_difficulty": 0.975, + "hit_difficulty": 0.9, "side": "left", "stylish_bonus": 1, "hot_morale_mod": 0.5, @@ -206,7 +206,7 @@ "opposite_part": "leg_l", "hit_size": 9, "hit_size_relative": [ 25, 12, 5.71 ], - "hit_difficulty": 0.975, + "hit_difficulty": 0.9, "side": "right", "stylish_bonus": 1, "hot_morale_mod": 0.5, From bd3ffdea59d4c11f15792aec8d45c5c8a31e27e2 Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Thu, 14 Sep 2023 16:32:57 -0500 Subject: [PATCH 2/5] Update creature_test.cpp I hope I got the math right on this... --- tests/creature_test.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/creature_test.cpp b/tests/creature_test.cpp index cdb5334d9518..75bd395164e5 100644 --- a/tests/creature_test.cpp +++ b/tests/creature_test.cpp @@ -12,13 +12,13 @@ #include "rng.h" float expected_weights_base[][12] = { { 20, 0, 0, 0, 15, 15, 0, 0, 25, 25, 0, 0 }, - { 33.33, 2.33, 0.33, 0, 20, 20, 0, 0, 12, 12, 0, 0 }, - { 36.57, 5.71, .57, 0, 22.86, 22.86, 0, 0, 5.71, 5.71, 0, 0 } + { 33.33, 2.4, 0.32, 0, 10.65, 10.65, 0, 0, 9.91, 9.91, 0, 0 }, + { 36.57, 6.09, .55, 0, 13.57, 13.57, 0, 0, 4.99, 4.99, 0, 0 } }; float expected_weights_max[][12] = { { 2000, 0, 0, 0, 1191.49, 1191.49, 0, 0, 2228.12, 2228.12, 0, 0 }, - { 3333, 1167.77, 65.84, 0, 1588.66, 1588.66, 0, 0, 1069.50, 1069.50, 0, 0 }, - { 3657, 2861.78, 113.73, 0, 1815.83, 1815.83, 0, 0, 508.904, 508.904, 0, 0 } + { 3333, 1516.92, 78.99, 0, 465.08, 465.08, 0, 0, 625.41, 625.41, 0, 0 }, + { 3657, 3842.91, 139.72, 0, 374.07, 374.07, 0, 0, 315.09, 315.09, 0, 0 } }; static void calculate_bodypart_distribution( const enum m_size asize, const enum m_size dsize, From 7d472a9d9108b49991ebfb9bc9d5b0148a19cfe5 Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Thu, 14 Sep 2023 16:49:02 -0500 Subject: [PATCH 3/5] There was no need to touch those --- tests/creature_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/creature_test.cpp b/tests/creature_test.cpp index 75bd395164e5..dc13992adfa2 100644 --- a/tests/creature_test.cpp +++ b/tests/creature_test.cpp @@ -12,8 +12,8 @@ #include "rng.h" float expected_weights_base[][12] = { { 20, 0, 0, 0, 15, 15, 0, 0, 25, 25, 0, 0 }, - { 33.33, 2.4, 0.32, 0, 10.65, 10.65, 0, 0, 9.91, 9.91, 0, 0 }, - { 36.57, 6.09, .55, 0, 13.57, 13.57, 0, 0, 4.99, 4.99, 0, 0 } + { 33.33, 2.33, 0.33, 0, 20, 20, 0, 0, 12, 12, 0, 0 }, + { 36.57, 5.71, .57, 0, 22.86, 22.86, 0, 0, 5.71, 5.71, 0, 0 } }; float expected_weights_max[][12] = { { 2000, 0, 0, 0, 1191.49, 1191.49, 0, 0, 2228.12, 2228.12, 0, 0 }, From 85f1b74777d34ded41913259fdeb3aa6449c712d Mon Sep 17 00:00:00 2001 From: scarf Date: Fri, 15 Sep 2023 09:30:45 +0900 Subject: [PATCH 4/5] style: format array --- tests/creature_test.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/creature_test.cpp b/tests/creature_test.cpp index dc13992adfa2..c2612f212cac 100644 --- a/tests/creature_test.cpp +++ b/tests/creature_test.cpp @@ -11,14 +11,16 @@ #include "bodypart.h" #include "rng.h" -float expected_weights_base[][12] = { { 20, 0, 0, 0, 15, 15, 0, 0, 25, 25, 0, 0 }, +float expected_weights_base[][12] = { + { 20, 0, 0, 0, 15, 15, 0, 0, 25, 25, 0, 0 }, { 33.33, 2.33, 0.33, 0, 20, 20, 0, 0, 12, 12, 0, 0 }, - { 36.57, 5.71, .57, 0, 22.86, 22.86, 0, 0, 5.71, 5.71, 0, 0 } + { 36.57, 5.71, 0.57, 0, 22.86, 22.86, 0, 0, 5.71, 5.71, 0, 0 } }; -float expected_weights_max[][12] = { { 2000, 0, 0, 0, 1191.49, 1191.49, 0, 0, 2228.12, 2228.12, 0, 0 }, +float expected_weights_max[][12] = { + { 2000, 0, 0, 0, 1191.49, 1191.49, 0, 0, 2228.12, 2228.12, 0, 0 }, { 3333, 1516.92, 78.99, 0, 465.08, 465.08, 0, 0, 625.41, 625.41, 0, 0 }, - { 3657, 3842.91, 139.72, 0, 374.07, 374.07, 0, 0, 315.09, 315.09, 0, 0 } + { 3657, 3842.91, 139.72, 0, 374.07, 374.07, 0, 0, 315.09, 315.09, 0, 0 } }; static void calculate_bodypart_distribution( const enum m_size asize, const enum m_size dsize, From 31d7b8db7054f7ecd22deb577c324486f0fac768 Mon Sep 17 00:00:00 2001 From: scarf Date: Fri, 15 Sep 2023 10:45:32 +0900 Subject: [PATCH 5/5] test: refactor display and adjust values --- tests/creature_test.cpp | 104 ++++++++++++++++++++++++++++------------ 1 file changed, 73 insertions(+), 31 deletions(-) diff --git a/tests/creature_test.cpp b/tests/creature_test.cpp index c2612f212cac..3d11cb3708e6 100644 --- a/tests/creature_test.cpp +++ b/tests/creature_test.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include "creature.h" @@ -10,78 +11,119 @@ #include "test_statistics.h" #include "bodypart.h" #include "rng.h" +namespace +{ + +using Weights = std::map; +struct Expected { + Weights base, max; +}; + + +const auto expected_smaller = Expected +{ + Weights{ + { bp_torso, 20 }, { bp_head, 0 }, { bp_eyes, 0 }, { bp_mouth, 0 }, { bp_arm_l, 15 }, { bp_arm_r, 15 }, + { bp_hand_l, 0 }, { bp_hand_r, 0 }, { bp_leg_l, 25 }, { bp_leg_r, 25 }, { bp_foot_l, 0 }, { bp_foot_r, 0 } + }, + Weights{ + { bp_torso, 4960 }, { bp_head, 0 }, { bp_eyes, 0 }, { bp_mouth, 0 }, { bp_arm_l, 1143 }, { bp_arm_r, 1186 }, + { bp_hand_l, 0 }, { bp_hand_r, 0 }, { bp_leg_l, 3844 }, { bp_leg_r, 3867 }, { bp_foot_l, 0 }, { bp_foot_r, 0 } + } +}; -float expected_weights_base[][12] = { - { 20, 0, 0, 0, 15, 15, 0, 0, 25, 25, 0, 0 }, - { 33.33, 2.33, 0.33, 0, 20, 20, 0, 0, 12, 12, 0, 0 }, - { 36.57, 5.71, 0.57, 0, 22.86, 22.86, 0, 0, 5.71, 5.71, 0, 0 } + +const auto expected_same = Expected +{ + Weights{ + { bp_torso, 33.33 }, { bp_head, 2.33 }, { bp_eyes, 0.33 }, { bp_mouth, 0 }, { bp_arm_l, 20 }, { bp_arm_r, 20 }, + { bp_hand_l, 0 }, { bp_hand_r, 0 }, { bp_leg_l, 12 }, { bp_leg_r, 12 }, { bp_foot_l, 0 }, { bp_foot_r, 0 } + }, + Weights{ + { bp_torso, 6513 }, { bp_head, 2928 }, { bp_eyes, 150 }, { bp_mouth, 0 }, { bp_arm_l, 1224 }, { bp_arm_r, 1235 }, + { bp_hand_l, 0 }, { bp_hand_r, 0 }, { bp_leg_l, 1458 }, { bp_leg_r, 1492 }, { bp_foot_l, 0 }, { bp_foot_r, 0 } + } }; -float expected_weights_max[][12] = { - { 2000, 0, 0, 0, 1191.49, 1191.49, 0, 0, 2228.12, 2228.12, 0, 0 }, - { 3333, 1516.92, 78.99, 0, 465.08, 465.08, 0, 0, 625.41, 625.41, 0, 0 }, - { 3657, 3842.91, 139.72, 0, 374.07, 374.07, 0, 0, 315.09, 315.09, 0, 0 } +const auto expected_larger = Expected +{ + Weights{ + { bp_torso, 36.57 }, { bp_head, 5.71 }, { bp_eyes, 0.57 }, { bp_mouth, 0 }, { bp_arm_l, 22.86 }, { bp_arm_r, 22.86 }, + { bp_hand_l, 0 }, { bp_hand_r, 0 }, { bp_leg_l, 5.71 }, { bp_leg_r, 5.71 }, { bp_foot_l, 0 }, { bp_foot_r, 0 } + }, + Weights{ + { bp_torso, 5689 }, { bp_head, 5682 }, { bp_eyes, 221 }, { bp_mouth, 0 }, { bp_arm_l, 1185 }, { bp_arm_r, 1089 }, + { bp_hand_l, 0 }, { bp_hand_r, 0 }, { bp_leg_l, 578 }, { bp_leg_r, 556 }, { bp_foot_l, 0 }, { bp_foot_r, 0 } + } }; -static void calculate_bodypart_distribution( const enum m_size asize, const enum m_size dsize, - const int hit_roll, float ( &expected )[12] ) + +void calculate_bodypart_distribution( const enum m_size attacker_size, + const enum m_size defender_size, + const int hit_roll, const Weights &expected ) { INFO( "hit roll = " << hit_roll ); - std::map selected_part_histogram = { + auto selected_part_histogram = Weights{ { bp_torso, 0 }, { bp_head, 0 }, { bp_eyes, 0 }, { bp_mouth, 0 }, { bp_arm_l, 0 }, { bp_arm_r, 0 }, { bp_hand_l, 0 }, { bp_hand_r, 0 }, { bp_leg_l, 0 }, { bp_leg_r, 0 }, { bp_foot_l, 0 }, { bp_foot_r, 0 } }; mtype atype; - atype.size = asize; + atype.size = attacker_size; monster attacker; attacker.type = &atype; mtype dtype; - dtype.size = dsize; + dtype.size = defender_size; monster defender; defender.type = &dtype; const int num_tests = 15000; for( int i = 0; i < num_tests; ++i ) { - selected_part_histogram[defender.select_body_part( &attacker, hit_roll )]++; + const auto bp = defender.select_body_part( &attacker, hit_roll ); + selected_part_histogram.at( bp )++; } - float total_weight = 0.0; - for( float w : expected ) { - total_weight += w; - } + const float total_weight = std::accumulate( expected.begin(), expected.end(), 0.0f, + []( float acc, const auto & p ) { + return acc + p.second; + } ); - for( auto weight : selected_part_histogram ) { - INFO( body_part_name( weight.first ) ); - const double expected_proportion = expected[weight.first] / total_weight; - CHECK_THAT( weight.second, IsBinomialObservation( num_tests, expected_proportion ) ); + std::stringstream ss; + for( const auto &[bp, weight] : selected_part_histogram ) { + ss << body_part_name( bp ) << ": " << weight << ", "; + } + INFO( '{' << ss.str() << "}\n" ); + for( const auto &[bp, weight] : selected_part_histogram ) { + const double expected_proportion = expected.at( bp ) / total_weight; + CHECK_THAT( weight, IsBinomialObservation( num_tests, expected_proportion ) ); } } +} // namespace TEST_CASE( "Check distribution of attacks to body parts for same sized opponents." ) { rng_set_engine_seed( 4242424242 ); - calculate_bodypart_distribution( MS_SMALL, MS_SMALL, 0, expected_weights_base[1] ); - calculate_bodypart_distribution( MS_SMALL, MS_SMALL, 1, expected_weights_base[1] ); - calculate_bodypart_distribution( MS_SMALL, MS_SMALL, 100, expected_weights_max[1] ); + calculate_bodypart_distribution( MS_SMALL, MS_SMALL, 0, expected_same.base ); + calculate_bodypart_distribution( MS_SMALL, MS_SMALL, 1, expected_same.base ); + calculate_bodypart_distribution( MS_SMALL, MS_SMALL, 100, expected_same.max ); } TEST_CASE( "Check distribution of attacks to body parts for smaller attacker." ) { rng_set_engine_seed( 4242424242 ); - calculate_bodypart_distribution( MS_SMALL, MS_MEDIUM, 0, expected_weights_base[0] ); - calculate_bodypart_distribution( MS_SMALL, MS_MEDIUM, 1, expected_weights_base[0] ); - calculate_bodypart_distribution( MS_SMALL, MS_MEDIUM, 100, expected_weights_max[0] ); + calculate_bodypart_distribution( MS_SMALL, MS_MEDIUM, 0, expected_smaller.base ); + calculate_bodypart_distribution( MS_SMALL, MS_MEDIUM, 1, expected_smaller.base ); + calculate_bodypart_distribution( MS_SMALL, MS_MEDIUM, 100, expected_smaller.max ); } TEST_CASE( "Check distribution of attacks to body parts for larger attacker." ) { rng_set_engine_seed( 4242424242 ); - calculate_bodypart_distribution( MS_MEDIUM, MS_SMALL, 0, expected_weights_base[2] ); - calculate_bodypart_distribution( MS_MEDIUM, MS_SMALL, 1, expected_weights_base[2] ); - calculate_bodypart_distribution( MS_MEDIUM, MS_SMALL, 100, expected_weights_max[2] ); + calculate_bodypart_distribution( MS_MEDIUM, MS_SMALL, 0, expected_larger.base ); + calculate_bodypart_distribution( MS_MEDIUM, MS_SMALL, 1, expected_larger.base ); + calculate_bodypart_distribution( MS_MEDIUM, MS_SMALL, 100, expected_larger.max ); }