Skip to content

Commit

Permalink
refactor: use result<T, E> for climbing down
Browse files Browse the repository at this point in the history
  • Loading branch information
scarf005 committed May 24, 2023
1 parent c0026ce commit 841cc4e
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 34 deletions.
50 changes: 16 additions & 34 deletions src/iexamine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <set>
#include <type_traits>
#include <utility>
#include <variant>

#include "activity_actor.h"
#include "activity_actor_definitions.h"
Expand Down Expand Up @@ -55,6 +56,7 @@
#include "game_inventory.h"
#include "handle_liquid.h"
#include "harvest.h"
#include "iexamine_ledge.h"
#include "input.h"
#include "int_id.h"
#include "inventory.h"
Expand Down Expand Up @@ -105,6 +107,7 @@
#include "units_utility.h"
#include "value_ptr.h"
#include "vehicle.h"
#include "visitor_utils.h"
#include "vpart_position.h"
#include "weather.h"

Expand Down Expand Up @@ -4667,47 +4670,26 @@ 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 = [&]() {
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;
} else {
return climb_result::safe_difficult;
}
};
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" );
const auto res = get_climb_result( has_grapnel, climb_cost, fall_mod );
std::visit( visitor_util::overloaded{
[&]( both_way arg )
{
if( arg == both_way::grapnel ) {
p.add_msg_if_player( _( "You tie the rope around your waist and begin to climb down." ) );
}
},
[&]( one_way arg )
{
if( !query_yn( get_climb_query( arg ) ) ) {
return;
}
};
if( !query_yn( get_query() ) ) {
return;
}
}
}, res );
}

p.moves -= to_moves<int>( 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 );
Expand Down
32 changes: 32 additions & 0 deletions src/iexamine_ledge.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include <stdexcept>

#include "iexamine_ledge.h"
#include "translations.h"

auto get_climb_result( bool has_grapnel, int climb_cost, float fall_mod ) -> climb_result
{
if( has_grapnel ) {
return both_way::grapnel;
} else if( climb_cost <= 0 && fall_mod > 0.8 ) {
return one_way::dangerous;
} else if( climb_cost <= 0 ) {
return one_way::unclimbable;
} else if( climb_cost < 200 ) {
return both_way::easy;
} else {
return one_way::hard_to_climb;
}
};

auto get_climb_query( one_way result ) -> const char *
{
switch( result ) {
case one_way::dangerous:
return _( "You probably won't be able to get up and jumping down may hurt. Jump?" );
case one_way::unclimbable:
return _( "You probably won't be able to get back up. Climb down?" );
case one_way::hard_to_climb:
return _( "You may have problems climbing back up. Climb down?" );
}
}

21 changes: 21 additions & 0 deletions src/iexamine_ledge.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once
#ifndef CATA_SRC_IEXAMINE_LEDGE_H
#define CATA_SRC_IEXAMINE_LEDGE_H

#include <variant>

enum class one_way { dangerous, unclimbable, hard_to_climb };
enum class both_way { easy, grapnel };

// stores whether it's possible to climb down then get up
using climb_result = std::variant<one_way, both_way>;

/**
* @brief Check if it's possible to climb down then get up.
*
* @param fall_mod Fall damage modifier. @see Character::fall_damage_mod()
*/
auto get_climb_result( bool has_grapnel, int climb_cost, float fall_mod ) -> climb_result;
auto get_climb_query( one_way result ) -> const char *;

#endif // CATA_SRC_IEXAMINE_LEDGE_H

0 comments on commit 841cc4e

Please sign in to comment.