Skip to content
121 changes: 121 additions & 0 deletions src/openvic-simulation/country/CountryInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <cstddef>
#include <cstdint>
#include <limits>
#include <compare>
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

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

#include <compare> was added but doesn't appear to be used anywhere in this file. Removing unused includes helps keep compile times and dependencies down.

Suggested change
#include <compare>

Copilot uses AI. Check for mistakes.

#include <type_safe/strong_typedef.hpp>

Expand Down Expand Up @@ -49,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 @@ -1173,6 +1175,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));
}

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;
}

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

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");
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 @@ -602,6 +603,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 @@ -14,6 +14,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 @@ -408,6 +409,11 @@ void ProvinceInstance::province_tick(
rgo.rgo_tick(reusable_vectors[0]);
}

bool ProvinceInstance::evaluate_leaf(ConditionNode const& node) const {
// TODO: implement
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 @@ -216,6 +216,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
13 changes: 13 additions & 0 deletions src/openvic-simulation/population/Pop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "openvic-simulation/core/FormatValidate.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 @@ -465,6 +466,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 @@ -32,6 +32,7 @@ namespace OpenVic {
struct RebelType;
struct Religion;
struct SellResult;
struct ConditionNode;

struct PopBase {
friend PopManager;
Expand Down Expand Up @@ -216,6 +217,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