From 877bac43886be0033a651c8b6836782fea547549 Mon Sep 17 00:00:00 2001 From: scarf Date: Sat, 27 May 2023 12:02:13 +0900 Subject: [PATCH] refactor: use optional for `map_funcs::climbing_cost` game - remove unnecessary cost <= 0 check (climbing_cost cannot be < 0) iexamine - being hard to climb is now considered both_way - prevent redundant rope message when climbing down by hand --- src/game.cpp | 9 ++--- src/iexamine.cpp | 76 +++++++++++++++++++++++++------------------ src/map_functions.cpp | 6 ++-- src/map_functions.h | 4 +-- 4 files changed, 55 insertions(+), 40 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index 92fc9e21b041..fd7d76c9cda1 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -10026,9 +10026,10 @@ void game::vertical_move( int movez, bool force, bool peeking ) } } - const int cost = map_funcs::climbing_cost( m, u.pos(), stairs ); - if( cost == 0 ) { + const auto cost = map_funcs::climbing_cost( m, u.pos(), stairs ); + + if( !cost.has_value() ) { if( u.has_trait( trait_WEB_ROPE ) ) { if( pts.empty() ) { add_msg( m_info, _( "There is nothing above you that you can attach a web to." ) ); @@ -10056,14 +10057,14 @@ void game::vertical_move( int movez, bool force, bool peeking ) } - if( cost <= 0 || pts.empty() ) { + if( pts.empty() ) { add_msg( m_info, _( "You can't climb here - there is no terrain above you that would support your weight." ) ); return; } else { // TODO: Make it an extended action climbing = true; - move_cost = cost; + move_cost = cost.value(); const std::optional pnt = point_selection_menu( pts ); if( !pnt ) { diff --git a/src/iexamine.cpp b/src/iexamine.cpp index a545d7dbc4bd..ae0fd466304c 100644 --- a/src/iexamine.cpp +++ b/src/iexamine.cpp @@ -26,6 +26,7 @@ #include "bionics.h" #include "bodypart.h" #include "calendar.h" +#include "cata_unreachable.h" #include "cata_utility.h" #include "catacharset.h" #include "character.h" @@ -4658,7 +4659,7 @@ void iexamine::ledge( player &p, const tripoint &examp ) } const bool has_grapnel = p.has_amount( itype_grapnel, 1 ); - const int climb_cost = map_funcs::climbing_cost( here, where, examp ); + const auto climb_cost = map_funcs::climbing_cost( here, where, examp ); const auto fall_mod = p.fall_damage_mod(); const std::string query_str = vgettext( "Looks like %d story. Jump down?", "Looks like %d stories. Jump down?", @@ -4667,47 +4668,60 @@ void iexamine::ledge( player &p, const tripoint &examp ) if( height > 1 && !query_yn( query_str.c_str(), height ) ) { return; } else if( height == 1 ) { - enum class climb_result { dangerous_one_way, safe_one_way, safe, safe_difficult }; - const auto get_status = [&]() { + enum class climb_result { + one_way_dangerous, one_way_unclimbable, + both_way_safe, both_way_grapnel, both_way_hard_to_climb, + }; + const auto get_climb_result = [&]() { if( has_grapnel ) { - return climb_result::safe; - } else if( climb_cost <= 0 && fall_mod > 0.8 ) { - return climb_result::dangerous_one_way; - } else if( climb_cost <= 0 ) { - return climb_result::safe_one_way; - } else if( climb_cost < 200 ) { - return climb_result::safe; + return climb_result::both_way_grapnel; + } + if( climb_cost.has_value() ) { + return climb_cost.value() < 200 + ? climb_result::both_way_safe + : climb_result::both_way_hard_to_climb; } else { - return climb_result::safe_difficult; + return fall_mod > 0.8 + ? climb_result::one_way_dangerous + : climb_result::one_way_unclimbable; } }; - const auto status = get_status(); - if( status != climb_result::safe ) { - const auto get_query = [&]() { - switch( status ) { - case climb_result::dangerous_one_way: - return _( "You probably won't be able to get up and jumping down may hurt. Jump?" ); - case climb_result::safe_one_way: - return _( "You probably won't be able to get back up. Climb down?" ); - case climb_result::safe_difficult: - return _( "You may have problems climbing back up. Climb down?" ); - default: - throw std::logic_error( "unreachable" ); - } - }; - if( !query_yn( get_query() ) ) { - return; + const auto get_message = []( climb_result res ) { + switch( res ) { + case climb_result::both_way_safe: + return _( "You climb down." ); + case climb_result::both_way_grapnel: + return _( "You tie the rope around your waist and begin to climb down." ); + case climb_result::both_way_hard_to_climb: + return _( "You climb down but feel that it won't be easy to climb back up." ); + case climb_result::one_way_dangerous: + return _( "You probably won't be able to get up and jumping down may hurt. Jump?" ); + case climb_result::one_way_unclimbable: + return _( "You probably won't be able to get back up. Climb down?" ); } + cata::unreachable(); + }; + add_msg( m_debug, "climb_cost: %d", climb_cost.value_or( -1 ) ); + const auto result = get_climb_result(); + const auto message = get_message( result ); + switch( result ) { + case climb_result::both_way_safe: + case climb_result::both_way_grapnel: + case climb_result::both_way_hard_to_climb: + p.add_msg_if_player( message ); + break; + case climb_result::one_way_dangerous: + case climb_result::one_way_unclimbable: + default: + if( !query_yn( message ) ) { + return; + } } } p.moves -= to_moves( 1_seconds + 1_seconds * fall_mod ); p.setpos( examp ); - if( has_grapnel ) { - p.add_msg_if_player( _( "You tie the rope around your waist and begin to climb down." ) ); - } - if( climb_cost > 0 || rng_float( 0.8, 1.0 ) > fall_mod ) { // One tile of falling less (possibly zero) g->vertical_move( -1, true ); diff --git a/src/map_functions.cpp b/src/map_functions.cpp index 02943ebc8376..b4334e216363 100644 --- a/src/map_functions.cpp +++ b/src/map_functions.cpp @@ -13,15 +13,15 @@ static const mtype_id mon_mi_go_myrmidon( "mon_mi_go_myrmidon" ); namespace map_funcs { -int climbing_cost( const map &m, const tripoint &from, const tripoint &to ) +auto climbing_cost( const map &m, const tripoint &from, const tripoint &to ) -> std::optional { // TODO: All sorts of mutations, equipment weight etc. for characters if( !m.valid_move( from, to, false, true ) ) { - return 0; + return {}; } const int diff = m.climb_difficulty( from ); if( diff > 5 ) { - return 0; + return {}; } return 50 + diff * 100; } diff --git a/src/map_functions.h b/src/map_functions.h index 4fb70f925ad5..f542d11e6f40 100644 --- a/src/map_functions.h +++ b/src/map_functions.h @@ -1,4 +1,5 @@ #pragma once +#include #ifndef CATA_SRC_MAP_FUNCTIONS_H #define CATA_SRC_MAP_FUNCTIONS_H @@ -11,10 +12,9 @@ namespace map_funcs /** * Checks both the neighborhoods of from and to for climbable surfaces, * returns move cost of climbing from `from` to `to`. - * 0 means climbing is not possible. * Return value can depend on the orientation of the terrain. */ -int climbing_cost( const map &m, const tripoint &from, const tripoint &to ); +auto climbing_cost( const map &m, const tripoint &from, const tripoint &to ) -> std::optional; void migo_nerve_cage_removal( map &m, const tripoint &p, bool spawn_damaged );