Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions src/openvic-simulation/country/CountryInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include "openvic-simulation/utility/Containers.hpp"
#include "openvic-simulation/utility/Logger.hpp"
#include "openvic-simulation/core/Typedefs.hpp"
#include "openvic-simulation/scripts/Condition.hpp"

using namespace OpenVic;

Expand Down Expand Up @@ -1178,6 +1179,125 @@ void CountryInstance::start_research(Technology const& technology, const Date to
_update_current_tech(today);
}

bool CountryInstance::evaluate_leaf(ConditionNode const& node) const {
std::string_view const& id = node.get_condition()->get_identifier();

// TODO: https://vic2.paradoxwikis.com/List_of_conditions#Country_Scope Implement all of these

if (id == "ai") {
bool expected = std::get<bool>(node.get_value());
return is_ai() == expected;
}

if (id == "average_consciousness") {
fixed_point_t expected = std::get<fixed_point_t>(node.get_value());
return get_average_consciousness() >= expected;
}

if (id == "average_militancy") {
fixed_point_t expected = std::get<fixed_point_t>(node.get_value());
return get_average_militancy() >= expected;
}

if (id == "badboy") {
fixed_point_t expected_ratio = std::get<fixed_point_t>(node.get_value());
return get_infamy_untracked() >= (expected_ratio * fixed_point_t(25));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a hardcoded value.
The bad boy limit comes from the country defines.

}

if (id == "civilized") {
bool expected = std::get<bool>(node.get_value());
return is_civilised() == expected;
}

if (id == "colonial_nation") {
bool expected = std::get<bool>(node.get_value());
return is_colonial(colony_status_t::COLONY) == expected;
}

if (id == "exists") {
bool expected = std::get<bool>(node.get_value());
return exists() == expected;
}
Comment on lines +1217 to +1220
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "exists" condition can accept either IDENTIFIER (country tag) or BOOLEAN values according to its definition (line 285), but this implementation only handles the BOOLEAN case. When the condition is used with an IDENTIFIER (e.g., "exists = ENG"), this code will throw a std::bad_variant_access exception when trying to std::get. The implementation should check which variant type is present and handle both cases appropriately.

Copilot uses AI. Check for mistakes.

if (id == "industrial_score") {
fixed_point_t expected = std::get<fixed_point_t>(node.get_value());
return get_industrial_power_untracked() >= expected;
Comment on lines +1223 to +1224
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "industrial_score" condition can accept either REAL or IDENTIFIER values according to its definition (line 299), but this implementation only handles the REAL case. When used with an IDENTIFIER (e.g., "industrial_score = ENG" to compare against another country's score), this code will throw a std::bad_variant_access exception when trying to std::get<fixed_point_t>. The implementation should check which variant type is present and handle both cases appropriately.

Suggested change
fixed_point_t expected = std::get<fixed_point_t>(node.get_value());
return get_industrial_power_untracked() >= expected;
return std::visit(
[this](auto const& value) -> bool {
using T = std::decay_t<decltype(value)>;
if constexpr (std::is_same_v<T, fixed_point_t>) {
return get_industrial_power_untracked() >= value;
} else {
Logger::error(
"industrial_score condition received unsupported value type");
return false;
}
},
node.get_value()
);

Copilot uses AI. Check for mistakes.
}

if (id == "is_disarmed") {
bool expected = std::get<bool>(node.get_value());
return is_disarmed() == expected;
}

if (id == "is_greater_power") {
bool expected = std::get<bool>(node.get_value());
return is_great_power() == expected;
}

if (id == "is_mobilised") {
bool expected = std::get<bool>(node.get_value());
return is_mobilised() == expected;
}

if (id == "is_secondary_power") {
bool expected = std::get<bool>(node.get_value());
return is_secondary_power() == expected;
}

if (id == "num_of_cities") {
uint64_t expected = std::get<uint64_t>(node.get_value());
return get_owned_provinces().size() >= expected;
}

if (id == "num_of_ports") {
uint64_t expected = std::get<uint64_t>(node.get_value());
return get_port_count() >= expected;
}

if (id == "number_of_states") {
uint64_t expected = std::get<uint64_t>(node.get_value());
return get_states().size() >= expected;
}

if (id == "prestige") {
fixed_point_t expected = std::get<fixed_point_t>(node.get_value());
return get_prestige_untracked() >= expected;
}

if (id == "plurality") {
fixed_point_t expected = std::get<fixed_point_t>(node.get_value());
return get_plurality_untracked() >= expected;
}

if (id == "total_amount_of_ships") {
uint64_t expected = std::get<uint64_t>(node.get_value());
return get_ship_count() >= expected;
}

if (id == "rank") {
uint64_t expected = std::get<uint64_t>(node.get_value());
return get_total_rank() >= expected;
}

if (id == "tag") {
memory::string const& expected = std::get<memory::string>(node.get_value());
return country_definition.get_identifier() == expected;
}

if (id == "war") {
bool expected = std::get<bool>(node.get_value());
return is_at_war() == expected;
}

if (id == "war_exhaustion") {
fixed_point_t expected = std::get<fixed_point_t>(node.get_value());
return get_war_exhaustion() >= expected;
}

spdlog::warn_s("Condition {} not implemented in CountryInstance::evaluate_leaf", node.get_condition() ? node.get_condition()->get_identifier() : "NULL");
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message duplicates the condition null-check logic unnecessarily. Since id is already obtained from node.get_condition()->get_identifier() at line 1183, and would have crashed earlier if condition were null, the ternary operator here is redundant. The message should simply use id for consistency.

Suggested change
spdlog::warn_s("Condition {} not implemented in CountryInstance::evaluate_leaf", node.get_condition() ? node.get_condition()->get_identifier() : "NULL");
spdlog::warn_s("Condition {} not implemented in CountryInstance::evaluate_leaf", id);

Copilot uses AI. Check for mistakes.
return false;
}

void CountryInstance::apply_foreign_investments(
fixed_point_map_t<CountryDefinition const*> const& investments, CountryInstanceManager const& country_instance_manager
) {
Expand Down
3 changes: 3 additions & 0 deletions src/openvic-simulation/country/CountryInstance.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ namespace OpenVic {
struct TechnologySchool;
struct UnitInstanceGroup;
struct UnitTypeManager;
struct ConditionNode;

static constexpr Timespan RECENT_WAR_LOSS_TIME_LIMIT = Timespan::from_years(5);

Expand Down Expand Up @@ -603,6 +604,8 @@ namespace OpenVic {
bool can_research_tech(Technology const& technology, const Date today) const;
void start_research(Technology const& technology, const Date today);

bool evaluate_leaf(ConditionNode const& node) const;

// Sets the investment of each country in the map (rather than adding to them), leaving the rest unchanged.
void apply_foreign_investments(
fixed_point_map_t<CountryDefinition const*> const& investments,
Expand Down
6 changes: 6 additions & 0 deletions src/openvic-simulation/map/ProvinceInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "openvic-simulation/misc/GameRulesManager.hpp"
#include "openvic-simulation/modifier/StaticModifierCache.hpp"
#include "openvic-simulation/types/TypedIndices.hpp"
#include "openvic-simulation/scripts/Condition.hpp"

using namespace OpenVic;

Expand Down Expand Up @@ -399,6 +400,11 @@ void ProvinceInstance::province_tick(
rgo.rgo_tick(reusable_vectors[0]);
}

bool ProvinceInstance::evaluate_leaf(ConditionNode const& node) const {
// TODO: implement
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ProvinceInstance::evaluate_leaf is implemented as a stub that always returns false without logging a warning. This is inconsistent with other evaluate_leaf implementations (Pop, State, CountryInstance) which log warnings for unimplemented conditions. Consider adding a warning log similar to the other implementations to help with debugging.

Suggested change
// TODO: implement
spdlog::warn_s("ProvinceInstance::evaluate_leaf is not yet implemented; returning false for condition.");

Copilot uses AI. Check for mistakes.
return false;
}

bool ProvinceInstance::add_unit_instance_group(UnitInstanceGroup& group) {
using enum unit_branch_t;

Expand Down
2 changes: 2 additions & 0 deletions src/openvic-simulation/map/ProvinceInstance.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ namespace OpenVic {
> reusable_vectors
);

bool evaluate_leaf(ConditionNode const& node) const;

bool add_unit_instance_group(UnitInstanceGroup& group);
bool remove_unit_instance_group(UnitInstanceGroup const& group);

Expand Down
8 changes: 8 additions & 0 deletions src/openvic-simulation/map/State.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "openvic-simulation/population/PopType.hpp"
#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
#include "openvic-simulation/utility/Containers.hpp"
#include "openvic-simulation/scripts/Condition.hpp"

using namespace OpenVic;

Expand Down Expand Up @@ -95,6 +96,13 @@ void State::update_gamestate() {
_update_country();
}

bool State::evaluate_leaf(ConditionNode const& node) const {
std::string_view const& id = node.get_condition()->get_identifier();

spdlog::warn_s("Condition {} not implemented in State::evaluate_leaf", id);
return false;
}

void State::_update_country() {
CountryInstance* const owner_ptr = get_owner();
if (owner_ptr == previous_country_ptr) {
Expand Down
3 changes: 3 additions & 0 deletions src/openvic-simulation/map/State.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ namespace OpenVic {
struct StateManager;
struct StateSet;
struct Strata;
struct ConditionNode;

struct State : PopsAggregate {
friend struct StateManager;
Expand Down Expand Up @@ -67,6 +68,8 @@ namespace OpenVic {
}

void update_gamestate();

bool evaluate_leaf(ConditionNode const& node) const;
};

struct Region;
Expand Down
14 changes: 14 additions & 0 deletions src/openvic-simulation/population/Pop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
#include "openvic-simulation/types/TypedIndices.hpp"
#include "openvic-simulation/utility/Containers.hpp"
#include "openvic-simulation/utility/Logger.hpp"
#include "openvic-simulation/core/Typedefs.hpp"
#include "openvic-simulation/scripts/Condition.hpp"


using namespace OpenVic;
Expand Down Expand Up @@ -466,6 +468,18 @@ void Pop::allocate_for_needs(
reusable_vector.clear();
}

bool Pop::evaluate_leaf(ConditionNode const& node) const {
std::string_view const& id = node.get_condition()->get_identifier();

if (id == "consciousness") {
fixed_point_t expected = std::get<fixed_point_t>(node.get_value());
return get_consciousness() >= expected;
}
// TODO: Implement the rest
spdlog::warn_s("Condition {} not implemented in Pop::evaluate_leaf", id);
return false;
}

void Pop::pop_tick(
PopValuesFromProvince const& shared_values,
RandomU32& random_number_generator,
Expand Down
3 changes: 3 additions & 0 deletions src/openvic-simulation/population/Pop.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ namespace OpenVic {
struct RebelType;
struct Religion;
struct SellResult;
struct ConditionNode;

struct PopBase {
friend PopManager;
Expand Down Expand Up @@ -225,6 +226,8 @@ namespace OpenVic {
DECLARE_POP_MONEY_STORE_FUNCTIONS(import_subsidies)
#undef DECLARE_POP_MONEY_STORE_FUNCTIONS

bool evaluate_leaf(ConditionNode const& node) const;

void pop_tick(
PopValuesFromProvince const& shared_values,
RandomU32& random_number_generator,
Expand Down
Loading