20 float value = state.world.nation_get_military_score(n) * state.defines.alice_ai_strength_estimation_military_industrial_balance;
21 value += state.world.nation_get_industrial_score(n) * (1.f - state.defines.alice_ai_strength_estimation_military_industrial_balance);
22 for(
auto subj : state.world.nation_get_overlord_as_ruler(n)) {
23 value += subj.get_subject().get_military_score() * state.defines.alice_ai_strength_estimation_military_industrial_balance;
24 value += subj.get_subject().get_industrial_score() * (1.f - state.defines.alice_ai_strength_estimation_military_industrial_balance);
31 for(
auto dr : state.world.nation_get_diplomatic_relation(n)) {
32 if(!dr.get_are_allied())
35 auto other = dr.get_related_nations(0) != n ? dr.get_related_nations(0) : dr.get_related_nations(1);
36 if(other.get_overlord_as_subject().get_ruler() != n)
39 if(
auto sl = state.world.nation_get_in_sphere_of(n); sl)
46 for(
auto dr : state.world.nation_get_diplomatic_relation(n)) {
47 if(!dr.get_are_allied())
50 auto other = dr.get_related_nations(0) != n ? dr.get_related_nations(0) : dr.get_related_nations(1);
54 return value * state.defines.alice_ai_offensive_strength_overestimate;
59 for(
auto n : state.world.in_nation) {
60 if(state.world.nation_get_owned_province_count(n) == 0) {
61 state.world.nation_set_ai_is_threatened(n,
false);
62 state.world.nation_set_ai_rival(n, dcon::nation_id{});
66 auto ll = state.world.nation_get_last_war_loss(n);
67 float safety_factor = 1.2f;
68 if(ll && state.current_date < ll + 365 * 4) {
71 auto in_sphere_of = state.world.nation_get_in_sphere_of(n);
73 float greatest_neighbor = 0.0f;
74 for(
auto b : state.world.nation_get_nation_adjacency_as_connected_nations(n)) {
75 auto other = b.get_connected_nations(0) != n ? b.get_connected_nations(0) : b.get_connected_nations(1);
76 if(!
nations::are_allied(state, n, other) && (!in_sphere_of || in_sphere_of != other.get_in_sphere_of())) {
81 float self_str = float(state.world.nation_get_military_score(n));
82 for(
auto subj : n.get_overlord_as_ruler())
83 self_str += 0.75f * float(subj.get_subject().get_military_score());
86 bool threatened = defensive_str < safety_factor * greatest_neighbor;
87 state.world.nation_set_ai_is_threatened(n, threatened);
89 if(!n.get_ai_rival()) {
91 dcon::nation_id potential;
92 for(
auto adj : n.get_nation_adjacency()) {
93 auto other = adj.get_connected_nations(0) != n ? adj.get_connected_nations(0) : adj.get_connected_nations(1);
94 auto ol = other.get_overlord_as_subject().get_ruler();
95 if(!ol && other.get_in_sphere_of() != n && (!threatened || !
nations::are_allied(state, n, other))) {
97 if(self_str * 0.5f < other_str && other_str <= self_str * 1.5f && min_str > self_str) {
109 n.set_ai_rival(potential);
113 auto ol = n.get_ai_rival().get_overlord_as_subject().get_ruler();
114 if(ol || n.get_ai_rival().get_in_sphere_of() == n || rival_str * 2 < self_str || self_str * 2 < rival_str) {
115 n.set_ai_rival(dcon::nation_id{});
121static void internal_get_alliance_targets_by_adjacency(
sys::state& state, dcon::nation_id n, dcon::nation_id adj, std::vector<dcon::nation_id>& alliance_targets) {
122 for(
auto nb : state.world.nation_get_nation_adjacency(adj)) {
123 auto other = nb.get_connected_nations(0) != adj ? nb.get_connected_nations(0) : nb.get_connected_nations(1);
125 bool b = other.get_is_player_controlled()
126 ? state.world.unilateral_relationship_get_interested_in_alliance(state.world.get_unilateral_relationship_by_unilateral_pair(n, other))
129 alliance_targets.push_back(other.id);
133static void internal_get_alliance_targets(
sys::state& state, dcon::nation_id n, std::vector<dcon::nation_id>& alliance_targets) {
135 internal_get_alliance_targets_by_adjacency(state, n, n, alliance_targets);
136 if(!alliance_targets.empty())
140 if(
auto rival =
state.world.nation_get_ai_rival(n);
bool(rival)) {
141 internal_get_alliance_targets_by_adjacency(state, n, rival, alliance_targets);
142 if(!alliance_targets.empty())
147 for(
auto wp :
state.world.nation_get_war_participant(n)) {
148 for(
auto p :
state.world.war_get_war_participant(wp.get_war())) {
149 if(p.get_is_attacker() == !wp.get_is_attacker()) {
150 internal_get_alliance_targets_by_adjacency(state, n, p.get_nation(), alliance_targets);
151 if(!alliance_targets.empty())
159 static std::vector<dcon::nation_id> alliance_targets;
160 for(
auto n : state.world.in_nation) {
161 if(!n.get_is_player_controlled() && n.get_ai_is_threatened() && !(n.get_overlord_as_subject().get_ruler())) {
162 alliance_targets.clear();
163 internal_get_alliance_targets(state, n, alliance_targets);
164 if(!alliance_targets.empty()) {
165 std::sort(alliance_targets.begin(), alliance_targets.end(), [&](dcon::nation_id a, dcon::nation_id b) {
166 if(estimate_strength(state, a) != estimate_strength(state, b))
167 return estimate_strength(state, a) > estimate_strength(state, b);
169 return a.index() > b.index();
171 if(state.world.nation_get_is_player_controlled(alliance_targets[0])) {
176 "msg_entered_automatic_alliance_title",
177 n, dcon::nation_id{}, dcon::nation_id{},
188 static std::vector<dcon::nation_id> prune_targets;
189 for(
auto n : state.world.in_nation) {
190 if(!n.get_is_player_controlled()
191 && !n.get_ai_is_threatened()
192 && !(n.get_overlord_as_subject().get_ruler())) {
193 prune_targets.clear();
194 for(
auto dr : n.get_diplomatic_relation()) {
195 if(dr.get_are_allied()) {
196 auto other = dr.get_related_nations(0) != n ? dr.get_related_nations(0) : dr.get_related_nations(1);
197 if(other.get_in_sphere_of() != n
199 prune_targets.push_back(other);
204 if(prune_targets.empty())
207 std::sort(prune_targets.begin(), prune_targets.end(), [&](dcon::nation_id a, dcon::nation_id b) {
208 if(estimate_strength(state, a) != estimate_strength(state, b))
209 return estimate_strength(state, a) < estimate_strength(state, b);
211 return a.index() > b.index();
214 float greatest_neighbor = 0.0f;
215 auto in_sphere_of = state.world.nation_get_in_sphere_of(n);
217 for(
auto b : state.world.nation_get_nation_adjacency_as_connected_nations(n)) {
218 auto other = b.get_connected_nations(0) != n ? b.get_connected_nations(0) : b.get_connected_nations(1);
219 if(!
nations::are_allied(state, n, other) && (!in_sphere_of || in_sphere_of != other.get_in_sphere_of())) {
220 greatest_neighbor = std::max(greatest_neighbor,
estimate_strength(state, other));
225 auto ll = state.world.nation_get_last_war_loss(n);
226 float safety_factor = 1.2f;
227 if(ll && state.current_date < ll + 365 * 4) {
228 safety_factor = 1.8f;
231 auto safety_margin = defensive_str - safety_factor * greatest_neighbor;
233 for(
auto pt : prune_targets) {
235 if(weakest_str * 1.25 < safety_margin) {
236 safety_margin -= weakest_str;
239 }
else if(state.world.nation_get_infamy(pt) >= state.defines.badboy_limit) {
240 safety_margin -= weakest_str;
252 auto target_continent = state.world.province_get_continent(state.world.nation_get_capital(target));
253 auto source_continent = state.world.province_get_continent(state.world.nation_get_capital(from));
254 return (target_continent == source_continent) || bool(state.world.get_nation_adjacency_by_nation_adjacency_pair(target, from));
257static bool ai_has_mutual_enemy(
sys::state& state, dcon::nation_id from, dcon::nation_id target) {
258 auto rival_a = state.world.nation_get_ai_rival(target);
259 auto rival_b = state.world.nation_get_ai_rival(from);
261 if(rival_a && rival_a == rival_b)
284 if(!state.world.nation_get_ai_is_threatened(target))
288 if(state.world.nation_get_infamy(target) >= state.defines.badboy_limit * 0.75f)
292 if(state.world.nation_get_ai_rival(target) == from || state.world.nation_get_ai_rival(from) == target)
297 if(
bool(state.defines.alice_artificial_gp_limitant) && state.world.nation_get_is_great_power(target)) {
298 int32_t gp_count = 0;
299 for(
const auto rel : state.world.nation_get_diplomatic_relation(from)) {
300 auto n = rel.get_related_nations(rel.get_related_nations(0) == from ? 1 : 0);
301 if(rel.get_are_allied() && n.get_is_great_power()) {
309 if(
bool(state.defines.alice_spherelings_only_ally_sphere)) {
310 auto spherelord = state.world.nation_get_in_sphere_of(from);
313 if(state.world.nation_get_in_sphere_of(target) != spherelord && target != spherelord)
315 if(target == spherelord)
319 if(ai_has_mutual_enemy(state, from, target))
344 text::add_line_with_condition(state, contents,
"ai_alliance_3", state.world.nation_get_ai_rival(target) != state.local_player_nation && state.world.nation_get_ai_rival(state.local_player_nation) != target, indent + 15);
352 if(!state.world.nation_get_is_at_war(from))
354 if(state.world.nation_get_ai_rival(target) == from)
359 for(
auto wa : state.world.nation_get_war_participant(target)) {
360 auto is_attacker = wa.get_is_attacker();
361 for(
auto o : wa.get_war().get_war_participant()) {
362 if(o.get_is_attacker() != is_attacker) {
376 auto ymd_date = state.current_date.to_ymd(state.start_date);
377 auto year =
uint32_t(ymd_date.year);
378 concurrency::parallel_for(
uint32_t(0), state.world.nation_size(), [&](
uint32_t id) {
379 dcon::nation_id n{ dcon::nation_id::value_base_t(id) };
381 if(state.world.nation_get_is_player_controlled(n)
382 || state.world.nation_get_current_research(n)
383 || !state.world.nation_get_is_civilized(n)
384 || state.world.nation_get_owned_province_count(n) == 0) {
390 struct potential_techs {
391 dcon::technology_id id;
395 std::vector<potential_techs> potential;
397 for(
auto tid : state.world.in_technology) {
398 if(state.world.nation_get_active_technologies(n, tid))
401 if(state.current_date.to_ymd(state.start_date).year >= state.world.technology_get_year(tid)) {
403 dcon::technology_id prev_tech = dcon::technology_id(dcon::technology_id::value_base_t(tid.id.index() - 1));
405 if(tid.id.index() != 0 && state.world.technology_get_folder_index(prev_tech) == state.world.technology_get_folder_index(tid)) {
407 if(state.world.nation_get_active_technologies(n, prev_tech))
408 potential.push_back(potential_techs{ tid, 0.0f });
410 potential.push_back(potential_techs{ tid, 0.0f });
415 for(
auto& pt : potential) {
416 auto base = state.world.technology_get_ai_weight(pt.id);
417 if(state.world.nation_get_ai_is_threatened(n) && state.culture_definitions.tech_folders[state.world.technology_get_folder_index(pt.id)].category ==
culture::tech_category::army) {
435 pt.weight = base / cost;
438 std::sort(potential.begin(), potential.end(), [&](potential_techs& a, potential_techs& b) {
439 if(a.weight != b.weight)
440 return a.weight > b.weight;
442 return (a.id.index() ^ rval) > (b.id.index() ^ rval);
445 if(!potential.empty()) {
446 state.world.nation_set_current_research(n, potential[0].
id);
452 for(
auto t : state.world.in_technology) {
453 float base = 1000.0f;
462 auto mod = t.get_modifier();
463 auto& vals = mod.get_national_values();
465 if(vals.offsets[i] == sys::national_mod_offsets::research_points) {
467 }
else if(vals.offsets[i] == sys::national_mod_offsets::research_points_modifier) {
469 }
else if(vals.offsets[i] == sys::national_mod_offsets::education_efficiency) {
471 }
else if(vals.offsets[i] == sys::national_mod_offsets::education_efficiency_modifier) {
473 }
else if(vals.offsets[i] == sys::national_mod_offsets::pop_growth) {
475 }
else if(vals.offsets[i] == sys::national_mod_offsets::max_national_focus) {
477 }
else if(vals.offsets[i] == sys::national_mod_offsets::colonial_life_rating) {
479 }
else if(vals.offsets[i] == sys::national_mod_offsets::rgo_output) {
481 }
else if(vals.offsets[i] == sys::national_mod_offsets::factory_output) {
483 }
else if(vals.offsets[i] == sys::national_mod_offsets::factory_throughput) {
485 }
else if(vals.offsets[i] == sys::national_mod_offsets::factory_input) {
487 }
else if(vals.offsets[i] == sys::national_mod_offsets::tax_efficiency) {
492 t.set_ai_weight(base);
497 concurrency::parallel_for(
uint32_t(0), state.world.nation_size(), [&](
uint32_t id) {
498 dcon::nation_id n{ dcon::nation_id::value_base_t(id) };
500 if(state.world.nation_get_owned_province_count(n) == 0) {
506 std::vector<float> employment;
507 employment.resize(state.world.factory_type_size());
509 state.world.nation_for_each_province_ownership_as_nation(n, [&](dcon::province_ownership_id province_ownership) {
510 auto province = state.world.province_ownership_get_province(province_ownership);
511 auto sid = state.world.province_get_state_membership(province);
512 auto market = state.world.state_instance_get_market_from_local_market(sid);
513 state.world.province_for_each_factory_location_as_province(province, [&](auto location) {
514 auto factory = state.world.factory_location_get_factory(location);
515 auto type = state.world.factory_get_building_type(factory);
516 auto level = state.world.factory_get_level(factory);
517 employment[type.id.index()] +=
518 state.world.factory_get_primary_employment(factory)
520 * economy::factory_type_input_cost(
521 state, n, market, type
526 state.world.for_each_factory_type([&](dcon::factory_type_id factory_type_id) {
529 !state.world.nation_get_active_building(n, factory_type_id)
530 && !state.world.factory_type_get_is_available_from_start(factory_type_id)
532 state.world.nation_set_factory_type_experience_priority_private(n, factory_type_id, 0.f);
542 auto costs = employment[factory_type_id.index()];
543 state.world.nation_set_factory_type_experience_priority_private(n, factory_type_id, costs);
546 if(
state.world.nation_get_is_player_controlled(n)) {
552 std::vector<float>
supply;
555 state.world.for_each_commodity([&](dcon::commodity_id cid) {
559 state.world.for_each_factory_type([&](dcon::factory_type_id factory_type_id) {
561 !
state.world.nation_get_active_building(n, factory_type_id)
562 && !
state.world.factory_type_get_is_available_from_start(factory_type_id)
564 state.world.nation_set_factory_type_experience_priority_private(n, factory_type_id, 0.f);
570 auto& inputs =
state.world.factory_type_get_inputs(factory_type_id);
572 auto min_effective_supply = std::numeric_limits<float>::infinity();
574 auto input = inputs.commodity_type[i];
576 min_effective_supply = std::min(supply[input.index()] / inputs.commodity_amounts[i], min_effective_supply);
583 auto local_price =
economy::price(state, n,
state.world.factory_type_get_output(factory_type_id));
584 auto rival_price = local_price * 2.f;
585 for(
auto adj :
state.world.nation_get_nation_adjacency(n)) {
586 auto other =
adj.get_connected_nations(0) !=
n ?
adj.get_connected_nations(0) :
adj.get_connected_nations(1);
587 rival_price = std::min(rival_price,
economy::price(state, other,
state.world.factory_type_get_output(factory_type_id)));
590 auto rival_modifier = (rival_price + 0.01f) / (local_price + 0.01f);
593 rival_modifier = (rival_modifier * rival_modifier) * (rival_modifier * rival_modifier) * rival_modifier;
595 state.world.nation_set_factory_type_experience_priority_national(n, factory_type_id, min_effective_supply * rival_modifier);
601 struct weighted_nation {
605 static std::vector<weighted_nation> targets;
607 for(
auto gprl : state.world.in_gp_relationship) {
608 if(gprl.get_great_power().get_is_player_controlled()) {
611 auto& status = gprl.get_status();
612 status &=
~nations::influence::priority_mask;
619 for(
auto& n : state.great_nations) {
620 if(state.world.nation_get_is_player_controlled(n.nation))
624 for(
auto t : state.world.in_nation) {
625 if(t.get_is_great_power())
627 if(t.get_owned_province_count() == 0)
629 if(t.get_in_sphere_of() == n.nation)
636 for(
auto c : state.world.in_commodity) {
638 auto cweight = std::min(
647 if(t.get_in_sphere_of()) {
652 if(t.get_primary_culture() == state.world.nation_get_primary_culture(n.nation)) {
657 else if(t.get_primary_culture().get_group_from_culture_group_membership() == state.world.nation_get_primary_culture(n.nation).get_group_from_culture_group_membership()) {
666 bool is_reachable =
false;
667 for(
auto adj : state.world.nation_get_nation_adjacency(t)) {
668 auto casted_adj = adj.get_connected_nations(0) != t ? adj.get_connected_nations(0) : adj.get_connected_nations(1);
669 if(casted_adj == n.nation) {
673 if(casted_adj.get_in_sphere_of() == n.nation) {
680 if(state.world.nation_get_central_ports(t) > 0) {
685 if(state.world.get_nation_adjacency_by_nation_adjacency_pair(n.nation, t.id)) {
694 targets.push_back(weighted_nation{ t.id, weight });
697 std::sort(targets.begin(), targets.end(), [](weighted_nation
const& a, weighted_nation
const& b) {
698 if(a.weight != b.weight)
699 return a.weight > b.weight;
701 return a.id.index() < b.id.index();
705 for(; i < 2 && i < targets.size(); ++i) {
706 auto rel = state.world.get_gp_relationship_by_gp_influence_pair(targets[i].
id, n.nation);
708 rel = state.world.force_create_gp_relationship(targets[i].
id, n.nation);
711 for(; i < 4 && i < targets.size(); ++i) {
712 auto rel = state.world.get_gp_relationship_by_gp_influence_pair(targets[i].
id, n.nation);
714 rel = state.world.force_create_gp_relationship(targets[i].
id, n.nation);
717 for(; i < 6 && i < targets.size(); ++i) {
718 auto rel = state.world.get_gp_relationship_by_gp_influence_pair(targets[i].
id, n.nation);
720 rel = state.world.force_create_gp_relationship(targets[i].
id, n.nation);
727 for(
auto gprl : state.world.in_gp_relationship) {
728 if(gprl.get_great_power().get_is_player_controlled()) {
741 auto current_sphere = gprl.get_influence_target().get_in_sphere_of();
754 && state.defines.removefromsphere_influence_cost <= gprl.get_influence()
757 && (state.world.nation_get_infamy(gprl.get_great_power()) + state.defines.removefromsphere_infamy_cost) < state.defines.badboy_limit
767 for(
auto f : state.world.in_national_focus) {
768 if(f.get_promotion_amount() > 0) {
769 if(f.get_promotion_type() == state.culture_definitions.clergy)
770 state.national_definitions.clergy_focus = f;
771 if(f.get_promotion_type() == state.culture_definitions.soldiers)
772 state.national_definitions.soldier_focus = f;
773 if(f.get_promotion_type() == state.culture_definitions.aristocrat)
774 state.national_definitions.aristocrat_focus = f;
775 if(f.get_promotion_type() == state.culture_definitions.capitalists)
776 state.national_definitions.capitalist_focus = f;
777 if(f.get_promotion_type() == state.culture_definitions.primary_factory_worker)
778 state.national_definitions.primary_factory_worker_focus = f;
779 if(f.get_promotion_type() == state.culture_definitions.secondary_factory_worker)
780 state.national_definitions.secondary_factory_worker_focus = f;
786 for(
auto si : state.world.in_state_instance) {
787 if(!si.get_nation_from_state_ownership().get_is_player_controlled())
788 si.set_owner_focus(dcon::national_focus_id{});
791 for(
auto n : state.world.in_nation) {
792 if(n.get_is_player_controlled())
794 if(n.get_owned_province_count() == 0)
797 n.set_state_from_flashpoint_focus(dcon::state_instance_id{});
800 if(num_focuses_total <= 0)
803 auto base_opt = state.world.pop_type_get_research_optimum(state.culture_definitions.clergy);
805 bool max_clergy = clergy_frac >= base_opt;
807 static std::vector<dcon::state_instance_id> ordered_states;
808 ordered_states.clear();
809 for(
auto si : n.get_state_ownership()) {
810 ordered_states.push_back(si.get_state().id);
812 std::sort(ordered_states.begin(), ordered_states.end(), [&](
auto a,
auto b) {
813 auto apop = state.world.state_instance_get_demographics(a, demographics::total);
814 auto bpop = state.world.state_instance_get_demographics(b, demographics::total);
818 return a.index() < b.index();
820 bool threatened = n.get_ai_is_threatened() || n.get_is_at_war();
821 for(
uint32_t i = 0; num_focuses_total > 0 && i < ordered_states.size(); ++i) {
822 auto prov = state.world.state_instance_get_capital(ordered_states[i]);
825 auto nf = state.national_definitions.soldier_focus;
826 auto k = state.world.national_focus_get_limit(nf);
829 state.world.state_instance_set_owner_focus(ordered_states[i], state.national_definitions.soldier_focus);
833 auto total = state.world.state_instance_get_demographics(ordered_states[i],
demographics::total);
834 auto cfrac = state.world.state_instance_get_demographics(ordered_states[i],
demographics::to_key(state, state.culture_definitions.clergy)) / total;
835 if(cfrac < state.defines.max_clergy_for_literacy * 0.8f && !state.world.province_get_is_colonial(state.world.state_instance_get_capital(ordered_states[i]))) {
836 auto nf = state.national_definitions.clergy_focus;
837 auto k = state.world.national_focus_get_limit(nf);
840 state.world.state_instance_set_owner_focus(ordered_states[i], state.national_definitions.clergy_focus);
847 auto cfrac = state.world.state_instance_get_demographics(ordered_states[i],
demographics::to_key(state, state.culture_definitions.clergy)) / state.world.state_instance_get_demographics(ordered_states[i],
demographics::total);
848 if(cfrac < base_opt * 1.2f && !state.world.province_get_is_colonial(state.world.state_instance_get_capital(ordered_states[i]))) {
849 auto nf = state.national_definitions.clergy_focus;
850 auto k = state.world.national_focus_get_limit(nf);
853 state.world.state_instance_set_owner_focus(ordered_states[i], state.national_definitions.clergy_focus);
860 for(
uint32_t i = 0; num_focuses_total > 0 && i < ordered_states.size(); ++i) {
861 auto prov = state.world.state_instance_get_capital(ordered_states[i]);
863 if(state.world.province_get_is_colonial(state.world.state_instance_get_capital(ordered_states[i]))) {
867 auto total = state.world.state_instance_get_demographics(ordered_states[i],
demographics::total);
868 auto pw_num = state.world.state_instance_get_demographics(ordered_states[i],
demographics::to_key(state, state.culture_definitions.primary_factory_worker));
869 auto pw_employed = state.world.state_instance_get_demographics(ordered_states[i],
demographics::to_employment_key(state, state.culture_definitions.primary_factory_worker));
870 auto sw_num = state.world.state_instance_get_demographics(ordered_states[i],
demographics::to_key(state, state.culture_definitions.secondary_factory_worker));
871 auto sw_employed = state.world.state_instance_get_demographics(ordered_states[i],
demographics::to_employment_key(state, state.culture_definitions.secondary_factory_worker));
872 auto sw_frac = sw_num / std::max(pw_num + sw_num, 1.0f);
873 auto ideal_swfrac = (1.f - state.economy_definitions.craftsmen_fraction);
876 if((pw_employed >= pw_num || pw_num < 1.0f)) {
877 auto nf = state.national_definitions.primary_factory_worker_focus;
878 auto k = state.world.national_focus_get_limit(nf);
883 state.world.state_instance_set_owner_focus(ordered_states[i], nf);
886 }
else if(pw_num > 1.0f && pw_employed > 1.0f && int8_t(sw_frac * 100.f) != int8_t(ideal_swfrac * 100.f)) {
887 auto nf = state.national_definitions.secondary_factory_worker_focus;
888 auto k = state.world.national_focus_get_limit(nf);
893 state.world.state_instance_set_owner_focus(ordered_states[i], nf);
900 auto rules = n.get_combined_issue_rules();
902 auto nf = state.national_definitions.capitalist_focus;
903 auto k = state.world.national_focus_get_limit(nf);
906 state.world.state_instance_set_owner_focus(ordered_states[i], nf);
910 auto nf = state.national_definitions.aristocrat_focus;
911 auto k = state.world.national_focus_get_limit(nf);
914 state.world.state_instance_set_owner_focus(ordered_states[i], nf);
924 using decision_nation_pair = std::pair<dcon::decision_id, dcon::nation_id>;
925 concurrency::combinable<std::vector<decision_nation_pair, dcon::cache_aligned_allocator<decision_nation_pair>>> decisions_taken;
928 uint32_t d_block_size = state.world.decision_size() / 32;
930 auto d_block_end = state.world.decision_size();
933 concurrency::parallel_for(d_block_size * block_index, d_block_end, [&](
uint32_t i) {
934 auto d = dcon::decision_id{ dcon::decision_id::value_base_t(i) };
935 auto e = state.world.decision_get_effect(d);
937 auto potential = state.world.decision_get_potential(d);
938 auto allow = state.world.decision_get_allow(d);
939 auto ai_will_do = state.world.decision_get_ai_will_do(d);
940 ve::execute_serial_fast<dcon::nation_id>(state.world.nation_size(), [&](
auto ids) {
942 ve::mask_vector filter_a = !state.world.nation_get_is_player_controlled(ids)
943 && state.world.nation_get_owned_province_count(ids) != 0;
944 if(ve::compress_mask(filter_a).v != 0) {
946 ve::mask_vector filter_b = potential
947 ? filter_a && (trigger::evaluate(state, potential, trigger::to_generic(ids), trigger::to_generic(ids), 0))
949 if(ve::compress_mask(filter_b).v != 0) {
950 ve::mask_vector filter_c = allow
951 ? filter_b && (trigger::evaluate(state, allow, trigger::to_generic(ids), trigger::to_generic(ids), 0))
953 if(ve::compress_mask(filter_c).v != 0) {
954 ve::mask_vector filter_d = ai_will_do
955 ? filter_c && (trigger::evaluate_multiplicative_modifier(state, ai_will_do, trigger::to_generic(ids), trigger::to_generic(ids), 0) > 0.0f)
957 ve::apply([&](dcon::nation_id n, bool passed_filter) {
959 decisions_taken.local().push_back(decision_nation_pair(d, n));
969 auto total_vector = decisions_taken.combine([](
auto& a,
auto& b) {
970 std::vector<decision_nation_pair, dcon::cache_aligned_allocator<decision_nation_pair>> result(a.begin(), a.end());
971 result.insert(result.end(), b.begin(), b.end());
975 std::sort(total_vector.begin(), total_vector.end(), [&](
auto a,
auto b) {
979 return na.index() < nb.index();
980 return a.first.index() < b.first.index();
983 for(
const auto& v : total_vector) {
986 auto e =
state.world.decision_get_effect(d);
996 "msg_decision_title",
997 n, dcon::nation_id{}, dcon::nation_id{},
1005 auto iid = state.world.political_party_get_ideology(pid);
1019 auto last_change = state.world.nation_get_ruling_party_last_appointed(n);
1020 if(last_change && state.current_date < last_change + 365)
1031 for(
auto n : state.world.in_nation) {
1033 if(n.get_is_player_controlled() || n.get_owned_province_count() == 0)
1037 auto gov = n.get_government_type();
1038 auto identity = n.get_identity_from_identity_holder();
1039 auto start = state.world.national_identity_get_political_party_first(identity).id.index();
1040 auto end = start + state.world.national_identity_get_political_party_count(identity);
1042 dcon::political_party_id target;
1044 for(int32_t i = start; i < end; i++) {
1045 auto pid = dcon::political_party_id(uint16_t(i));
1048 if(support > max_support) {
1050 max_support = support;
1055 assert(target != state.world.nation_get_ruling_party(n));
1064 assert(desired_types.empty());
1068 if(desired_types.empty()) {
1069 for(
auto type : state.world.in_factory_type) {
1070 if(n.get_active_building(type) || type.get_is_available_from_start()) {
1071 auto& inputs = type.get_inputs();
1072 bool lacking_input =
false;
1073 bool lacking_output = m.get_demand_satisfaction(type.get_output()) < 0.98f;
1076 if(inputs.commodity_type[i]) {
1077 if(m.get_demand_satisfaction(inputs.commodity_type[i]) < 0.5f)
1078 lacking_input =
true;
1088 if((output - input) / input > 10.f)
1089 desired_types.push_back(type.id);
1096 assert(desired_types.empty());
1103 if(desired_types.empty()) {
1104 for(
auto type : state.world.in_factory_type) {
1105 if(n.get_active_building(type) || type.get_is_available_from_start()) {
1106 auto& inputs = type.get_inputs();
1107 bool lacking_input =
false;
1108 bool lacking_output = m.get_demand_satisfaction(type.get_output()) < 0.98f;
1111 if(inputs.commodity_type[i]) {
1112 if(m.get_demand_satisfaction(inputs.commodity_type[i]) < 0.5f)
1113 lacking_input =
true;
1123 if((output - input) / input > 2.f)
1124 desired_types.push_back(type.id);
1131 if(desired_types.empty()) {
1132 for(
auto type : state.world.in_factory_type) {
1133 if(n.get_active_building(type) || type.get_is_available_from_start()) {
1134 auto& inputs = type.get_inputs();
1135 bool lacking_input =
false;
1136 bool lacking_output = m.get_demand_satisfaction(type.get_output()) < 0.98f;
1139 if(inputs.commodity_type[i]) {
1140 if(m.get_demand_satisfaction(inputs.commodity_type[i]) < 0.5f)
1141 lacking_input =
true;
1151 if((!lacking_input && (lacking_output || ((output - input) / cost < 365.f))) || (output - input) / input > 1.00f)
1152 desired_types.push_back(type.id);
1158 if(desired_types.empty()) {
1159 for(
auto type : state.world.in_factory_type) {
1160 if(n.get_active_building(type) || type.get_is_available_from_start()) {
1161 auto& inputs = type.get_inputs();
1162 bool lacking_input =
false;
1163 bool lacking_output = m.get_demand_satisfaction(type.get_output()) < 0.98f;
1166 if(inputs.commodity_type[i]) {
1167 if(m.get_demand_satisfaction(inputs.commodity_type[i]) < 0.5f)
1168 lacking_input =
true;
1177 if((output - input) / input > 0.3f)
1178 desired_types.push_back(type.id);
1185 assert(desired_types.empty());
1190 if(desired_types.empty()) {
1191 for(
auto type : state.world.in_factory_type) {
1192 if(n.get_active_building(type) || type.get_is_available_from_start()) {
1197 if((output - input) / input > 20.f)
1198 desired_types.push_back(type.id);
1205 assert(desired_types.empty());
1212 if(desired_types.empty()) {
1213 for(
auto type : state.world.in_factory_type) {
1214 if(n.get_active_building(type) || type.get_is_available_from_start()) {
1215 auto& inputs = type.get_inputs();
1216 bool lacking_input =
false;
1217 bool lacking_output = m.get_demand_satisfaction(type.get_output()) < 0.98f;
1220 if(inputs.commodity_type[i]) {
1221 if(m.get_demand_satisfaction(inputs.commodity_type[i]) < 0.5f)
1222 lacking_input =
true;
1232 if((lacking_output || ((output - input) / cost < 365.f)))
1233 desired_types.push_back(type.id);
1239 if(desired_types.empty()) {
1240 for(
auto type : state.world.in_factory_type) {
1241 if(n.get_active_building(type) || type.get_is_available_from_start()) {
1242 auto& inputs = type.get_inputs();
1243 bool lacking_input =
false;
1244 bool lacking_output = m.get_demand_satisfaction(type.get_output()) < 0.98f;
1247 if(inputs.commodity_type[i]) {
1248 if(m.get_demand_satisfaction(inputs.commodity_type[i]) < 0.5f)
1249 lacking_input =
true;
1258 auto profitabilitymark = std::max(0.01f, cost * 10.f / treasury);
1260 if((lacking_output || ((output - input) / input > profitabilitymark)))
1261 desired_types.push_back(type.id);
1269 for(
auto fac : state.world.nation_get_rebellion_within(n)) {
1270 for(
auto ar : state.world.rebel_faction_get_army_rebel_control(fac.get_rebels())) {
1271 auto regs = ar.get_army().get_army_membership();
1272 total += int32_t(regs.end() - regs.begin());
1284 if(state.world.nation_get_ai_is_threatened(nation)) {
1288 if(fid.get_is_at_war()) {
1292 if(state.world.nation_get_ai_strategy(nation) == ai_strategies::militant) {
1305 auto in_sphere_of = state.world.nation_get_in_sphere_of(nation);
1308 dcon::nation_id greatest_neighbor;
1309 auto greatest_neighbor_strength = 0.0f;
1312 for(
auto b : state.world.nation_get_nation_adjacency_as_connected_nations(nation)) {
1313 auto other = b.get_connected_nations(0) != nation ? b.get_connected_nations(0) : b.get_connected_nations(1);
1314 if(!
nations::are_allied(state, nation, other) && (!in_sphere_of || in_sphere_of != other.get_in_sphere_of())) {
1317 if(other_str > greatest_neighbor_strength && other_str < own_str * 10.0f) {
1318 greatest_neighbor_strength = other_str;
1319 greatest_neighbor = other;
1326 for(
auto p : state.world.nation_get_army_control(greatest_neighbor)) {
1327 auto frange = p.get_army().get_army_membership();
1328 total += int16_t(frange.end() - frange.begin());
1334 auto identity = fid.get_identity_from_identity_holder();
1337 identity = fid2.get_identity_from_identity_holder();
1341 return int16_t(std::clamp(total *
double(factor), 0.1 * fid.get_recruitable_regiments(), 1.0 * fid.get_recruitable_regiments()));
1345 for(
auto n : state.world.in_nation) {
1347 if(n.get_owned_province_count() == 0 || !n.get_is_civilized())
1350 if(n.get_is_player_controlled()) {
1368 float budget = treasury * 0.5f + base_income - estimated_construction_costs * 2.f;
1369 float additional_expenses = 0.f;
1370 float days_prepaid = 10.f;
1371 auto rules = n.get_combined_issue_rules();
1379 static std::vector<dcon::state_instance_id> ordered_states;
1380 ordered_states.clear();
1381 for(
auto si : n.get_state_ownership()) {
1382 if(si.get_state().get_capital().get_is_colonial() ==
false)
1383 ordered_states.push_back(si.get_state().id);
1385 std::sort(ordered_states.begin(), ordered_states.end(), [&](
auto a,
auto b) {
1386 auto apop = state.world.state_instance_get_demographics(a, demographics::total);
1387 auto bpop = state.world.state_instance_get_demographics(b, demographics::total);
1391 return a.index() < b.index();
1395 static::std::vector<dcon::factory_type_id> craved_types;
1398 if(!craved_types.empty()) {
1402 for(
auto si : ordered_states) {
1404 auto market = state.world.state_instance_get_market_from_local_market(si);
1406 if(budget - additional_expenses <= 0.f)
1409 auto m = state.world.state_instance_get_market_from_local_market(si);
1410 craved_types.clear();
1414 auto pw_num = state.world.state_instance_get_demographics(si,
1416 pw_num += state.world.state_instance_get_demographics(si,
1418 auto pw_employed = state.world.state_instance_get_demographics(si,
1420 pw_employed += state.world.state_instance_get_demographics(si,
1423 if(pw_employed >=
float(pw_num) * 2.5f && pw_num > 0.0f)
1426 auto type_selection = craved_types[
rng::get_random(state,
uint32_t(n.id.index() + int32_t(budget))) % craved_types.size()];
1432 bool already_in_progress = [&]() {
1433 for(
auto p : state.world.state_instance_get_state_building_construction(si)) {
1434 if(p.get_type() == type_selection)
1440 if(already_in_progress)
1444 bool present_in_location =
false;
1445 bool under_cap =
false;
1448 for(
auto fac : state.world.province_get_factory_location(p)) {
1449 auto type = fac.get_factory().get_building_type();
1450 if(type_selection == type) {
1451 under_cap = fac.get_factory().get_primary_employment() * state.world.market_get_labor_unskilled_demand_satisfaction(market) < 0.9f;
1452 present_in_location = true;
1461 auto expected_item_cost = 0.f;
1462 auto costs = state.world.factory_type_get_construction_costs(type_selection);
1463 auto time = state.world.factory_type_get_construction_time(type_selection);
1464 for(
uint32_t i = 0; i < costs.set_size; ++i) {
1465 if(costs.commodity_type[i]) {
1466 expected_item_cost +=
1467 costs.commodity_amounts[i]
1476 if(budget - additional_expenses - expected_item_cost <= 0.f)
1479 if(present_in_location) {
1481 auto new_up = fatten(state.world, state.world.force_create_state_building_construction(si, n));
1482 new_up.set_is_pop_project(
false);
1483 new_up.set_is_upgrade(
true);
1484 new_up.set_type(type_selection);
1486 additional_expenses += expected_item_cost;
1493 if(num_factories < int32_t(state.defines.factories_per_state)) {
1494 auto new_up = fatten(state.world, state.world.force_create_state_building_construction(si, n));
1495 new_up.set_is_pop_project(
false);
1496 new_up.set_is_upgrade(
false);
1497 new_up.set_type(type_selection);
1498 additional_expenses += expected_item_cost;
1509 for(
auto si : ordered_states) {
1511 auto market = state.world.state_instance_get_market_from_local_market(si);
1513 if(budget - additional_expenses <= 0.f)
1517 for(
auto fac : state.world.province_get_factory_location(p)) {
1518 auto type = fac.get_factory().get_building_type();
1521 auto unprofitable = fac.get_factory().get_unprofitable();
1522 auto factory_level = fac.get_factory().get_level();
1523 auto primary_employment = fac.get_factory().get_primary_employment() * state.world.market_get_labor_unskilled_demand_satisfaction(market);
1525 if(!unprofitable && factory_level < uint8_t(255) && primary_employment >= 0.9f) {
1527 auto ug_in_progress = false;
1528 for(auto c : state.world.state_instance_get_state_building_construction(si)) {
1529 if(c.get_type() == type) {
1530 ug_in_progress = true;
1535 auto expected_item_cost = 0.f;
1536 auto& costs = state.world.factory_type_get_construction_costs(type);
1537 auto& time = state.world.factory_type_get_construction_time(type);
1538 for(uint32_t i = 0; i < costs.set_size; ++i) {
1539 if(costs.commodity_type[i]) {
1540 expected_item_cost +=
1541 costs.commodity_amounts[i]
1542 * economy::price(state, market, costs.commodity_type[i])
1550 if(budget - additional_expenses - expected_item_cost <= 0.f)
1553 if(!ug_in_progress) {
1554 auto new_up = fatten(state.world, state.world.force_create_state_building_construction(si, n));
1555 new_up.set_is_pop_project(false);
1556 new_up.set_is_upgrade(true);
1557 new_up.set_type(type);
1559 additional_expenses += expected_item_cost;
1568 static::std::vector<dcon::factory_type_id> desired_types;
1571 if(!desired_types.empty()) {
1575 for(
auto si : ordered_states) {
1577 auto market = state.world.state_instance_get_market_from_local_market(si);
1579 if(budget - additional_expenses <= 0.f)
1582 auto m = state.world.state_instance_get_market_from_local_market(si);
1583 desired_types.clear();
1587 auto pw_num = state.world.state_instance_get_demographics(si,
1589 pw_num += state.world.state_instance_get_demographics(si,
1591 auto pw_employed = state.world.state_instance_get_demographics(si,
1593 pw_employed += state.world.state_instance_get_demographics(si,
1596 if(pw_employed >=
float(pw_num) * 2.5f && pw_num > 0.0f)
1599 auto type_selection = desired_types[
rng::get_random(state,
uint32_t(n.id.index() + int32_t(budget))) % desired_types.size()];
1605 bool already_in_progress = [&]() {
1606 for(
auto p : state.world.state_instance_get_state_building_construction(si)) {
1607 if(p.get_type() == type_selection)
1613 if(already_in_progress)
1617 bool present_in_location =
false;
1618 bool under_cap =
false;
1621 for(
auto fac : state.world.province_get_factory_location(p)) {
1622 auto type = fac.get_factory().get_building_type();
1623 if(type_selection == type) {
1624 under_cap = fac.get_factory().get_primary_employment() * state.world.market_get_labor_unskilled_demand_satisfaction(market) < 0.9f;
1625 present_in_location = true;
1634 auto expected_item_cost = 0.f;
1635 auto costs = state.world.factory_type_get_construction_costs(type_selection);
1636 auto time = state.world.factory_type_get_construction_time(type_selection);
1637 for(
uint32_t i = 0; i < costs.set_size; ++i) {
1638 if(costs.commodity_type[i]) {
1639 expected_item_cost +=
1640 costs.commodity_amounts[i]
1649 if(budget - additional_expenses - expected_item_cost <= 0.f)
1652 if(present_in_location) {
1654 auto new_up = fatten(state.world, state.world.force_create_state_building_construction(si, n));
1655 new_up.set_is_pop_project(
false);
1656 new_up.set_is_upgrade(
true);
1657 new_up.set_type(type_selection);
1659 additional_expenses += expected_item_cost;
1666 if(num_factories < int32_t(state.defines.factories_per_state)) {
1667 auto new_up = fatten(state.world, state.world.force_create_state_building_construction(si, n));
1668 new_up.set_is_pop_project(
false);
1669 new_up.set_is_upgrade(
false);
1670 new_up.set_type(type_selection);
1671 additional_expenses += expected_item_cost;
1681 if(0.9f *
n.get_recruitable_regiments() >
n.get_active_regiments())
1684 static std::vector<dcon::province_id> project_provs;
1685 project_provs.clear();
1688 if(budget - additional_expenses >= 0.f) {
1689 project_provs.clear();
1690 for(
auto o :
n.get_province_ownership()) {
1691 if(!o.get_province().get_is_coast())
1693 if(n != o.get_province().get_nation_from_province_control())
1703 int32_t min_build = int32_t(o.get_province().get_modifier_values(sys::provincial_mod_offsets::min_build_naval_base));
1705 if(max_local_lvl - current_lvl - min_build <= 0)
1709 project_provs.push_back(o.get_province().id);
1713 auto cap =
n.get_capital();
1714 std::sort(project_provs.begin(), project_provs.end(), [&](dcon::province_id a, dcon::province_id b) {
1715 auto a_dist = province::sorting_distance(state, a, cap);
1716 auto b_dist = province::sorting_distance(state, b, cap);
1717 if(a_dist != b_dist)
1718 return a_dist < b_dist;
1720 return a.index() < b.index();
1722 if(!project_provs.empty()) {
1723 auto si =
state.world.province_get_state_membership(project_provs[0]);
1724 auto market =
state.world.state_instance_get_market_from_local_market(si);
1728 auto expected_item_cost = 0.f;
1731 for(
uint32_t i = 0; i < costs.set_size; ++i) {
1732 if(costs.commodity_type[i]) {
1733 expected_item_cost +=
1734 costs.commodity_amounts[i]
1743 if(budget - additional_expenses - expected_item_cost <= 0.f)
1747 si.set_naval_base_is_taken(
true);
1748 auto new_rr =
fatten(
state.world,
state.world.force_create_province_building_construction(project_provs[0], n));
1749 new_rr.set_is_pop_project(
false);
1751 additional_expenses += expected_item_cost;
1759 dcon::provincial_modifier_value mod;
1760 } econ_buildable[3] = {
1765 for(
auto i = 0; i < 3; i++) {
1766 if(econ_buildable[i].buildable && budget - additional_expenses > 0) {
1767 project_provs.clear();
1768 for(
auto o :
n.get_province_ownership()) {
1769 if(n != o.get_province().get_nation_from_province_control())
1773 int32_t current_lvl =
state.world.province_get_building_level(o.get_province(),
uint8_t(econ_buildable[i].type));
1774 int32_t max_local_lvl =
state.world.nation_get_max_building_level(n,
uint8_t(econ_buildable[i].type));
1775 int32_t min_build = int32_t(
state.world.province_get_modifier_values(o.get_province(), econ_buildable[i].mod));
1776 if(max_local_lvl - current_lvl - min_build <= 0)
1779 project_provs.push_back(o.get_province().id);
1782 auto cap =
n.get_capital();
1783 std::sort(project_provs.begin(), project_provs.end(), [&](dcon::province_id a, dcon::province_id b) {
1784 auto a_dist = province::sorting_distance(state, a, cap);
1785 auto b_dist = province::sorting_distance(state, b, cap);
1786 if(a_dist != b_dist)
1787 return a_dist < b_dist;
1789 return a.index() < b.index();
1791 for(
uint32_t j = 0; j < project_provs.size() && budget - additional_expenses > 0; ++j) {
1792 auto sid =
state.world.province_get_state_membership(project_provs[j]);
1793 auto market =
state.world.state_instance_get_market_from_local_market(sid);
1797 auto expected_item_cost = 0.f;
1798 auto& costs =
state.economy_definitions.building_definitions[
uint8_t(econ_buildable[i].type)].cost;
1799 auto&
time =
state.economy_definitions.building_definitions[
uint8_t(econ_buildable[i].type)].time;
1800 for(
uint32_t k = 0; k < costs.set_size; ++k) {
1801 if(costs.commodity_type[k]) {
1802 expected_item_cost +=
1803 costs.commodity_amounts[k]
1812 if(budget - additional_expenses - expected_item_cost <= 0.f)
1815 auto new_proj =
fatten(
state.world,
state.world.force_create_province_building_construction(project_provs[j], n));
1816 new_proj.set_is_pop_project(
false);
1817 new_proj.set_type(
uint8_t(econ_buildable[i].type));
1818 additional_expenses += expected_item_cost;
1823 if(0.95f *
n.get_recruitable_regiments() >
n.get_active_regiments())
1827 if(budget - additional_expenses > 0.f) {
1828 project_provs.clear();
1830 for(
auto o :
n.get_province_ownership()) {
1831 if(n != o.get_province().get_nation_from_province_control())
1839 int32_t min_build = int32_t(
state.world.province_get_modifier_values(o.get_province(), sys::provincial_mod_offsets::min_build_fort));
1841 if(max_local_lvl - current_lvl - min_build <= 0)
1845 project_provs.push_back(o.get_province().id);
1849 auto cap =
n.get_capital();
1850 std::sort(project_provs.begin(), project_provs.end(), [&](dcon::province_id a, dcon::province_id b) {
1851 auto a_dist = province::sorting_distance(state, a, cap);
1852 auto b_dist = province::sorting_distance(state, b, cap);
1853 if(a_dist != b_dist)
1854 return a_dist < b_dist;
1856 return a.index() < b.index();
1859 for(
uint32_t i = 0; i < project_provs.size() && budget - additional_expenses > 0.f; ++i) {
1861 auto sid =
state.world.province_get_state_membership(project_provs[i]);
1862 auto market =
state.world.state_instance_get_market_from_local_market(sid.id);
1866 auto expected_item_cost = 0.f;
1869 for(
uint32_t k = 0; k < costs.set_size; ++k) {
1870 if(costs.commodity_type[k]) {
1871 expected_item_cost +=
1872 costs.commodity_amounts[k]
1883 if(budget - additional_expenses - expected_item_cost <= 0.f)
1886 auto new_rr =
fatten(
state.world,
state.world.force_create_province_building_construction(project_provs[i], n));
1887 new_rr.set_is_pop_project(
false);
1889 additional_expenses += expected_item_cost;
1896 static std::vector<dcon::state_definition_id> investments;
1897 static std::vector<int32_t> free_points;
1899 investments.clear();
1900 investments.resize(
uint32_t(state.defines.colonial_rank));
1902 free_points.clear();
1903 free_points.resize(
uint32_t(state.defines.colonial_rank), -1);
1907 for(
auto col : state.world.in_colonization) {
1908 auto n = col.get_colonizer();
1909 if(n.get_is_player_controlled() ==
false
1910 && n.get_rank() <= uint16_t(state.defines.colonial_rank)
1911 && !investments[n.get_rank() - 1]
1912 && col.get_state().get_colonization_stage() <=
uint8_t(2)
1914 && col.get_state() != state.world.state_instance_get_definition(state.crisis_state_instance)
1915 && (!state.crisis_war || n.get_is_at_war() ==
false)
1918 if(state.crisis_attacker_wargoals.size() > 0) {
1919 auto first_wg = state.crisis_attacker_wargoals.at(0);
1920 if(first_wg.state == col.get_state()) {
1925 auto crange = col.get_state().get_colonization();
1926 if(crange.end() - crange.begin() > 1) {
1927 if(col.get_last_investment() + int32_t(state.defines.colonization_days_between_investment) <= state.current_date) {
1929 if(free_points[n.get_rank() - 1] < 0) {
1934 if(col.get_state().get_colonization_stage() == 1) {
1935 cost = int32_t(state.defines.colonization_interest_cost);
1936 }
else if(col.get_level() <= 4) {
1937 cost = int32_t(state.defines.colonization_influence_cost);
1940 int32_t(state.defines.colonization_extra_guard_cost * (col.get_level() - 4) + state.defines.colonization_influence_cost);
1942 if(free_points[n.get_rank() - 1] >= cost) {
1943 investments[n.get_rank() - 1] = col.get_state().id;
1949 for(
uint32_t i = 0; i < investments.size(); ++i) {
1955 static std::vector<int32_t> free_points;
1956 free_points.clear();
1957 free_points.resize(
uint32_t(state.defines.colonial_rank), -1);
1958 for(int32_t i = 0; i < int32_t(state.defines.colonial_rank); ++i) {
1959 if(state.world.nation_get_is_player_controlled(state.nations_by_rank[i])) {
1969 for(
auto sd : state.world.in_state_definition) {
1970 if(sd.get_colonization_stage() <= 1) {
1971 bool has_unowned_land =
false;
1973 dcon::province_id coastal_target;
1974 for(
auto p : state.world.state_definition_get_abstract_state_membership(sd)) {
1975 if(!p.get_province().get_nation_from_province_ownership()) {
1976 if(p.get_province().get_is_coast() && !coastal_target) {
1977 coastal_target = p.get_province();
1979 if(p.get_province().id.index() < state.province_definitions.first_sea_province.index())
1980 has_unowned_land =
true;
1983 if(has_unowned_land) {
1984 for(int32_t i = 0; i < int32_t(state.defines.colonial_rank); ++i) {
1985 if(free_points[i] > 0) {
1986 bool adjacent =
false;
1988 free_points[i] -= int32_t(state.defines.colonization_interest_cost_initial + (adjacent ? state.defines.colonization_interest_cost_neighbor_modifier : 0.0f));
1990 auto new_rel = fatten(state.world, state.world.force_create_colonization(sd, state.nations_by_rank[i]));
1991 new_rel.set_level(
uint8_t(1));
1992 new_rel.set_last_investment(state.current_date);
1993 new_rel.set_points_invested(uint16_t(state.defines.colonization_interest_cost_initial + (adjacent ? state.defines.colonization_interest_cost_neighbor_modifier : 0.0f)));
1995 state.world.state_definition_set_colonization_stage(sd,
uint8_t(1));
2005 for(
auto si : state.world.in_state_instance) {
2006 if(si.get_capital().get_is_colonial() && si.get_nation_from_state_ownership().get_is_player_controlled() ==
false) {
2015 for(
auto n : state.world.in_nation) {
2016 if(!n.get_is_player_controlled() && !n.get_is_civilized() && n.get_modifier_values(sys::national_mod_offsets::civilization_progress_modifier) >= 1.0f) {
2023 for(
auto n : state.world.in_nation) {
2024 if(n.get_is_player_controlled() || n.get_owned_province_count() == 0)
2027 if(n.get_is_civilized()) {
2030 dcon::issue_option_id iss;
2031 float max_support = 0.0f;
2033 for(
auto m : state.world.nation_get_movement_within(n)) {
2034 if(m.get_movement().get_associated_issue_option() && m.get_movement().get_pop_support() > max_support) {
2035 iss = m.get_movement().get_associated_issue_option();
2036 max_support = m.get_movement().get_pop_support();
2041 iss = dcon::issue_option_id{};
2042 state.world.for_each_issue_option([&](dcon::issue_option_id io) {
2044 float support = 0.f;
2045 for(
const auto poid : state.world.nation_get_province_ownership_as_nation(n)) {
2046 for(auto plid : state.world.province_get_pop_location_as_province(poid.get_province())) {
2047 float weigth = plid.get_pop().get_size() * 0.001f;
2048 support += pop_demographics::get_demo(state, plid.get_pop(), pop_demographics::to_key(state, io)) * weigth;
2051 if(support > max_support) {
2053 max_support = support;
2062 dcon::reform_option_id cheap_r;
2063 float cheap_cost = 0.0f;
2068 for(
auto r : state.world.in_reform_option) {
2071 auto reform = state.world.reform_option_get_parent_reform(r);
2072 auto current = state.world.nation_get_reforms(n, reform.id).id;
2073 auto allow = state.world.reform_option_get_allow(r);
2077 float base_cost = float(state.world.reform_option_get_technology_cost(r));
2078 float reform_factor = is_military ? m_mul : e_mul;
2080 if(!cheap_r || base_cost * reform_factor < cheap_cost) {
2081 cheap_cost = base_cost * reform_factor;
2087 if(cheap_r && cheap_cost <= n.get_research_points()) {
2096 auto first_wg = state.crisis_attacker_wargoals.at(0);
2097 if(first_wg.cb == state.military_definitions.crisis_colony) {
2098 auto colonizers = state.world.state_definition_get_colonization(first_wg.state);
2099 if(colonizers.end() - colonizers.begin() < 2)
2102 auto defending_colonizer = (*(colonizers.begin() + 1)).get_colonizer();
2103 if(state.world.nation_get_in_sphere_of(defending_colonizer) == n)
2105 if(state.world.nation_get_ai_rival(n) == defending_colonizer
2106 || (defending_colonizer.get_in_sphere_of() && !
nations::are_allied(state, n, defending_colonizer) && state.world.nation_get_ai_rival(n) == defending_colonizer.get_in_sphere_of())) {
2109 if(state.primary_crisis_defender && state.world.nation_get_ai_rival(n) == state.primary_crisis_defender)
2113 }
else if(first_wg.cb == state.military_definitions.liberate) {
2114 auto state_owner = first_wg.target_nation;
2115 auto liberated = state.world.national_identity_get_nation_from_identity_holder(first_wg.wg_tag);
2117 if(state_owner == n)
2121 if(state.world.nation_get_in_sphere_of(state_owner) == n ||
nations::are_allied(state, n, state_owner))
2123 if(state.world.nation_get_ai_rival(n) == state_owner)
2125 if(state.world.nation_get_in_sphere_of(state_owner) && state.world.nation_get_ai_rival(n) == state.world.nation_get_in_sphere_of(state_owner))
2127 if(state.world.nation_get_in_sphere_of(liberated) == n ||
nations::are_allied(state, n, liberated))
2129 if(state.primary_crisis_defender && state.world.nation_get_ai_rival(n) == state.primary_crisis_defender)
2137 auto first_wg = state.crisis_attacker_wargoals.at(0);
2138 if(first_wg.cb == state.military_definitions.crisis_colony) {
2139 auto colonizers = state.world.state_definition_get_colonization(first_wg.state);
2140 if(colonizers.end() - colonizers.begin() < 2)
2143 auto attacking_colonizer = (*colonizers.begin()).get_colonizer();
2145 if(state.world.nation_get_in_sphere_of(attacking_colonizer) == n)
2147 if(state.world.nation_get_ai_rival(n) == attacking_colonizer
2148 || (attacking_colonizer.get_in_sphere_of() && !
nations::are_allied(state, n, attacking_colonizer) && state.world.nation_get_ai_rival(n) == attacking_colonizer.get_in_sphere_of())
2149 || state.world.nation_get_ai_rival(n) == state.primary_crisis_attacker) {
2152 if(state.primary_crisis_attacker && state.world.nation_get_ai_rival(n) == state.primary_crisis_attacker)
2156 }
else if(first_wg.cb == state.military_definitions.liberate) {
2157 auto state_owner = first_wg.target_nation;
2158 auto liberated = state.world.national_identity_get_nation_from_identity_holder(first_wg.wg_tag);
2160 if(state_owner == n)
2164 if(state.world.nation_get_in_sphere_of(liberated) == n ||
nations::are_allied(state, n, liberated))
2166 if(state.world.nation_get_ai_rival(n) == liberated)
2168 if(state.world.nation_get_in_sphere_of(liberated) && state.world.nation_get_ai_rival(n) == state.world.nation_get_in_sphere_of(liberated))
2170 if(state.world.nation_get_in_sphere_of(state_owner) == n ||
nations::are_allied(state, n, state_owner))
2172 if(state.primary_crisis_attacker && state.world.nation_get_ai_rival(n) == state.primary_crisis_attacker)
2181 float attacker = 0.0f;
2182 float defender = 0.0f;
2183 bool defender_win =
false;
2184 bool attacker_win =
false;
2185 bool fast_victory =
false;
2189 float atotal = 0.0f;
2190 float dtotal = 0.0f;
2192 if(state.crisis_attacker && state.crisis_attacker != state.primary_crisis_attacker) {
2195 if(state.crisis_defender && state.crisis_defender != state.primary_crisis_defender) {
2198 for(
auto& i : state.crisis_participants) {
2201 if(!i.merely_interested) {
2202 if(i.supports_attacker) {
2210 auto necessary_atk_win_ratio = 1.55f;
2211 auto necessary_def_win_ratio = 1.55f;
2212 auto necessary_fast_win_ratio = 1.9f;
2213 for(
auto wg : state.crisis_attacker_wargoals) {
2218 necessary_atk_win_ratio += 0.10f;
2219 necessary_fast_win_ratio += 0.1f;
2221 for(
auto wg : state.crisis_defender_wargoals) {
2226 necessary_def_win_ratio += 0.10f;
2227 necessary_fast_win_ratio += 0.1f;
2230 auto def_victory = dtotal > atotal * necessary_def_win_ratio;
2231 auto atk_victory = atotal > dtotal * necessary_atk_win_ratio;
2232 auto fast_victory = (dtotal / atotal > necessary_fast_win_ratio) || (atotal / dtotal > necessary_fast_win_ratio);
2234 atk_victory = atotal > dtotal;
2235 def_victory = dtotal > atotal;
2238 return crisis_str{ atotal, dtotal, def_victory, atk_victory, fast_victory};
2242 if(offer.
target_nation == state.world.nation_get_ai_rival(n))
2244 auto offer_bits = state.world.cb_type_get_type_bits(offer.
cb);
2251 auto offer_bits = state.world.cb_type_get_type_bits(t);
2266 for(
auto si : state.world.nation_get_state_ownership(within)) {
2267 result.push_back(si.get_state().id);
2270 auto distance_from = state.world.nation_get_capital(for_nation).id;
2273 if(state.world.get_nation_adjacency_by_nation_adjacency_pair(for_nation, within)) {
2274 int32_t last = int32_t(result.size());
2275 while(first < last - 1) {
2282 if(first < last - 1) {
2283 std::swap(result[first], result[last - 1]);
2289 std::sort(result.begin(), result.begin() + first, [&](dcon::state_instance_id a, dcon::state_instance_id b) {
2290 auto a_distance = province::sorting_distance(state, state.world.state_instance_get_capital(a), distance_from);
2291 auto b_distance = province::sorting_distance(state, state.world.state_instance_get_capital(b), distance_from);
2292 if(a_distance != b_distance)
2293 return a_distance < b_distance;
2295 return a.index() < b.index();
2298 if(state.world.nation_get_total_ports(for_nation) > 0 && state.world.nation_get_total_ports(within) > 0) {
2299 int32_t last = int32_t(result.size());
2300 while(first < last - 1) {
2307 if(first < last - 1) {
2308 std::swap(result[first], result[last - 1]);
2313 std::sort(result.begin(), result.begin() + first, [&](dcon::state_instance_id a, dcon::state_instance_id b) {
2314 auto a_distance = province::sorting_distance(state, state.world.state_instance_get_capital(a), distance_from);
2315 auto b_distance = province::sorting_distance(state, state.world.state_instance_get_capital(b), distance_from);
2316 if(a_distance != b_distance)
2317 return a_distance < b_distance;
2319 return a.index() < b.index();
2322 if(first < int32_t(result.size())) {
2323 std::sort(result.begin() + first, result.end(), [&](dcon::state_instance_id a, dcon::state_instance_id b) {
2324 auto a_distance = province::sorting_distance(state, state.world.state_instance_get_capital(a), distance_from);
2325 auto b_distance = province::sorting_distance(state, state.world.state_instance_get_capital(b), distance_from);
2326 if(a_distance != b_distance)
2327 return a_distance < b_distance;
2329 return a.index() < b.index();
2341 if(state.crisis_temperature > 75.f || str_est.fast_victory) {
2342 auto any_victory = str_est.attacker_win || str_est.defender_win;
2343 auto defender_victory = str_est.defender_win;
2345 if(state.world.nation_get_is_player_controlled(state.primary_crisis_attacker) ==
false && any_victory) {
2348 auto pending = state.world.nation_get_peace_offer_from_pending_peace_offer(state.primary_crisis_attacker);
2350 auto wargoalslist = (defender_victory) ? state.crisis_defender_wargoals : state.crisis_attacker_wargoals;
2351 for(
auto swg : wargoalslist) {
2355 auto wg = fatten(state.world, state.world.create_wargoal());
2356 wg.set_peace_offer_from_peace_offer_item(pending);
2357 wg.set_added_by(swg.added_by);
2358 wg.set_associated_state(swg.state);
2359 wg.set_associated_tag(swg.wg_tag);
2360 wg.set_secondary_nation(swg.secondary_nation);
2361 wg.set_target_nation(swg.target_nation);
2362 wg.set_type(swg.cb);
2364 swg.cb, swg.state, swg.wg_tag, swg.secondary_nation));
2368 }
else if(state.world.nation_get_is_player_controlled(state.primary_crisis_defender) ==
false && any_victory) {
2371 auto pending = state.world.nation_get_peace_offer_from_pending_peace_offer(state.primary_crisis_defender);
2373 auto wargoalslist = (defender_victory) ? state.crisis_defender_wargoals : state.crisis_attacker_wargoals;
2374 for(
auto swg : wargoalslist) {
2379 swg.cb, swg.state, swg.wg_tag, swg.secondary_nation));
2380 auto wg = fatten(state.world, state.world.create_wargoal());
2381 wg.set_peace_offer_from_peace_offer_item(pending);
2382 wg.set_added_by(swg.added_by);
2383 wg.set_associated_state(swg.state);
2384 wg.set_associated_tag(swg.wg_tag);
2385 wg.set_secondary_nation(swg.secondary_nation);
2386 wg.set_target_nation(swg.target_nation);
2387 wg.set_type(swg.cb);
2393 }
else if(state.crisis_temperature > 20.f) {
2394 if(str_est.attacker < str_est.defender && state.world.nation_get_is_player_controlled(state.primary_crisis_attacker) ==
false) {
2395 for(
auto& par : state.crisis_participants) {
2398 if(par.merely_interested) {
2399 auto other_cbs = state.world.nation_get_available_cbs(par.id);
2400 dcon::cb_type_id offer_cb;
2401 dcon::nation_id target;
2404 for(
auto& op_par : state.crisis_participants) {
2407 if(!op_par.merely_interested && op_par.supports_attacker ==
false) {
2408 for(
auto& cb : other_cbs) {
2410 offer_cb = cb.cb_type;
2415 for(
auto cb : state.world.in_cb_type) {
2430 std::vector < dcon::state_instance_id> potential_states;
2432 for(
auto s : potential_states) {
2438 m.from = state.primary_crisis_attacker;
2439 m.data.crisis_offer.added_by = m.to;
2440 m.data.crisis_offer.target_nation = target;
2441 m.data.crisis_offer.secondary_nation = dcon::nation_id{};
2442 m.data.crisis_offer.state = state.world.state_instance_get_definition(s);
2443 m.data.crisis_offer.wg_tag = dcon::national_identity_id{};
2444 m.data.crisis_offer.cb = offer_cb;
2455 m.from = state.primary_crisis_attacker;
2456 m.data.crisis_offer.added_by = m.to;
2457 m.data.crisis_offer.target_nation = target;
2458 m.data.crisis_offer.secondary_nation = dcon::nation_id{};
2459 m.data.crisis_offer.state = dcon::state_definition_id{};
2460 m.data.crisis_offer.wg_tag = dcon::national_identity_id{};
2461 m.data.crisis_offer.cb = offer_cb;
2468 }
else if(str_est.attacker < str_est.defender && state.world.nation_get_is_player_controlled(state.primary_crisis_defender) ==
false) {
2469 for(
auto& par : state.crisis_participants) {
2472 if(par.merely_interested) {
2473 auto other_cbs = state.world.nation_get_available_cbs(par.id);
2474 dcon::cb_type_id offer_cb;
2475 dcon::nation_id target;
2478 for(
auto& op_par : state.crisis_participants) {
2481 if(!op_par.merely_interested && op_par.supports_attacker ==
true) {
2482 for(
auto& cb : other_cbs) {
2484 offer_cb = cb.cb_type;
2489 for(
auto cb : state.world.in_cb_type) {
2504 std::vector < dcon::state_instance_id> potential_states;
2506 for(
auto s : potential_states) {
2512 m.from = state.primary_crisis_defender;
2513 m.data.crisis_offer.added_by = m.to;
2514 m.data.crisis_offer.target_nation = target;
2515 m.data.crisis_offer.secondary_nation = dcon::nation_id{};
2516 m.data.crisis_offer.state = state.world.state_instance_get_definition(s);
2517 m.data.crisis_offer.wg_tag = dcon::national_identity_id{};
2518 m.data.crisis_offer.cb = offer_cb;
2529 m.from = state.primary_crisis_defender;
2530 m.data.crisis_offer.added_by = m.to;
2531 m.data.crisis_offer.target_nation = target;
2532 m.data.crisis_offer.secondary_nation = dcon::nation_id{};
2533 m.data.crisis_offer.state = dcon::state_definition_id{};
2534 m.data.crisis_offer.wg_tag = dcon::national_identity_id{};
2535 m.data.crisis_offer.cb = offer_cb;
2547 if(state.crisis_temperature < 50.0f)
2552 if(to == state.primary_crisis_attacker) {
2553 if(str_est.attacker < str_est.defender * 0.66f)
2555 if(str_est.attacker < str_est.defender * 0.75f)
2556 return is_concession;
2561 dcon::nation_id attacker = state.primary_crisis_attacker;
2567 }
else if(to == state.primary_crisis_defender) {
2568 if(str_est.defender < str_est.attacker * 0.66f)
2570 if(str_est.defender < str_est.attacker * 0.75f)
2571 return is_concession;
2585 if(state.crisis_temperature < 50.0f)
2590 if(to == state.primary_crisis_attacker) {
2591 if(str_est.attacker < str_est.defender * 0.66f)
2593 if(str_est.attacker < str_est.defender * 0.75f)
2594 return state.world.peace_offer_get_is_concession(peace);
2596 if(!state.world.peace_offer_get_is_concession(peace))
2599 bool missing_wg =
false;
2600 for(
auto swg : state.crisis_attacker_wargoals) {
2601 bool found_wg =
false;
2602 for(
auto item : state.world.peace_offer_get_peace_offer_item(peace)) {
2603 auto wg = item.get_wargoal();
2604 if(wg.get_type() == swg.cb && wg.get_associated_state() == swg.state && wg.get_added_by() == swg.added_by && wg.get_target_nation() == swg.target_nation &&
2605 wg.get_associated_tag() == swg.wg_tag) {
2606 found_wg =
true;
continue;
2616 }
else if(to == state.primary_crisis_defender) {
2617 if(str_est.defender < str_est.attacker * 0.66f)
2619 if(str_est.defender < str_est.attacker * 0.75f)
2620 return state.world.peace_offer_get_is_concession(peace);
2622 if(!state.world.peace_offer_get_is_concession(peace))
2626 bool missing_wg =
false;
2627 for(
auto swg : state.crisis_defender_wargoals) {
2628 bool found_wg =
false;
2629 for(
auto item : state.world.peace_offer_get_peace_offer_item(peace)) {
2630 auto wg = item.get_wargoal();
2631 if(wg.get_type() == swg.cb && wg.get_associated_state() == swg.state && wg.get_added_by() == swg.added_by && wg.get_target_nation() == swg.target_nation &&
2632 wg.get_associated_tag() == swg.wg_tag) {
2633 found_wg =
true;
continue;
2648 for(
auto& gp : state.great_nations) {
2649 if(state.world.nation_get_is_player_controlled(gp.nation) ==
false && state.world.nation_get_is_at_war(gp.nation) ==
false){
2650 bool as_attacker =
false;
2651 dcon::war_id intervention_target;
2653 for(
auto w : state.world.in_war) {
2656 auto par = state.world.war_get_primary_defender(w);
2657 if(state.world.nation_get_primary_culture(gp.nation).get_group_from_culture_group_membership() == state.world.nation_get_primary_culture(par).get_group_from_culture_group_membership()
2660 intervention_target = w;
2664 if(w.get_is_great()) {
2666 for(
auto par : w.get_war_participant()) {
2668 intervention_target = w;
2674 for(
auto par : w.get_war_participant()) {
2676 intervention_target = w;
2684 intervention_target = w;
2690 if(intervention_target) {
2707void place_instance_in_result(
sys::state& state, std::vector<possible_cb>& result, dcon::nation_id n, dcon::nation_id target, dcon::cb_type_id cb, std::vector<dcon::state_instance_id>
const& target_states) {
2708 auto can_use = state.world.cb_type_get_can_use(cb);
2709 auto allowed_substates = state.world.cb_type_get_allowed_substate_regions(cb);
2711 if(allowed_substates) {
2712 if(!state.world.nation_get_is_substate(target))
2714 auto ruler = state.world.overlord_get_ruler(state.world.nation_get_overlord_as_subject(target));
2724 auto allowed_countries = state.world.cb_type_get_allowed_countries(cb);
2725 auto allowed_states = state.world.cb_type_get_allowed_states(cb);
2727 if(!allowed_countries && allowed_states) {
2728 bool any_allowed =
false;
2729 for(
auto si : target_states) {
2732 result.push_back(
possible_cb{ target, dcon::nation_id{}, dcon::national_identity_id{}, state.world.state_instance_get_definition(si), cb });
2737 }
else if(allowed_substates) {
2738 for(
auto si : target_states) {
2741 result.push_back(
possible_cb{ target, dcon::nation_id{}, dcon::national_identity_id{}, state.world.state_instance_get_definition(si), cb });
2746 }
else if(allowed_countries) {
2748 for(
auto other_nation : state.world.in_nation) {
2749 if(other_nation != n) {
2752 if(allowed_states) {
2753 for(
auto i = target_states.size(); i-- > 0;) {
2754 auto si = target_states[i];
2758 result.push_back(
possible_cb{ target, dcon::nation_id{}, other_nation.get_identity_from_identity_holder(), state.world.state_instance_get_definition(si), cb });
2762 result.push_back(
possible_cb{ target, other_nation, dcon::national_identity_id{}, state.world.state_instance_get_definition(si), cb });
2770 result.push_back(
possible_cb{ target, dcon::nation_id{}, other_nation.get_identity_from_identity_holder(), dcon::state_definition_id{}, cb });
2774 result.push_back(
possible_cb{ target, other_nation, dcon::national_identity_id{}, dcon::state_definition_id{}, cb });
2784 result.push_back(
possible_cb{ target, dcon::nation_id{}, dcon::national_identity_id{}, dcon::state_definition_id{}, cb });
2792 static std::vector<dcon::state_instance_id> target_states;
2796 for(
auto cb : state.world.in_cb_type) {
2797 auto bits = state.world.cb_type_get_type_bits(cb);
2803 auto sl = state.world.nation_get_in_sphere_of(target);
2812 if((state.world.nation_get_ai_rival(n) == a.target) != (state.world.nation_get_ai_rival(n) == b.target)) {
2813 return state.world.nation_get_ai_rival(n) == a.target;
2818 if(a_annexes != b_annexes)
2827 auto rel_a = state.world.get_diplomatic_relation_by_diplomatic_pair(n, a.
target);
2828 auto rel_b = state.world.get_diplomatic_relation_by_diplomatic_pair(n, b.
target);
2829 if(state.world.diplomatic_relation_get_value(rel_a) != state.world.diplomatic_relation_get_value(rel_b))
2830 return state.world.diplomatic_relation_get_value(rel_a) < state.world.diplomatic_relation_get_value(rel_b);
2833 return a.
cb.index() < b.
cb.index();
2845 static std::vector<possible_cb> possibilities;
2849 float infamy_limit = state.world.nation_get_is_civilized(from) ? state.defines.badboy_limit / 2.f : state.defines.badboy_limit;
2851 if(!possibilities.empty()) {
2853 auto possibility = possibilities[0];
2857 if(state.world.nation_get_infamy(from) +
military::cb_infamy(state, possibility.cb, target, possibility.state_def) > infamy_limit)
2860 if(state.world.nation_get_infamy(from) +
military::cb_infamy(state, possibility.cb, target) > infamy_limit)
2865 for (
auto n : state.nations_by_rank) {
2870 auto is_discovered = state.world.nation_get_constructing_cb_is_discovered(n);
2872 if(!is_discovered) {
2876 auto target_nation = state.world.nation_get_constructing_cb_target(n);
2877 auto target_state = state.world.nation_get_constructing_cb_target_state(n);
2879 if(possibility.target == target_nation && possibility.state_def == target_state) {
2894 if(state.world.nation_get_constructing_cb_type(from))
2896 auto ol = state.world.nation_get_overlord_as_subject(from);
2897 if(state.world.overlord_get_ruler(ol) && state.world.overlord_get_ruler(ol) != target)
2899 if(state.world.nation_get_in_sphere_of(target) == from)
2905 auto sl = state.world.nation_get_in_sphere_of(target);
2909 if(state.world.nation_get_is_at_war(target)) {
2915 if(state.world.nation_get_owned_province_count(target) <= 2)
2918 if(state.world.province_get_continent(state.world.nation_get_capital(from)) != state.world.province_get_continent(state.world.nation_get_capital(target))) {
2920 if(state.world.nation_get_capital_ship_score(from) < std::max(1.f, 1.5f * state.world.nation_get_capital_ship_score(target)))
2927 for(
auto nid : state.nations_by_rank) {
2930 if(!n.get_is_player_controlled() && n.get_owned_province_count() > 0) {
2931 if(n.get_is_at_war())
2934 float infamy_limit = state.world.nation_get_is_civilized(n) ? state.defines.badboy_limit / 2.f : state.defines.badboy_limit;
2935 if(n.get_infamy() > infamy_limit)
2937 if(n.get_constructing_cb_type())
2939 auto ol = n.get_overlord_as_subject().get_ruler().id;
2941 && n.get_ai_rival().get_in_sphere_of() != n
2942 && (!ol || ol == n.get_ai_rival())
2949 n.set_constructing_cb_target(n.get_ai_rival());
2950 n.set_constructing_cb_type(cb.cb);
2951 n.set_constructing_cb_target_state(cb.state_def);
2956 static std::vector<dcon::nation_id> possible_targets;
2957 possible_targets.clear();
2958 for(
auto i : state.world.in_nation) {
2961 possible_targets.push_back(i.id);
2962 if(!i.get_is_civilized())
2963 possible_targets.push_back(i.id);
2966 if(!possible_targets.empty()) {
2969 n.set_constructing_cb_target(t);
2970 n.set_constructing_cb_type(pcb.cb);
2971 n.set_constructing_cb_target_state(pcb.state_def);
2981 if(
bool(state.defines.alice_unciv_civ_forbid_war) && !state.world.nation_get_is_civilized(n)
2982 && !state.world.nation_get_is_substate(n) && !state.world.nation_get_in_sphere_of(n)
2983 && !state.world.overlord_get_ruler(state.world.nation_get_overlord_as_subject(n))) {
2984 auto pa = state.world.war_get_primary_attacker(w);
2985 auto pd = state.world.war_get_primary_defender(w);
2986 auto pa_cap = state.world.nation_get_capital(pa);
2987 auto pd_cap = state.world.nation_get_capital(pd);
2988 auto cap = state.world.nation_get_capital(n);
2989 if(state.world.province_get_continent(pa_cap) != state.world.province_get_continent(cap))
2991 if(state.world.province_get_continent(pd_cap) != state.world.province_get_continent(cap))
2997 for(
auto par : state.world.war_get_war_participant(w)) {
2998 if(par.get_is_attacker() == !as_attacker) {
3003 if(state.world.nation_get_ai_rival(n) == par.get_nation())
3010void place_instance_in_result_war(
sys::state& state, std::vector<possible_cb>& result, dcon::nation_id n, dcon::nation_id target, dcon::war_id w, dcon::cb_type_id cb, std::vector<dcon::state_instance_id>
const& target_states) {
3011 auto can_use = state.world.cb_type_get_can_use(cb);
3012 auto allowed_substates = state.world.cb_type_get_allowed_substate_regions(cb);
3013 if(allowed_substates) {
3014 if(!state.world.nation_get_is_substate(target))
3016 auto ruler = state.world.overlord_get_ruler(state.world.nation_get_overlord_as_subject(target));
3026 auto allowed_countries = state.world.cb_type_get_allowed_countries(cb);
3027 auto allowed_states = state.world.cb_type_get_allowed_states(cb);
3029 if(!allowed_countries && allowed_states) {
3030 for(
auto si : target_states) {
3034 result.push_back(
possible_cb{ target, dcon::nation_id{}, dcon::national_identity_id{}, state.world.state_instance_get_definition(si), cb });
3040 }
else if(allowed_substates) {
3041 for(
auto si : target_states) {
3045 result.push_back(
possible_cb{ target, dcon::nation_id{}, dcon::national_identity_id{}, state.world.state_instance_get_definition(si), cb });
3051 }
else if(allowed_countries) {
3053 for(
auto other_nation : state.world.in_nation) {
3054 if(other_nation != n) {
3056 if(allowed_states) {
3057 for(
auto i = target_states.size(); i-- > 0;) {
3058 auto si = target_states[i];
3061 if(!
military::war_goal_would_be_duplicate(state, n, w, target, cb, state.world.state_instance_get_definition(si), other_nation.get_identity_from_identity_holder(), dcon::nation_id{})) {
3063 result.push_back(
possible_cb{ target, dcon::nation_id{}, other_nation.get_identity_from_identity_holder(), state.world.state_instance_get_definition(si), cb });
3069 result.push_back(
possible_cb{ target, other_nation, dcon::national_identity_id{}, state.world.state_instance_get_definition(si), cb });
3079 result.push_back(
possible_cb{ target, dcon::nation_id{}, other_nation.get_identity_from_identity_holder(), dcon::state_definition_id{}, cb });
3085 result.push_back(
possible_cb{ target, other_nation, dcon::national_identity_id{}, dcon::state_definition_id{}, cb });
3096 result.push_back(
possible_cb{ target, dcon::nation_id{}, dcon::national_identity_id{}, dcon::state_definition_id{}, cb });
3105 for(
auto par : state.world.war_get_war_participant(w)) {
3106 if(par.get_is_attacker() != is_attacker) {
3107 static std::vector<dcon::state_instance_id> target_states;
3109 for(
auto& cb : state.world.nation_get_available_cbs(n)) {
3110 if(cb.target == par.get_nation())
3113 for(
auto cb : state.world.in_cb_type) {
3122 if((state.world.nation_get_ai_rival(n) == a.target) != (state.world.nation_get_ai_rival(n) == b.target)) {
3123 return state.world.nation_get_ai_rival(n) == a.target;
3128 if(a_annexes != b_annexes)
3137 auto rel_a = state.world.get_diplomatic_relation_by_diplomatic_pair(n, a.
target);
3138 auto rel_b = state.world.get_diplomatic_relation_by_diplomatic_pair(n, b.
target);
3139 if(state.world.diplomatic_relation_get_value(rel_a) != state.world.diplomatic_relation_get_value(rel_b))
3140 return state.world.diplomatic_relation_get_value(rel_a) < state.world.diplomatic_relation_get_value(rel_b);
3143 return a.
cb.index() < b.
cb.index();
3157 static std::vector<dcon::state_instance_id> target_states;
3161 auto other_cbs = state.world.nation_get_available_cbs(n);
3162 for(
auto& cb : other_cbs) {
3163 if(cb.target == target)
3167 for(
auto cb : state.world.in_cb_type) {
3175 if((state.world.nation_get_ai_rival(n) == a.target) != (state.world.nation_get_ai_rival(n) == b.target)) {
3176 return state.world.nation_get_ai_rival(n) == a.target;
3181 if(a_annexes != b_annexes)
3190 auto rel_a = state.world.get_diplomatic_relation_by_diplomatic_pair(n, a.
target);
3191 auto rel_b = state.world.get_diplomatic_relation_by_diplomatic_pair(n, b.
target);
3192 if(state.world.diplomatic_relation_get_value(rel_a) != state.world.diplomatic_relation_get_value(rel_b))
3193 return state.world.diplomatic_relation_get_value(rel_a) < state.world.diplomatic_relation_get_value(rel_b);
3196 return a.
cb.index() < b.
cb.index();
3217 static std::vector<possible_cb> potential;
3219 for(
auto& p : potential) {
3221 military::add_wargoal(state, w, n, p.target, p.cb, p.state_def, p.associated_tag, p.secondary_nation);
3231 static std::vector<dcon::cb_type_id> possibilities;
3232 possibilities.clear();
3234 auto free_infamy = state.defines.badboy_limit - state.world.nation_get_infamy(from);
3236 for(
auto c : state.world.in_cb_type) {
3237 auto bits = state.world.cb_type_get_type_bits(c);
3242 if(
military::cb_infamy(state, c, target) * state.defines.gw_justify_cb_badboy_impact > free_infamy)
3247 possibilities.push_back(c);
3250 if(!possibilities.empty()) {
3253 return dcon::cb_type_id{};
3260 return state.world.nation_get_ai_rival(from);
3262 return state.world.nation_get_ai_rival(from);
3264 static std::vector<dcon::nation_id> possibilities;
3265 possibilities.clear();
3267 for(
auto par : state.world.war_get_war_participant(w)) {
3268 if(par.get_is_attacker() != is_attacker) {
3269 if(state.world.get_nation_adjacency_by_nation_adjacency_pair(from, par.get_nation()))
3270 possibilities.push_back(par.get_nation().id);
3273 if(possibilities.empty()) {
3274 for(
auto par : state.world.war_get_war_participant(w)) {
3275 if(par.get_is_attacker() != is_attacker) {
3277 possibilities.push_back(par.get_nation().id);
3281 if(!possibilities.empty()) {
3284 return dcon::nation_id{};
3293 if(n == state.world.war_get_primary_attacker(w) || n == state.world.war_get_primary_defender(w)) {
3294 if(((rval >> 1) & 1) == 0) {
3300 auto jingoism_perc = totalpop > 0 ? state.world.nation_get_demographics(n,
demographics::to_key(state, state.culture_definitions.jingoism)) / totalpop : 0.0f;
3302 if(jingoism_perc < state.defines.wargoal_jingoism_requirement * state.defines.gw_wargoal_jingoism_requirement_mod)
3318 static std::vector<dcon::state_instance_id> target_states;
3320 static std::vector<possible_cb> result;
3323 if(!result.empty() && result[0].target) {
3324 military::add_wargoal(state, w, n, target, cb, result[0].state_def, result[0].associated_tag, result[0].secondary_nation);
3326 state.world.nation_get_infamy(n) +=
military::cb_infamy(state, cb, target) * state.defines.gw_justify_cb_badboy_impact;
3331 for(
auto w : state.world.in_war) {
3332 if(w.get_is_great()) {
3333 for(
auto par : w.get_war_participant()) {
3334 if(par.get_nation().get_is_player_controlled() ==
false) {
3343 if(
bool(state.defines.alice_surrender_on_cores_lost)) {
3344 auto i = state.world.nation_get_identity_from_identity_holder(n);
3345 auto cores = state.world.national_identity_get_core(i);
3346 bool has_owned_cores =
false;
3347 for(
auto c : cores) {
3348 if(c.get_province().get_nation_from_province_ownership() == n) {
3349 has_owned_cores =
true;
3350 }
if(c.get_province().get_nation_from_province_control() == n) {
3354 auto pc = state.world.nation_get_province_control(n);
3355 return has_owned_cores || pc.begin() == pc.end();
3361 auto send_offer_up_to = [&](dcon::nation_id from, dcon::nation_id to, dcon::war_id w,
bool attacker, int32_t score_max,
bool concession) {
3362 if(
auto off = state.world.nation_get_peace_offer_from_pending_peace_offer(from); off) {
3363 if(state.world.peace_offer_get_is_crisis_offer(off) ==
true || state.world.peace_offer_get_war_from_war_settlement(off))
3365 state.world.delete_peace_offer(off);
3370 auto pending = state.world.nation_get_peace_offer_from_pending_peace_offer(from);
3374 score_max = std::min(score_max, 100);
3375 int32_t current_value = 0;
3376 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
3378 auto goal_cost =
military::peace_cost(state, w, wg.get_wargoal().get_type(), wg.get_wargoal().get_added_by(), wg.get_wargoal().get_target_nation(), wg.get_wargoal().get_secondary_nation(), wg.get_wargoal().get_associated_state(), wg.get_wargoal().get_associated_tag());
3379 if(current_value + goal_cost <= score_max) {
3380 current_value += goal_cost;
3381 state.world.force_create_peace_offer_item(pending, wg.get_wargoal().id);
3390 for(
auto w : state.world.in_war) {
3391 if((w.get_primary_attacker().get_is_player_controlled() ==
false || w.get_primary_defender().get_is_player_controlled() ==
false)
3392 && w.get_primary_attacker().get_owned_province_count() > 0
3393 && w.get_primary_defender().get_owned_province_count() > 0) {
3401 if(overall_score >= 0) {
3404 if(w.get_primary_attacker().get_is_player_controlled() ==
false) {
3405 if(defender_surrender || (overall_score >= 100 || (overall_score >= 50 && overall_score >= total_po_cost * 2))) {
3406 send_offer_up_to(w.get_primary_attacker(), w.get_primary_defender(), w,
true, int32_t(overall_score),
false);
3409 if(w.get_primary_defender().get_is_player_controlled() ==
false) {
3410 auto war_duration = state.current_date.value - state.world.war_get_start_date(w).value;
3411 if(war_duration >= 365) {
3412 float willingness_factor = float(war_duration - 365) * 10.f / 365.0f;
3413 if(defender_surrender || (overall_score > (total_po_cost - willingness_factor) && (-overall_score / 2 + total_po_cost - willingness_factor) < 0)) {
3414 send_offer_up_to(w.get_primary_attacker(), w.get_primary_defender(), w,
true, int32_t(total_po_cost),
false);
3419 }
else if(w.get_primary_defender().get_is_player_controlled() ==
false) {
3420 if(defender_surrender || (overall_score >= 100 || (overall_score >= 50 && overall_score >= total_po_cost * 2))) {
3421 send_offer_up_to(w.get_primary_defender(), w.get_primary_attacker(), w,
false, int32_t(overall_score),
true);
3428 if(w.get_primary_defender().get_is_player_controlled() ==
false) {
3429 if(attacker_surrender || (overall_score <= -100 || (overall_score <= -50 && overall_score <= -total_po_cost * 2))) {
3430 send_offer_up_to(w.get_primary_defender(), w.get_primary_attacker(), w,
false, int32_t(-overall_score),
false);
3433 if(w.get_primary_attacker().get_is_player_controlled() ==
false) {
3434 auto war_duration = state.current_date.value - state.world.war_get_start_date(w).value;
3435 if(war_duration >= 365) {
3436 float willingness_factor = float(war_duration - 365) * 10.f / 365.0f;
3437 if(attacker_surrender || (-overall_score > (total_po_cost - willingness_factor) && (overall_score / 2 + total_po_cost - willingness_factor) < 0)) {
3438 send_offer_up_to(w.get_primary_defender(), w.get_primary_attacker(), w,
false, int32_t(total_po_cost),
false);
3443 }
else if(w.get_primary_attacker().get_is_player_controlled() ==
false) {
3444 if(attacker_surrender || (overall_score <= -100 || (overall_score <= -50 && overall_score <= -total_po_cost * 2))) {
3445 send_offer_up_to(w.get_primary_attacker(), w.get_primary_defender(), w,
true, int32_t(-overall_score),
true);
3455 dcon::nation_id n, dcon::nation_id from,
3456 dcon::nation_id prime_attacker, dcon::nation_id prime_defender,
3457 float primary_warscore,
float scoreagainst_me,
3458 bool offer_from_attacker,
bool concession,
3459 int32_t overall_po_value, int32_t my_po_target,
3460 int32_t target_personal_po_value, int32_t potential_peace_score_against,
3461 int32_t my_side_against_target, int32_t my_side_peace_cost,
3462 int32_t war_duration,
bool contains_sq) {
3463 bool is_attacking = !offer_from_attacker;
3465 auto overall_score = primary_warscore;
3466 if(concession && overall_score <= -50.0f) {
3471 overall_po_value = -overall_po_value;
3473 if(overall_po_value < -100)
3476 auto personal_score_saved = target_personal_po_value - potential_peace_score_against;
3478 if((prime_attacker == n || prime_defender == n) && (prime_attacker == from || prime_defender == from)) {
3479 if(overall_score <= -50 && overall_score <= overall_po_value * 2)
3482 if(concession && my_side_peace_cost <= overall_po_value)
3484 if(war_duration < 365) {
3487 float willingness_factor = float(war_duration - 365) * 10.f / 365.0f;
3488 if(overall_score >= 0) {
3489 if(concession && ((overall_score * 2 - overall_po_value - willingness_factor) < 0))
3492 if((overall_score - willingness_factor) <= overall_po_value && (overall_score / 2 - overall_po_value - willingness_factor) < 0)
3496 }
else if((prime_attacker == n || prime_defender == n) && concession) {
3497 if(scoreagainst_me > 50)
3500 if(overall_score < 0.0f) {
3501 if(my_side_against_target - scoreagainst_me <= overall_po_value + personal_score_saved)
3504 if(my_side_against_target <= overall_po_value)
3512 if(scoreagainst_me > 50 && scoreagainst_me > -overall_po_value * 2)
3515 if(overall_score < 0.0f) {
3516 if(personal_score_saved > 0 && scoreagainst_me + personal_score_saved - my_po_target >= -overall_po_value)
3520 if(my_po_target > 0 && my_po_target >= overall_po_value)
3532 auto w = state.world.peace_offer_get_war_from_war_settlement(p);
3533 auto prime_attacker = state.world.war_get_primary_attacker(w);
3534 auto prime_defender = state.world.war_get_primary_defender(w);
3536 bool contains_sq =
false;
3540 overall_score = -overall_score;
3542 auto concession = state.world.peace_offer_get_is_concession(p);
3544 if(concession && overall_score <= -50.0f) {
3548 int32_t overall_po_value = 0;
3549 int32_t personal_po_value = 0;
3550 int32_t my_po_target = 0;
3551 for(
auto wg : state.world.peace_offer_get_peace_offer_item(p)) {
3552 auto wg_value =
military::peace_cost(state, w, wg.get_wargoal().get_type(), wg.get_wargoal().get_added_by(), wg.get_wargoal().get_target_nation(), wg.get_wargoal().get_secondary_nation(), wg.get_wargoal().get_associated_state(), wg.get_wargoal().get_associated_tag());
3553 overall_po_value += wg_value;
3558 if(wg.get_wargoal().get_target_nation() == n) {
3559 personal_po_value += wg_value;
3563 overall_po_value = -overall_po_value;
3565 if(overall_po_value < -100)
3568 int32_t potential_peace_score_against = 0;
3569 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
3570 if(wg.get_wargoal().get_target_nation() == n || wg.get_wargoal().get_added_by() == n) {
3571 auto wg_value =
military::peace_cost(state, w, wg.get_wargoal().get_type(), wg.get_wargoal().get_added_by(), n, wg.get_wargoal().get_secondary_nation(), wg.get_wargoal().get_associated_state(), wg.get_wargoal().get_associated_tag());
3573 if(wg.get_wargoal().get_target_nation() == n && (wg.get_wargoal().get_added_by() == from || from == prime_attacker || from == prime_defender)) {
3574 potential_peace_score_against += wg_value;
3576 if(wg.get_wargoal().get_added_by() == n && (wg.get_wargoal().get_target_nation() == from || from == prime_attacker || from == prime_defender)) {
3577 my_po_target += wg_value;
3581 auto personal_score_saved = personal_po_value - potential_peace_score_against;
3583 if((prime_attacker == n || prime_defender == n) && (prime_attacker == from || prime_defender == from)) {
3584 if(overall_score <= -50 && overall_score <= overall_po_value * 2)
3587 auto war_duration = state.current_date.value - state.world.war_get_start_date(w).value;
3590 if(war_duration < 365) {
3593 float willingness_factor = float(war_duration - 365) * 10.f / 365.0f;
3594 if(overall_score >= 0) {
3595 if(concession && ((overall_score * 2 - overall_po_value - willingness_factor) < 0))
3598 if((overall_score - willingness_factor) <= overall_po_value && (overall_score / 2 - overall_po_value - willingness_factor) < 0)
3602 }
else if((prime_attacker == n || prime_defender == n) && concession) {
3605 if(scoreagainst_me > 50)
3608 int32_t my_side_against_target = 0;
3609 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
3610 if(wg.get_wargoal().get_target_nation() == from) {
3611 auto wg_value =
military::peace_cost(state, w, wg.get_wargoal().get_type(), wg.get_wargoal().get_added_by(), n, wg.get_wargoal().get_secondary_nation(), wg.get_wargoal().get_associated_state(), wg.get_wargoal().get_associated_tag());
3613 my_side_against_target += wg_value;
3617 if(overall_score < 0.0f) {
3618 if(my_side_against_target - scoreagainst_me <= overall_po_value + personal_score_saved)
3621 if(my_side_against_target <= overall_po_value)
3630 if(scoreagainst_me > 50 && scoreagainst_me > -overall_po_value * 2)
3633 if(overall_score < 0.0f) {
3634 if(personal_score_saved > 0 && scoreagainst_me + personal_score_saved - my_po_target >= -overall_po_value)
3638 if(my_po_target > 0 && my_po_target >= overall_po_value)
3650 auto self_sup = state.world.nation_get_used_naval_supply_points(n);
3652 auto real_target = state.world.overlord_get_ruler(state.world.nation_get_overlord_as_subject(target));
3654 real_target = target;
3656 if(self_sup <= state.world.nation_get_used_naval_supply_points(real_target))
3659 if(self_sup <= state.world.nation_get_in_sphere_of(real_target).get_used_naval_supply_points())
3662 for(
auto a : state.world.nation_get_diplomatic_relation(real_target)) {
3663 if(!a.get_are_allied())
3665 auto other = a.get_related_nations(0) != real_target ? a.get_related_nations(0) : a.get_related_nations(1);
3666 if(self_sup <= other.get_used_naval_supply_points())
3674 auto targets = ve::vectorizable_buffer<dcon::nation_id, dcon::nation_id>(state.world.nation_size());
3675 concurrency::parallel_for(
uint32_t(0), state.world.nation_size(), [&](
uint32_t i) {
3676 dcon::nation_id n{ dcon::nation_id::value_base_t(i) };
3677 if(state.world.nation_get_owned_province_count(n) == 0)
3679 if(state.world.nation_get_is_at_war(n))
3681 if(state.world.nation_get_is_player_controlled(n))
3683 if(state.world.nation_get_military_score(n) == 0)
3685 if(
auto ol = state.world.nation_get_overlord_as_subject(n); state.world.overlord_get_ruler(ol))
3688 float best_difference = 2.0f;
3691 for(
auto target : state.world.in_nation) {
3692 auto real_target = target.get_overlord_as_subject().get_ruler() ? target.get_overlord_as_subject().get_ruler() : target;
3693 if(target == n || real_target == n)
3695 if(state.world.nation_get_owned_province_count(real_target) == 0)
3697 if(nations::are_allied(state, n, real_target))
3699 if(target.get_in_sphere_of() == n)
3701 if(military::has_truce_with(state, n, real_target))
3703 if(!military::can_use_cb_against(state, n, target))
3707 for(auto adj : state.world.nation_get_nation_adjacency(target)) {
3708 auto other = adj.get_connected_nations(0) != n ? adj.get_connected_nations(0) : adj.get_connected_nations(1);
3709 auto neighbor = other;
3710 if(neighbor.get_in_sphere_of() == n){
3711 auto path = province::make_safe_land_path(state, state.world.nation_get_capital(n), state.world.nation_get_capital(neighbor), n);
3715 auto str_difference = base_strength + estimate_additional_offensive_strength(state, n, real_target) - estimate_defensive_strength(state, real_target);
3716 if(str_difference > best_difference) {
3717 best_difference = str_difference;
3718 targets.set(n, target.id);
3723 if(!state.world.get_nation_adjacency_by_nation_adjacency_pair(n, target) && !
naval_supremacy(state, n, target))
3726 if(str_difference > best_difference) {
3727 best_difference = str_difference;
3728 targets.set(n, target.id);
3732 for(
auto adj : state.world.nation_get_nation_adjacency(n)) {
3733 auto other = adj.get_connected_nations(0) != n ? adj.get_connected_nations(0) : adj.get_connected_nations(1);
3734 auto real_target = other.get_overlord_as_subject().get_ruler() ? other.get_overlord_as_subject().get_ruler() : other;
3735 if(real_target == n)
3739 if(real_target.get_in_sphere_of() == n)
3741 if(state.world.nation_get_in_sphere_of(other) == n)
3747 if(!state.world.get_nation_adjacency_by_nation_adjacency_pair(n, other) && !naval_supremacy(state, n, other))
3749 auto str_difference = base_strength + estimate_additional_offensive_strength(state, n, real_target) - estimate_defensive_strength(state, real_target);
3750 if(str_difference > best_difference) {
3751 best_difference = str_difference;
3752 targets.set(n, other.id);
3755 if(
state.world.nation_get_central_ports(n) > 0) {
3760 dcon::nation_id
other{ dcon::nation_id::value_base_t(reduced_value) };
3761 auto real_target =
fatten(
state.world, other).get_overlord_as_subject().get_ruler() ?
fatten(
state.world, other).get_overlord_as_subject().get_ruler() :
fatten(
state.world, other);
3762 if(other == n || real_target == n)
3764 if(
state.world.nation_get_owned_province_count(other) == 0 ||
state.world.nation_get_owned_province_count(real_target) == 0)
3766 if(
state.world.nation_get_central_ports(other) == 0 ||
state.world.nation_get_central_ports(real_target) == 0)
3770 if(real_target.get_in_sphere_of() == n)
3772 if(
state.world.nation_get_in_sphere_of(other) == n)
3778 if(!
state.world.get_nation_adjacency_by_nation_adjacency_pair(n, other) && !
naval_supremacy(state, n, other))
3781 if(str_difference > best_difference) {
3782 best_difference = str_difference;
3783 targets.set(n, other);
3788 for(
auto n :
state.world.in_nation) {
3789 if(
n.get_is_at_war() ==
false && targets.get(n)) {
3790 static std::vector<possible_cb> potential;
3792 if(!potential.empty()) {
3793 assert(
command::can_declare_war(state, n, targets.get(n), potential[0].cb, potential[0].state_def, potential[0].associated_tag, potential[0].secondary_nation));
3794 command::execute_declare_war(state, n, targets.get(n), potential[0].cb, potential[0].state_def, potential[0].associated_tag, potential[0].secondary_nation,
true,
false);
3801 concurrency::parallel_for(
uint32_t(0), state.world.nation_size(), [&](
uint32_t i) {
3802 dcon::nation_id nid{ dcon::nation_id::value_base_t(i) };
3803 auto n = fatten(state.world, nid);
3804 if(n.get_is_player_controlled() || n.get_owned_province_count() == 0)
3815 float land_budget_ratio = 0.15f;
3816 float sea_budget_ratio = 0.05f;
3817 float education_budget_ratio = 0.30f;
3818 float investments_budget_ratio = 0.05f;
3819 float soldiers_budget_ratio = 0.40f;
3820 float construction_budget_ratio = 0.50f;
3821 float administration_budget_ratio = 0.15f;
3822 float overseas_maintenance_budget_ratio = 0.10f;
3824 if(n.get_is_at_war()) {
3825 land_budget_ratio = 2.f;
3826 sea_budget_ratio = 2.f;
3828 administration_budget_ratio *= 0.15f;
3829 education_budget_ratio *= 0.15f;
3830 overseas_maintenance_budget_ratio *= 0.15f;
3833 }
else if(n.get_ai_is_threatened()) {
3834 land_budget_ratio = 0.5f;
3835 sea_budget_ratio = 0.25f;
3837 administration_budget_ratio *= 0.75f;
3838 education_budget_ratio *= 0.75f;
3839 overseas_maintenance_budget_ratio *= 0.75f;
3846 float land_budget = land_budget_ratio * base_income;
3847 float naval_budget = sea_budget_ratio * base_income;
3848 float education_budget = education_budget_ratio * base_income;
3849 float construction_budget = construction_budget_ratio * base_income;
3850 float administration_budget = administration_budget_ratio * base_income;
3851 float soldiers_budget = soldiers_budget_ratio * base_income;
3852 float overseas_budget = overseas_maintenance_budget_ratio * base_income;
3857 ratio_land = std::clamp(ratio_land, 0.f, 100.f);
3858 ratio_naval = std::clamp(ratio_naval, 0.f, 100.f);
3862 ratio_naval /= 10.f;
3864 n.set_land_spending(int8_t(ratio_land));
3865 n.set_naval_spending(int8_t(ratio_naval));
3867 n.set_construction_spending(75);
3875 float ratio_education = 100.f *
math::sqrt(education_budget / max_education_budget);
3876 ratio_education = std::clamp(ratio_education, 0.f, 100.f);
3877 n.set_education_spending(int8_t(ratio_education));
3880 auto rules = n.get_combined_issue_rules();
3882 float investment_budget = investments_budget_ratio * base_income;
3884 float investment_ratio = 100.f *
math::sqrt(investment_budget / max_investment_budget);
3885 investment_ratio = std::clamp(investment_ratio, 0.f, 100.f);
3886 n.set_domestic_investment_spending(int8_t(investment_ratio));
3888 n.set_domestic_investment_spending(int8_t(0));
3891 float soldiers_max_ratio = 100.f *
math::sqrt(soldiers_budget / max_soldiers_budget);
3892 soldiers_max_ratio = std::clamp(soldiers_max_ratio, 0.f, 100.f);
3894 float administration_max_ratio = 100.f *
math::sqrt(administration_budget / max_admin_budget);
3895 administration_max_ratio = std::clamp(administration_max_ratio, 0.f, 100.f);
3897 float overseas_max_ratio = std::clamp(100.f * overseas_budget / max_overseas_budget, 0.f, 100.f);
3899 n.set_tariffs_import(int8_t(5));
3900 n.set_tariffs_export(int8_t(5));
3908 int max_poor_tax = int(10.f + 70.f * (1.f - poor_militancy));
3909 int max_mid_tax = int(10.f + 80.f * (1.f - mid_militancy));
3910 int max_rich_tax = int(10.f + 90.f * (1.f - rich_militancy));
3911 int max_social = int(100.f * poor_militancy);
3914 bool enough_tax =
true;
3915 if(ratio_education < 50.f) {
3917 n.set_poor_tax(int8_t(std::clamp(n.get_poor_tax() + 2, 10, std::max(10, max_poor_tax))));
3918 n.set_middle_tax(int8_t(std::clamp(n.get_middle_tax() + 3, 10, std::max(10, max_mid_tax))));
3919 n.set_rich_tax(int8_t(std::clamp(n.get_rich_tax() + 5, 10, std::max(10, max_rich_tax))));
3922 if(n.get_spending_level() < 1.0f || n.get_last_treasury() >= n.get_stockpiles(
economy::money) || ratio_education < 50.f) {
3926 if(!n.get_ai_is_threatened()) {
3927 n.set_military_spending(int8_t(std::max(50, n.get_military_spending() - 5)));
3929 n.set_social_spending(int8_t(std::max(0, n.get_social_spending() - 2)));
3931 n.set_poor_tax(int8_t(std::clamp(n.get_poor_tax() + 2, 10, std::max(10, max_poor_tax))));
3932 n.set_middle_tax(int8_t(std::clamp(n.get_middle_tax() + 3, 10, std::max(10, max_mid_tax))));
3933 n.set_rich_tax(int8_t(std::clamp(n.get_rich_tax() + 5, 10, std::max(10, max_rich_tax))));
3934 }
else if(n.get_last_treasury() < n.get_stockpiles(
economy::money)) {
3938 if(n.get_ai_is_threatened()) {
3939 n.set_military_spending(int8_t(std::min(100, n.get_military_spending() + 10)));
3941 n.set_military_spending(int8_t(std::min(75, n.get_military_spending() + 10)));
3943 n.set_social_spending(int8_t(std::min(max_social, n.get_social_spending() + 2)));
3946 n.set_poor_tax(int8_t(std::clamp(n.get_poor_tax() - 2, 10, std::max(10, max_poor_tax))));
3947 n.set_middle_tax(int8_t(std::clamp(n.get_middle_tax() - 3, 10, std::max(10, max_mid_tax))));
3948 n.set_rich_tax(int8_t(std::clamp(n.get_rich_tax() - 5, 10, std::max(10, max_rich_tax))));
3952 int max_poor_tax = int(10.f + 90.f * (1.f - poor_militancy));
3953 int max_mid_tax = int(10.f + 90.f * (1.f - mid_militancy));
3954 int max_rich_tax = int(10.f + 40.f * (1.f - rich_militancy));
3955 int max_social = int(100.f * poor_militancy);
3958 bool enough_tax =
true;
3959 if(ratio_education < 50.f) {
3961 n.set_poor_tax(int8_t(std::clamp(n.get_poor_tax() + 5, 10, std::max(10, max_poor_tax))));
3962 n.set_middle_tax(int8_t(std::clamp(n.get_middle_tax() + 3, 10, std::max(10, max_mid_tax))));
3963 n.set_rich_tax(int8_t(std::clamp(n.get_rich_tax() + 2, 10, std::max(10, max_rich_tax))));
3967 if(n.get_spending_level() < 1.0f || n.get_last_treasury() >= n.get_stockpiles(
economy::money) || ratio_education < 50.f) {
3971 if(!n.get_ai_is_threatened()) {
3972 n.set_military_spending(int8_t(std::max(50, n.get_military_spending() - 5)));
3974 n.set_social_spending(int8_t(std::max(0, n.get_social_spending() - 2)));
3976 n.set_poor_tax(int8_t(std::clamp(n.get_poor_tax() + 5, 10, std::max(10, max_poor_tax))));
3977 n.set_middle_tax(int8_t(std::clamp(n.get_middle_tax() + 3, 10, std::max(10, max_mid_tax))));
3978 n.set_rich_tax(int8_t(std::clamp(n.get_rich_tax() + 2, 10, std::max(10, max_rich_tax))));
3979 }
else if(n.get_last_treasury() < n.get_stockpiles(
economy::money)) {
3983 if(n.get_ai_is_threatened()) {
3984 n.set_military_spending(int8_t(std::min(100, n.get_military_spending() + 10)));
3986 n.set_military_spending(int8_t(std::min(75, n.get_military_spending() + 10)));
3988 n.set_social_spending(int8_t(std::min(max_social, n.get_social_spending() + 2)));
3991 n.set_poor_tax(int8_t(std::clamp(n.get_poor_tax() - 5, 10, std::max(10, max_poor_tax))));
3992 n.set_middle_tax(int8_t(std::clamp(n.get_middle_tax() - 3, 10, std::max(10, max_mid_tax))));
3993 n.set_rich_tax(int8_t(std::clamp(n.get_rich_tax() - 2, 10, std::max(10, max_rich_tax))));
3998 n.set_administrative_spending(int8_t(std::min(int8_t(administration_max_ratio), n.get_administrative_spending())));
3999 n.set_administrative_spending(int8_t(administration_max_ratio));
4000 n.set_military_spending(int8_t(std::min(int8_t(soldiers_max_ratio), n.get_military_spending())));
4001 n.set_overseas_spending(int8_t(overseas_max_ratio));
4009 for(
auto ar : state.world.nation_get_army_control(n)) {
4010 ar.get_army().set_ai_activity(0);
4011 ar.get_army().set_ai_province(dcon::province_id{});
4013 for(
auto v : state.world.nation_get_navy_control(n)) {
4014 v.get_navy().set_ai_activity(0);
4020 return fat_id.get_controller_from_army_control().get_is_player_controlled()
4021 ? fat_id.get_is_ai_controlled()
4032 static std::vector<dcon::ship_id> to_delete;
4034 for(
auto n : state.world.in_nation) {
4035 if(n.get_is_player_controlled())
4038 for(
auto v : n.get_navy_control()) {
4039 if(!v.get_navy().get_battle_from_navy_battle_participation()) {
4040 for(
auto shp : v.get_navy().get_navy_membership()) {
4041 to_delete.push_back(shp.get_ship().id);
4045 }
else if(n.get_is_at_war() ==
false) {
4046 dcon::unit_type_id best_transport;
4047 dcon::unit_type_id best_light;
4048 dcon::unit_type_id best_big;
4049 for(
uint32_t i = 2; i < state.military_definitions.unit_base_definitions.size(); ++i) {
4050 dcon::unit_type_id j{ dcon::unit_type_id::value_base_t(i) };
4051 if(!n.get_active_unit(j) && !state.military_definitions.unit_base_definitions[j].active)
4054 if(!best_transport || state.military_definitions.unit_base_definitions[best_transport].defence_or_hull < state.military_definitions.unit_base_definitions[j].defence_or_hull) {
4058 if(!best_light || state.military_definitions.unit_base_definitions[best_light].defence_or_hull < state.military_definitions.unit_base_definitions[j].defence_or_hull) {
4062 if(!best_big || state.military_definitions.unit_base_definitions[best_big].defence_or_hull < state.military_definitions.unit_base_definitions[j].defence_or_hull) {
4067 for(
auto v : n.get_navy_control()) {
4068 if(!v.get_navy().get_battle_from_navy_battle_participation()) {
4069 auto trange = v.get_navy().get_army_transport();
4072 for(
auto shp : v.get_navy().get_navy_membership()) {
4073 auto type = shp.get_ship().get_type();
4076 if(best_transport && type != best_transport)
4077 to_delete.push_back(shp.get_ship().id);
4079 if(best_light && type != best_light)
4080 to_delete.push_back(shp.get_ship().id);
4082 if(best_big && type != best_big)
4083 to_delete.push_back(shp.get_ship().id);
4090 for(
auto s : to_delete) {
4091 state.world.delete_ship(s);
4096 for(
auto n : state.world.in_nation) {
4097 if(!n.get_is_player_controlled() && n.get_province_naval_construction().begin() == n.get_province_naval_construction().end()) {
4098 auto disarm = n.get_disarmed_until();
4099 if(disarm && state.current_date < disarm)
4102 dcon::unit_type_id best_transport;
4103 dcon::unit_type_id best_light;
4104 dcon::unit_type_id best_big;
4106 for(
uint32_t i = 2; i < state.military_definitions.unit_base_definitions.size(); ++i) {
4107 dcon::unit_type_id j{ dcon::unit_type_id::value_base_t(i) };
4108 if(!n.get_active_unit(j) && !state.military_definitions.unit_base_definitions[j].active)
4112 if(!best_transport || state.military_definitions.unit_base_definitions[best_transport].defence_or_hull < state.military_definitions.unit_base_definitions[j].defence_or_hull) {
4116 if(!best_light || state.military_definitions.unit_base_definitions[best_light].defence_or_hull < state.military_definitions.unit_base_definitions[j].defence_or_hull) {
4120 if(!best_big || state.military_definitions.unit_base_definitions[best_big].defence_or_hull < state.military_definitions.unit_base_definitions[j].defence_or_hull) {
4126 int32_t num_transports = 0;
4127 int32_t fleet_cap_in_transports = 0;
4128 int32_t fleet_cap_in_small = 0;
4129 int32_t fleet_cap_in_big = 0;
4131 for(
auto v : n.get_navy_control()) {
4132 for(
auto s : v.get_navy().get_navy_membership()) {
4133 auto type = s.get_ship().get_type();
4136 fleet_cap_in_transports += state.military_definitions.unit_base_definitions[type].supply_consumption_score;
4138 fleet_cap_in_big += state.military_definitions.unit_base_definitions[type].supply_consumption_score;
4140 fleet_cap_in_small += state.military_definitions.unit_base_definitions[type].supply_consumption_score;
4145 static std::vector<dcon::province_id> owned_ports;
4146 owned_ports.clear();
4147 for(
auto p : n.get_province_ownership()) {
4148 if(p.get_province().get_is_coast() && p.get_province().get_nation_from_province_control() == n) {
4149 owned_ports.push_back(p.get_province().id);
4152 auto cap = n.get_capital().id;
4153 std::sort(owned_ports.begin(), owned_ports.end(), [&](dcon::province_id a, dcon::province_id b) {
4154 auto a_dist = province::sorting_distance(state, a, cap);
4155 auto b_dist = province::sorting_distance(state, b, cap);
4156 if(a_dist != b_dist)
4157 return a_dist < b_dist;
4159 return a.index() < b.index();
4162 int32_t constructing_fleet_cap = 0;
4163 if(best_transport) {
4164 if(fleet_cap_in_transports * 3 < n.get_naval_supply_points()) {
4165 auto overseas_allowed = state.military_definitions.unit_base_definitions[best_transport].can_build_overseas;
4166 auto level_req = state.military_definitions.unit_base_definitions[best_transport].min_port_level;
4167 auto supply_pts = state.military_definitions.unit_base_definitions[best_transport].supply_consumption_score;
4169 for(
uint32_t j = 0; j < owned_ports.size() && (fleet_cap_in_transports + constructing_fleet_cap) * 3 < n.get_naval_supply_points(); ++j) {
4173 auto c = fatten(state.world, state.world.try_create_province_naval_construction(owned_ports[j], n));
4174 c.set_type(best_transport);
4175 constructing_fleet_cap += supply_pts;
4178 }
else if(num_transports < 10) {
4179 auto overseas_allowed = state.military_definitions.unit_base_definitions[best_transport].can_build_overseas;
4180 auto level_req = state.military_definitions.unit_base_definitions[best_transport].min_port_level;
4181 auto supply_pts = state.military_definitions.unit_base_definitions[best_transport].supply_consumption_score;
4183 for(
uint32_t j = 0; j < owned_ports.size() && num_transports < 10; ++j) {
4187 auto c = fatten(state.world, state.world.try_create_province_naval_construction(owned_ports[j], n));
4188 c.set_type(best_transport);
4190 constructing_fleet_cap += supply_pts;
4196 int32_t used_points = n.get_used_naval_supply_points();
4197 auto rem_free = n.get_naval_supply_points() - (fleet_cap_in_transports + fleet_cap_in_small + fleet_cap_in_big + constructing_fleet_cap);
4198 fleet_cap_in_small = std::max(fleet_cap_in_small, 1);
4199 fleet_cap_in_big = std::max(fleet_cap_in_big, 1);
4201 auto free_big_points = best_light ? rem_free * fleet_cap_in_small / (fleet_cap_in_small + fleet_cap_in_big) : rem_free;
4202 auto free_small_points = best_big ? rem_free * fleet_cap_in_big / (fleet_cap_in_small + fleet_cap_in_big) : rem_free;
4205 auto overseas_allowed = state.military_definitions.unit_base_definitions[best_light].can_build_overseas;
4206 auto level_req = state.military_definitions.unit_base_definitions[best_light].min_port_level;
4207 auto supply_pts = state.military_definitions.unit_base_definitions[best_light].supply_consumption_score;
4209 for(
uint32_t j = 0; j < owned_ports.size() && supply_pts <= free_small_points; ++j) {
4213 auto c = fatten(state.world, state.world.try_create_province_naval_construction(owned_ports[j], n));
4214 c.set_type(best_light);
4215 free_small_points -= supply_pts;
4220 auto overseas_allowed = state.military_definitions.unit_base_definitions[best_big].can_build_overseas;
4221 auto level_req = state.military_definitions.unit_base_definitions[best_big].min_port_level;
4222 auto supply_pts = state.military_definitions.unit_base_definitions[best_big].supply_consumption_score;
4224 for(
uint32_t j = 0; j < owned_ports.size() && supply_pts <= free_big_points; ++j) {
4228 auto c = fatten(state.world, state.world.try_create_province_naval_construction(owned_ports[j], n));
4229 c.set_type(best_big);
4230 free_big_points -= supply_pts;
4239 auto cap = state.world.nation_get_capital(n);
4240 int32_t max_level = -1;
4241 dcon::province_id result;
4242 float current_distance = 1.0f;
4243 for(
auto p : state.world.nation_get_province_ownership(n)) {
4244 if(p.get_province().get_is_coast() && p.get_province().get_nation_from_province_control() == n) {
4247 result = p.get_province();
4251 result = p.get_province();
4259 for(
auto n : state.world.in_nation) {
4260 if(!n.get_is_player_controlled() && n.get_owned_province_count() > 0) {
4284 for(
auto shp : state.world.navy_get_navy_membership(n)) {
4285 if(shp.get_ship().get_strength() < 0.5f)
4294 for(
auto par : state.world.nation_get_war_participant(n)) {
4295 for(
auto other : par.get_war().get_war_participant()) {
4296 if(other.get_is_attacker() != par.get_is_attacker()) {
4297 if(other.get_nation().get_used_naval_supply_points() > state.world.nation_get_used_naval_supply_points(n))
4306 auto v = fatten(state.world, n);
4307 auto home_port = v.get_controller_from_navy_control().get_ai_home_port();
4308 if(v.get_location_from_navy_location() == home_port) {
4309 v.set_ai_activity(
uint8_t(at_base));
4310 }
else if(!home_port) {
4311 v.set_ai_activity(
uint8_t(fleet_activity::unspecified));
4312 }
else if(
auto naval_path =
province::make_naval_path(state, v.get_location_from_navy_location(), home_port); naval_path.size() > 0) {
4313 auto new_size =
uint32_t(naval_path.size());
4314 auto existing_path = v.get_path();
4315 existing_path.resize(new_size);
4317 for(
uint32_t i = 0; i < new_size; ++i) {
4318 existing_path[i] = naval_path[i];
4321 v.set_ai_activity(
uint8_t(moving_status));
4323 v.set_ai_activity(
uint8_t(fleet_activity::unspecified));
4328 dcon::province_id result;
4329 float closest = 0.0f;
4330 for(
auto par : state.world.nation_get_war_participant(n)) {
4331 for(
auto other : par.get_war().get_war_participant()) {
4332 if(other.get_is_attacker() != par.get_is_attacker()) {
4333 for(
auto nv : other.get_nation().get_navy_control()) {
4334 auto loc = nv.get_navy().get_location_from_navy_location();
4336 if(!result || dist < closest) {
4337 if(loc.id.index() < state.province_definitions.first_sea_province.index()) {
4338 result = loc.get_port_to();
4353 auto existing_path = state.world.navy_get_path(for_navy);
4355 if(path.size() > 0) {
4357 existing_path.resize(new_size);
4358 for(
uint32_t i = new_size; i-- > 0;) {
4359 assert(path[path.size() - 1 - i]);
4360 existing_path[new_size - 1 - i] = path[path.size() - 1 - i];
4363 state.world.navy_set_ai_activity(for_navy,
uint8_t(fleet_activity::attacking));
4374 auto transported_armies = state.world.navy_get_army_transport(n);
4375 auto location = state.world.navy_get_location_from_navy_location(n);
4378 for(
auto ar : transported_armies) {
4379 auto path =
province::make_land_path(state, location, ar.get_army().get_ai_province(), ar.get_army().get_controller_from_army_control(), ar.get_army());
4380 if(path.size() > 0) {
4381 auto existing_path = ar.get_army().get_path();
4382 auto new_size =
uint32_t(path.size());
4383 existing_path.resize(new_size);
4385 for(
uint32_t i = 0; i < new_size; ++i) {
4387 existing_path[i] = path[i];
4390 ar.get_army().set_dig_in(0);
4391 auto activity =
army_activity(ar.get_army().get_ai_activity());
4392 if(activity == army_activity::transport_guard) {
4393 ar.get_army().set_ai_activity(
uint8_t(army_activity::on_guard));
4394 }
else if(activity == army_activity::transport_attack) {
4395 ar.get_army().set_ai_activity(
uint8_t(army_activity::attack_gathered));
4400 state.world.navy_set_ai_activity(n,
uint8_t(fleet_activity::unloading));
4404 auto merge_target = [&]() {
4405 dcon::navy_id largest;
4406 int32_t largest_size = 0;
4407 for(
auto on : state.world.province_get_navy_location(p)) {
4408 if(on.get_navy() != n && on.get_navy().get_controller_from_navy_control() == owner) {
4409 auto other_mem = on.get_navy().get_navy_membership();
4410 if(
auto sz = int32_t(other_mem.end() - other_mem.begin()); sz > largest_size) {
4411 largest = on.get_navy().id;
4423 auto regs = state.world.navy_get_navy_membership(n);
4424 while(regs.begin() != regs.end()) {
4425 auto reg = (*regs.begin()).get_ship();
4426 reg.set_navy_from_navy_membership(merge_target);
4429 auto transported = state.world.navy_get_army_transport(n);
4430 while(transported.begin() != transported.end()) {
4431 auto arm = (*transported.begin()).get_army();
4432 arm.set_navy_from_army_transport(merge_target);
4438 for(
auto n : state.world.in_navy) {
4439 if(n.get_battle_from_navy_battle_participation())
4441 if(n.get_arrival_time())
4444 auto owner = n.get_controller_from_navy_control();
4446 if(!owner || owner.get_is_player_controlled() || owner.get_owned_province_count() == 0)
4449 auto home_port = state.world.nation_get_ai_home_port(owner);
4453 auto location = state.world.navy_get_location_from_navy_location(n);
4454 auto activity =
fleet_activity(state.world.navy_get_ai_activity(n));
4457 case fleet_activity::unspecified:
4458 if(location == home_port) {
4460 state.world.navy_set_ai_activity(n,
uint8_t(fleet_activity::idle));
4461 }
else if(!home_port) {
4468 case fleet_activity::boarding:
4470 bool all_loaded =
true;
4471 for(
auto ar : state.world.nation_get_army_control(owner)) {
4472 if(ar.get_army().get_ai_activity() ==
uint8_t(army_activity::transport_guard) || ar.get_army().get_ai_activity() ==
uint8_t(army_activity::transport_attack)) {
4473 if(ar.get_army().get_navy_from_army_transport() != n)
4479 auto transporting_range = n.get_army_transport();
4480 if(transporting_range.begin() == transporting_range.end()) {
4483 auto transported_dest = (*(transporting_range.begin())).get_army().get_ai_province();
4486 if(transported_dest.get_is_coast()) {
4487 auto target_prov = transported_dest.id;
4489 target_prov = state.world.province_get_port_to(target_prov);
4493 auto existing_path = n.get_path();
4494 auto new_size =
uint32_t(naval_path.size());
4495 existing_path.resize(new_size);
4497 for(
uint32_t k = 0; k < new_size; ++k) {
4498 existing_path[k] = naval_path[k];
4502 n.set_ai_activity(
uint8_t(fleet_activity::transporting));
4511 auto target_prov = path.front();
4513 target_prov = state.world.province_get_port_to(target_prov);
4517 auto existing_path = n.get_path();
4518 auto new_size =
uint32_t(naval_path.size());
4519 existing_path.resize(new_size);
4521 for(
uint32_t k = 0; k < new_size; ++k) {
4522 existing_path[k] = naval_path[k];
4526 n.set_ai_activity(
uint8_t(fleet_activity::transporting));
4536 case fleet_activity::transporting:
4539 case fleet_activity::failed_transport:
4540 if(location == home_port) {
4542 state.world.navy_set_ai_activity(n,
uint8_t(fleet_activity::idle));
4543 }
else if(home_port) {
4544 auto existing_path = state.world.navy_get_path(n);
4546 if(path.size() > 0) {
4547 auto new_size =
uint32_t(path.size());
4548 existing_path.resize(new_size);
4550 for(
uint32_t i = 0; i < new_size; ++i) {
4552 existing_path[i] = path[i];
4558 case fleet_activity::returning_to_base:
4559 if(location == home_port) {
4561 state.world.navy_set_ai_activity(n,
uint8_t(fleet_activity::idle));
4566 case fleet_activity::attacking:
4567 if(state.world.nation_get_is_at_war(owner) ==
false) {
4579 case fleet_activity::merging:
4580 if(location == home_port) {
4582 state.world.navy_set_ai_activity(n,
uint8_t(fleet_activity::idle));
4587 case fleet_activity::idle:
4588 if(location != home_port) {
4589 state.world.navy_set_ai_activity(n,
uint8_t(fleet_activity::unspecified));
4590 }
else if(owner.get_is_at_war()) {
4592 bool valid_attacker =
true;
4593 auto self_ships = state.world.navy_get_navy_membership(n);
4594 int32_t self_sz = int32_t(self_ships.end() - self_ships.begin());
4595 for(
auto o : owner.get_navy_control()) {
4596 if(o.get_navy() != n) {
4597 if(o.get_navy().get_ai_activity() ==
uint8_t(fleet_activity::attacking)) {
4598 valid_attacker =
false;
4601 auto orange = o.get_navy().get_navy_membership();
4602 if(int32_t(orange.end() - orange.begin()) >= self_sz) {
4603 valid_attacker =
false;
4609 set_fleet_target(state, owner, state.world.navy_get_location_from_navy_location(n), n);
4614 case fleet_activity::unloading:
4618 auto transporting = state.world.navy_get_army_transport(n);
4620 if(ar.get_army().get_path().size() != 0) {
4627 state.world.navy_set_ai_activity(n,
uint8_t(fleet_activity::unspecified));
4630 state.world.navy_set_ai_activity(n,
uint8_t(fleet_activity::failed_transport));
4657 std::vector<classified_province> provinces;
4658 provinces.reserve(state.world.province_size());
4660 auto cap = state.world.nation_get_capital(n);
4662 for(
auto c : state.world.nation_get_province_control(n)) {
4663 province_class cls = c.get_province().get_is_coast() ? province_class::coast : province_class::interior;
4664 if(c.get_province() == cap)
4665 cls = province_class::border;
4667 for(
auto padj : c.get_province().get_province_adjacency()) {
4668 auto other = padj.get_connected_provinces(0) == c.get_province() ? padj.get_connected_provinces(1) : padj.get_connected_provinces(0);
4669 auto n_controller = other.get_nation_from_province_control();
4670 auto ovr = n_controller.get_overlord_as_subject().get_ruler();
4672 if(n_controller == n) {
4674 }
else if(!n_controller && !other.get_rebel_faction_from_province_rebel_control()) {
4676 }
else if(other.get_rebel_faction_from_province_rebel_control()) {
4677 cls = province_class::hostile_border;
4680 cls = province_class::hostile_border;
4684 if(
uint8_t(cls) <
uint8_t(province_class::low_priority_border)) {
4685 cls = province_class::low_priority_border;
4691 bool is_threat =
false;
4693 is_threat |= n_controller.get_ai_rival() == n;
4694 is_threat |= state.world.nation_get_ai_rival(n) == n_controller.id;
4697 is_threat |= ovr.get_ai_rival() == n;
4698 is_threat |= state.world.nation_get_ai_rival(n) == ovr.id;
4700 is_threat |= ovr.get_constructing_cb_target() == n;
4701 for(
auto cb : ovr.get_available_cbs())
4702 is_threat |= cb.target == n;
4704 is_threat |= n_controller.get_constructing_cb_target() == n;
4705 for(
auto cb : n_controller.get_available_cbs())
4706 is_threat |= cb.target == n;
4711 cls = province_class::threat_border;
4715 cls = province_class::border;
4725 return uint8_t(a.c) > uint8_t(b.c);
4729 if(adist != bdist) {
4730 return adist < bdist;
4732 return a.
id.index() < b.
id.index();
4736 std::vector<dcon::army_id> guards_list;
4737 guards_list.reserve(state.world.army_size());
4738 for(
auto a : state.world.nation_get_army_control(n)) {
4739 if(a.get_army().get_ai_activity() ==
uint8_t(army_activity::on_guard)) {
4740 guards_list.push_back(a.get_army().id);
4747 for(
uint8_t stage =
uint8_t(province_class::count); stage-- > 0 && !guards_list.empty(); ) {
4748 uint32_t start_of_stage = end_of_stage;
4750 for(; end_of_stage <
provinces.size(); ++end_of_stage) {
4751 if(
uint8_t(provinces[end_of_stage].c) != stage)
4756 bool guard_assigned =
false;
4758 guard_assigned =
false;
4759 for(
uint32_t j = start_of_stage; j < end_of_stage && !guards_list.empty(); ++j) {
4761 auto p_region =
state.world.province_get_connected_region_id(provinces[j].
id);
4763 bool p_region_is_coastal =
state.province_definitions.connected_region_is_coastal[p_region - 1];
4767 dcon::army_id nearest;
4768 float nearest_distance = 1.0f;
4770 auto guard_loc =
state.world.army_get_location_from_army_location(guards_list[k]);
4790 nearest_distance =
d;
4791 nearest = guards_list[k];
4797 state.world.army_set_ai_province(nearest, p);
4798 guards_list[nearest_index] = guards_list.back();
4799 guards_list.pop_back();
4801 guard_assigned =
true;
4806 ++full_loops_through;
4807 }
while(guard_assigned);
4814 dcon::navy_id transport_fleet;
4816 for(
auto v : state.world.nation_get_navy_control(controller)) {
4817 if(v.get_navy().get_battle_from_navy_battle_participation())
4819 auto members = v.get_navy().get_navy_membership();
4821 auto tsize = int32_t(members.end() - members.begin());
4822 if(tsize <= n_size || tsize <= 1)
4826 transport_fleet = dcon::navy_id{};
4829 if(activity == fleet_activity::attacking || activity == fleet_activity::idle || activity == fleet_activity::returning_to_base) {
4830 auto in_transport = v.get_navy().get_army_transport();
4831 if(in_transport.begin() == in_transport.end()) {
4832 transport_fleet = v.get_navy();
4837 return transport_fleet;
4841 std::vector<dcon::army_id> require_transport;
4842 require_transport.reserve(state.world.army_size());
4844 for(
auto ar : state.world.in_army) {
4845 if(ar.get_ai_activity() ==
uint8_t(army_activity::on_guard)
4846 && ar.get_ai_province()
4847 && ar.get_ai_province() != ar.get_location_from_army_location()
4848 && ar.get_controller_from_army_control()
4850 && !ar.get_arrival_time()
4851 && !ar.get_battle_from_army_battle_participation()
4852 && !ar.get_navy_from_army_transport()) {
4855 if(path.size() > 0) {
4856 auto existing_path = ar.get_path();
4857 auto new_size =
uint32_t(path.size());
4858 existing_path.resize(new_size);
4860 for(
uint32_t i = 0; i < new_size; ++i) {
4862 existing_path[i] = path[i];
4868 if(!ar.get_controller_from_army_control().get_is_player_controlled())
4869 require_transport.push_back(ar.id);
4874 for(
uint32_t i = 0; i < require_transport.size(); ++i) {
4875 auto coastal_target_prov = state.world.army_get_location_from_army_location(require_transport[i]);
4876 auto controller = state.world.army_get_controller_from_army_control(require_transport[i]);
4880 auto regs = state.world.army_get_army_membership(require_transport[i]);
4883 tcap -= int32_t(regs.end() - regs.begin());
4885 if(tcap < 0 || (state.world.nation_get_is_at_war(controller) && !
naval_advantage(state, controller))) {
4887 if(state.world.army_get_controller_from_army_control(require_transport[j]) == controller) {
4888 state.world.army_set_ai_province(require_transport[j], dcon::province_id{});
4889 require_transport[j] = require_transport.back();
4890 require_transport.pop_back();
4893 state.world.army_set_ai_province(require_transport[i], dcon::province_id{});
4897 if(!state.world.province_get_is_coast(coastal_target_prov)) {
4898 auto path = state.world.army_get_black_flag(require_transport[i])
4902 state.world.army_set_ai_province(require_transport[i], dcon::province_id{});
4905 coastal_target_prov = path.front();
4907 auto existing_path = state.world.army_get_path(require_transport[i]);
4908 auto new_size =
uint32_t(path.size());
4909 existing_path.resize(new_size);
4911 for(
uint32_t k = 0; k < new_size; ++k) {
4913 existing_path[k] = path[k];
4915 state.world.army_set_arrival_time(require_transport[i],
military::arrival_time_to(state, require_transport[i], path.back()));
4916 state.world.army_set_dig_in(require_transport[i], 0);
4917 state.world.army_set_dig_in(require_transport[i], 0);
4923 if(fleet_destination == state.world.navy_get_location_from_navy_location(transport_fleet)) {
4924 state.world.navy_get_path(transport_fleet).clear();
4925 state.world.navy_set_arrival_time(transport_fleet,
sys::date{});
4926 state.world.navy_set_ai_activity(transport_fleet,
uint8_t(fleet_activity::boarding));
4927 }
else if(
auto fleet_path =
province::make_naval_path(state, state.world.navy_get_location_from_navy_location(transport_fleet), fleet_destination); fleet_path.empty()) {
4930 auto existing_path = state.world.navy_get_path(transport_fleet);
4931 auto new_size =
uint32_t(fleet_path.size());
4932 existing_path.resize(new_size);
4934 for(
uint32_t k = 0; k < new_size; ++k) {
4936 existing_path[k] = fleet_path[k];
4938 state.world.navy_set_arrival_time(transport_fleet,
military::arrival_time_to(state, transport_fleet, fleet_path.back()));
4939 state.world.navy_set_ai_activity(transport_fleet,
uint8_t(fleet_activity::boarding));
4943 state.world.army_set_ai_activity(require_transport[i],
uint8_t(army_activity::transport_guard));
4945 auto destination_region = state.world.province_get_connected_region_id(state.world.army_get_ai_province(require_transport[i]));
4949 if(state.world.army_get_controller_from_army_control(require_transport[j]) == controller) {
4950 auto jregs = state.world.army_get_army_membership(require_transport[j]);
4951 if(tcap >= (jregs.end() - jregs.begin())) {
4952 if(state.world.province_get_connected_region_id(state.world.army_get_ai_province(require_transport[j])) != destination_region)
4955 if(state.world.army_get_location_from_army_location(require_transport[j]) == coastal_target_prov) {
4956 state.world.army_set_ai_activity(require_transport[i],
uint8_t(army_activity::transport_guard));
4957 tcap -= int32_t(jregs.end() - jregs.begin());
4959 auto jpath = state.world.army_get_black_flag(require_transport[j])
4960 ?
province::make_land_path(state, state.world.army_get_location_from_army_location(require_transport[j]), coastal_target_prov, controller, require_transport[j])
4962 if(!jpath.empty()) {
4963 auto existing_path = state.world.army_get_path(require_transport[j]);
4964 auto new_size =
uint32_t(jpath.size());
4965 existing_path.resize(new_size);
4967 for(
uint32_t k = 0; k < new_size; ++k) {
4969 existing_path[k] = jpath[k];
4971 state.world.army_set_arrival_time(require_transport[j],
military::arrival_time_to(state, require_transport[j], jpath.back()));
4972 state.world.army_set_dig_in(require_transport[j], 0);
4973 state.world.army_set_ai_activity(require_transport[i],
uint8_t(army_activity::transport_guard));
4974 tcap -= int32_t(jregs.end() - jregs.begin());
4979 require_transport[j] = require_transport.back();
4980 require_transport.pop_back();
4989 for(
auto ar : state.world.in_army) {
4990 if(ar.get_battle_from_army_battle_participation())
4992 if(ar.get_navy_from_army_transport())
4994 if(ar.get_arrival_time())
4997 if(ar.get_ai_activity() ==
uint8_t(army_activity::transport_guard) || ar.get_ai_activity() ==
uint8_t(army_activity::transport_attack)) {
4998 auto controller = ar.get_controller_from_army_control();
4999 dcon::navy_id transports;
5000 for(
auto v : controller.get_navy_control()) {
5001 if(v.get_navy().get_ai_activity() ==
uint8_t(fleet_activity::boarding)) {
5002 transports = v.get_navy();
5006 ar.set_ai_activity(
uint8_t(army_activity::on_guard));
5007 ar.set_ai_province(dcon::province_id{});
5010 if(state.world.navy_get_arrival_time(transports) || state.world.navy_get_battle_from_navy_battle_participation(transports))
5013 auto army_location = ar.get_location_from_army_location();
5014 auto transport_location = state.world.navy_get_location_from_navy_location(transports);
5015 if(transport_location == army_location) {
5016 ar.set_navy_from_army_transport(transports);
5017 ar.set_black_flag(
false);
5018 }
else if(army_location.get_port_to() == transport_location) {
5019 auto existing_path = ar.get_path();
5020 existing_path.resize(1);
5021 assert(transport_location);
5022 existing_path[0] = transport_location;
5026 ar.set_ai_activity(
uint8_t(army_activity::on_guard));
5027 ar.set_ai_province(dcon::province_id{});
5034 dcon::regiment_id sample_reg;
5035 auto regs = state.world.army_get_army_membership(a);
5036 if(regs.begin() != regs.end()) {
5037 sample_reg = (*regs.begin()).get_regiment().id;
5043 auto spending_level = state.world.nation_get_effective_land_spending(n);
5044 auto max_org = 0.25f + 0.75f * spending_level;
5046 return state.world.regiment_get_org(sample_reg) > 0.7f * max_org;
5050 for(
auto ar : state.world.nation_get_army_control(n)) {
5052 if(ar.get_army().get_battle_from_army_battle_participation()
5053 || ar.get_army().get_navy_from_army_transport()
5054 || ar.get_army().get_black_flag()
5055 || ar.get_army().get_arrival_time()
5056 || (activity != army_activity::on_guard && activity != army_activity::attacking && activity != army_activity::attack_gathered && activity != army_activity::attack_transport)
5062 auto location = ar.get_army().get_location_from_army_location();
5067 if(sdist > state.defines.alice_ai_gather_radius)
5071 if(!jpath.empty()) {
5073 auto existing_path = ar.get_army().get_path();
5074 auto new_size =
uint32_t(jpath.size());
5075 existing_path.resize(new_size * 2);
5077 for(
uint32_t k = 0; k < new_size; ++k) {
5079 existing_path[new_size + k] = jpath[k];
5081 for(
uint32_t k = 1; k < new_size; ++k) {
5083 existing_path[new_size - k] = jpath[k];
5086 existing_path[0] = location;
5088 ar.get_army().set_dig_in(0);
5095 auto regs = state.world.army_get_army_membership(a);
5096 if(regs.begin() == regs.end())
5100 float total_str = 0.f;
5101 float str_art = 0.f;
5102 float str_inf = 0.f;
5103 float str_cav = 0.f;
5104 for(
const auto reg : regs) {
5105 float str = reg.get_regiment().get_strength() * reg.get_regiment().get_org();
5106 if(
auto utid = reg.get_regiment().get_type(); utid) {
5107 switch(state.military_definitions.unit_base_definitions[utid].type) {
5124 if(total_str == 0.f)
5128 float min_cav = std::min(str_cav, str_inf * (1.f / 4.f));
5129 float scale = 1.f -
math::sin(std::abs(std::min(str_art / total_str, str_inf / total_str) - (4.f * min_cav / total_str)));
5130 return total_str * scale;
5134 float scale = state.world.army_get_controller_from_army_control(a) ? 1.f : 0.5f;
5136 if(
auto gen = state.world.army_get_general_from_army_leadership(a); gen) {
5137 auto n = state.world.army_get_controller_from_army_control(a);
5139 n = state.world.national_identity_get_nation_from_identity_holder(state.national_definitions.rebel_id);
5140 auto back = state.world.leader_get_background(gen);
5141 auto pers = state.world.leader_get_personality(gen);
5142 float morale = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::org_regain)
5143 + state.world.leader_trait_get_morale(back)
5144 + state.world.leader_trait_get_morale(pers) + 1.0f;
5145 float org = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::land_organisation)
5146 + state.world.leader_trait_get_organisation(back)
5147 + state.world.leader_trait_get_organisation(pers) + 1.0f;
5148 float def = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::land_defense_modifier)
5149 + state.world.leader_trait_get_defense(back)
5150 + state.world.leader_trait_get_defense(pers) + 1.0f;
5151 scale += def * morale * org;
5152 scale += state.world.nation_get_has_gas_defense(n) ? 10.f : 0.f;
5155 float terrain_bonus = state.world.province_get_modifier_values(state.world.army_get_location_from_army_location(a), sys::provincial_mod_offsets::defense);
5156 scale += terrain_bonus;
5158 scale += defender_fort;
5161 return std::max(0.1f, strength * scale);
5165 float scale = state.world.army_get_controller_from_army_control(a) ? 1.f : 0.5f;
5167 if(
auto gen = state.world.army_get_general_from_army_leadership(a); gen) {
5168 auto n = state.world.army_get_controller_from_army_control(a);
5170 n = state.world.national_identity_get_nation_from_identity_holder(state.national_definitions.rebel_id);
5171 auto back = state.world.leader_get_background(gen);
5172 auto pers = state.world.leader_get_personality(gen);
5173 float morale = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::org_regain)
5174 + state.world.leader_trait_get_morale(back)
5175 + state.world.leader_trait_get_morale(pers) + 1.0f;
5176 float org = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::land_organisation)
5177 + state.world.leader_trait_get_organisation(back)
5178 + state.world.leader_trait_get_organisation(pers) + 1.0f;
5179 float atk = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::land_attack_modifier)
5180 + state.world.leader_trait_get_attack(back)
5181 + state.world.leader_trait_get_attack(pers) + 1.0f;
5182 scale += atk * morale * org;
5183 scale += state.world.nation_get_has_gas_attack(n) ? 10.f : 0.f;
5187 return std::max(0.1f, strength * scale);
5191 float strength_total = 0.f;
5192 if(state.world.nation_get_is_at_war(by)) {
5193 for(
auto ar : state.world.in_army) {
5194 if(ar.get_is_retreating()
5195 || ar.get_battle_from_army_battle_participation()
5196 || ar.get_controller_from_army_control() == by)
5198 auto loc = ar.get_location_from_army_location();
5200 if(sdist < state.defines.alice_ai_threat_radius) {
5201 auto other_nation = ar.get_controller_from_army_control();
5208 for(
auto ar : state.world.province_get_army_location(target)) {
5209 auto other_nation = ar.get_army().get_controller_from_army_control();
5215 return state.defines.alice_ai_offensive_strength_overestimate * strength_total;
5220 dcon::province_id p;
5223 std::vector<a_str> ready_armies;
5224 ready_armies.reserve(state.world.province_size());
5226 int32_t ready_count = 0;
5227 for(
auto ar : state.world.nation_get_army_control(n)) {
5229 if(ar.get_army().get_battle_from_army_battle_participation()
5230 || ar.get_army().get_navy_from_army_transport()
5231 || ar.get_army().get_black_flag()
5232 || ar.get_army().get_arrival_time()
5233 || activity != army_activity::on_guard
5240 auto loc = ar.get_army().get_location_from_army_location().id;
5241 if(std::find_if(ready_armies.begin(), ready_armies.end(), [loc](a_str
const& v) { return loc == v.p; }) == ready_armies.end()) {
5242 ready_armies.push_back(a_str{ loc, 0.0f });
5246 if(ready_armies.empty())
5249 struct army_target {
5250 float minimal_distance;
5251 dcon::province_id location;
5252 float strength_estimate = 0.0f;
5256 std::vector<army_target> potential_targets;
5257 potential_targets.reserve(state.world.province_size());
5258 for(
auto o : state.world.nation_get_province_ownership(n)) {
5259 if(!o.get_province().get_nation_from_province_control()
5262 potential_targets.push_back(
5268 std::vector<dcon::nation_id> at_war_with;
5269 at_war_with.reserve(state.world.nation_size());
5270 for(
auto w : state.world.nation_get_war_participant(n)) {
5271 auto attacker = w.get_is_attacker();
5272 for(
auto p : w.get_war().get_war_participant()) {
5273 if(p.get_is_attacker() != attacker) {
5274 if(std::find(at_war_with.begin(), at_war_with.end(), p.get_nation().id) == at_war_with.end()) {
5275 at_war_with.push_back(p.get_nation().id);
5280 for(
auto w : at_war_with) {
5281 for(
auto o : state.world.nation_get_province_control(w)) {
5282 potential_targets.push_back(
5286 for(
auto o : state.world.nation_get_province_ownership(w)) {
5287 if(!o.get_province().get_nation_from_province_control()) {
5288 potential_targets.push_back(
5295 for(
const auto ovr : state.world.nation_get_overlord_as_ruler(n)) {
5296 auto w = ovr.get_subject();
5297 for(
auto o : state.world.nation_get_province_ownership(w)) {
5298 if(!o.get_province().get_nation_from_province_control()
5301 potential_targets.push_back(
5308 for(
auto& pt : potential_targets) {
5311 if(sdist < pt.minimal_distance) {
5312 pt.minimal_distance = sdist;
5316 std::sort(potential_targets.begin(), potential_targets.end(), [&](army_target& a, army_target& b) {
5317 if(a.minimal_distance != b.minimal_distance)
5318 return a.minimal_distance < b.minimal_distance;
5320 return a.location.index() < b.location.index();
5324 bool is_at_war = state.world.nation_get_is_at_war(n);
5325 int32_t min_ready_count = std::min(ready_count, 3);
5326 int32_t max_attacks_to_make = is_at_war ? std::max(min_ready_count, (ready_count + 1) / 3) : ready_count;
5327 auto const psize = potential_targets.size();
5329 for(
uint32_t i = 0; i < psize && max_attacks_to_make > 0; ++i) {
5330 if(!potential_targets[i].location)
5332 if(potential_targets[i].strength_estimate == 0.0f)
5335 auto target_attack_force = potential_targets[i].strength_estimate;
5336 std::sort(ready_armies.begin(), ready_armies.end(), [&](a_str
const& a, a_str
const& b) {
5337 auto adist = province::sorting_distance(state, a.p, potential_targets[i].location);
5338 auto bdist = province::sorting_distance(state, b.p, potential_targets[i].location);
5340 return adist > bdist;
5342 return a.p.index() < b.p.index();
5346 float a_force_str = 0.f;
5347 int32_t k = int32_t(ready_armies.size());
5348 for(; k-- > 0 && a_force_str <= target_attack_force;) {
5349 if(ready_armies[k].str == 0.0f) {
5350 for(
auto ar : state.world.province_get_army_location(ready_armies[k].p)) {
5351 if(ar.get_army().get_battle_from_army_battle_participation()
5352 || n != ar.get_army().get_controller_from_army_control()
5353 || ar.get_army().get_navy_from_army_transport()
5354 || ar.get_army().get_black_flag()
5355 || ar.get_army().get_arrival_time()
5356 ||
army_activity(ar.get_army().get_ai_activity()) != army_activity::on_guard
5364 ready_armies[k].str += 0.00001f;
5366 a_force_str += ready_armies[k].str;
5369 if(a_force_str < target_attack_force) {
5374 dcon::province_id central_province;
5376 glm::vec3 accumulated{ 0.0f, 0.0f, 0.0f };
5377 float minimal_distance = 2.0f;
5379 for(int32_t m = int32_t(ready_armies.size()); m-- > k + 1; ) {
5380 accumulated += state.world.province_get_mid_point_b(ready_armies[m].p);
5382 auto magnitude =
math::sqrt((accumulated.x * accumulated.x + accumulated.y * accumulated.y) + accumulated.z * accumulated.z);
5383 if(magnitude > 0.00001f)
5384 accumulated /= magnitude;
5389 auto pmid = state.world.province_get_mid_point_b(p);
5390 if(
auto dist = -((accumulated.x * pmid.x + accumulated.y * pmid.y) + accumulated.z * pmid.z); dist < minimal_distance) {
5391 minimal_distance = dist;
5392 central_province = p;
5395 if(!central_province)
5399 for(int32_t m = int32_t(ready_armies.size()); m-- > k + 1; ) {
5400 assert(m >= 0 && m < int32_t(ready_armies.size()));
5401 for(
auto ar : state.world.province_get_army_location(ready_armies[m].p)) {
5402 if(ar.get_army().get_battle_from_army_battle_participation()
5403 || n != ar.get_army().get_controller_from_army_control()
5404 || ar.get_army().get_navy_from_army_transport()
5405 || ar.get_army().get_black_flag()
5406 || ar.get_army().get_arrival_time()
5407 ||
army_activity(ar.get_army().get_ai_activity()) != army_activity::on_guard
5413 if(ready_armies[m].p == central_province) {
5414 ar.get_army().set_ai_province(potential_targets[i].location);
5415 ar.get_army().set_ai_activity(
uint8_t(army_activity::attacking));
5417 auto existing_path = ar.get_army().get_path();
5418 auto new_size =
uint32_t(path.size());
5419 existing_path.resize(new_size);
5421 for(
uint32_t q = 0; q < new_size; ++q) {
5423 existing_path[q] = path[q];
5426 ar.get_army().set_dig_in(0);
5427 ar.get_army().set_ai_province(potential_targets[i].location);
5428 ar.get_army().set_ai_activity(
uint8_t(army_activity::attacking));
5433 ready_armies.resize(k + 1);
5434 --max_attacks_to_make;
5438 for(
uint32_t j = i + 1; j < psize; ++j) {
5439 if(
province::sorting_distance(state, potential_targets[j].location, potential_targets[i].location) < state.defines.alice_ai_attack_target_radius)
5440 potential_targets[j].location = dcon::province_id{};
5447 concurrency::parallel_for(
uint32_t(0), state.world.nation_size(), [&](
uint32_t i) {
5448 dcon::nation_id n{ dcon::nation_id::value_base_t(i) };
5449 if(state.world.nation_is_valid(n)) {
5450 assign_targets(state, n);
5456 concurrency::parallel_for(
uint32_t(0), state.world.nation_size(), [&](
uint32_t i) {
5457 dcon::nation_id n{ dcon::nation_id::value_base_t(i) };
5458 if(state.world.nation_is_valid(n)) {
5459 distribute_guards(state, n);
5465 static std::vector<dcon::army_id> require_transport;
5466 require_transport.clear();
5468 for(
auto ar : state.world.in_army) {
5469 if(ar.get_ai_activity() ==
uint8_t(army_activity::attack_transport)) {
5470 if(!ar.get_arrival_time()
5471 && !ar.get_battle_from_army_battle_participation()
5472 && !ar.get_navy_from_army_transport()
5473 && std::find(require_transport.begin(), require_transport.end(), ar.id) == require_transport.end()) {
5477 require_transport.push_back(ar.id);
5479 ar.set_ai_activity(
uint8_t(army_activity::on_guard));
5480 ar.set_ai_province(dcon::province_id{});
5483 }
else if(ar.get_ai_activity() ==
uint8_t(army_activity::attack_gathered)) {
5484 if(!ar.get_arrival_time()
5485 && !ar.get_battle_from_army_battle_participation()
5486 && !ar.get_navy_from_army_transport()) {
5488 if(ar.get_location_from_army_location() == ar.get_ai_province()) {
5489 if(ar.get_location_from_army_location().get_nation_from_province_control() && !
military::are_at_war(state, ar.get_location_from_army_location().get_nation_from_province_control(), ar.get_controller_from_army_control())) {
5491 ar.set_ai_activity(
uint8_t(army_activity::on_guard));
5492 ar.set_ai_province(dcon::province_id{});
5496 if(
auto path =
province::make_land_path(state, ar.get_location_from_army_location(), ar.get_ai_province(), ar.get_controller_from_army_control(), ar); path.size() > 0) {
5498 auto existing_path = ar.get_path();
5499 auto new_size =
uint32_t(path.size());
5500 existing_path.resize(new_size);
5502 for(
uint32_t i = 0; i < new_size; ++i) {
5504 existing_path[i] = path[i];
5509 ar.set_ai_activity(
uint8_t(army_activity::on_guard));
5510 ar.set_ai_province(dcon::province_id{});
5513 ar.set_ai_activity(
uint8_t(army_activity::on_guard));
5514 ar.set_ai_province(dcon::province_id{});
5518 }
else if(ar.get_ai_activity() ==
uint8_t(army_activity::attacking)
5519 && ar.get_ai_province() != ar.get_location_from_army_location()
5520 && !ar.get_arrival_time()
5521 && !ar.get_battle_from_army_battle_participation()
5522 && !ar.get_navy_from_army_transport()) {
5524 bool all_gathered =
true;
5525 for(
auto o : ar.get_controller_from_army_control().get_army_control()) {
5526 if(o.get_army().get_ai_province() == ar.get_ai_province()) {
5527 if(ar.get_location_from_army_location() != o.get_army().get_location_from_army_location()) {
5529 if(o.get_army().get_path().size() > 0 && o.get_army().get_path()[0] == ar.get_location_from_army_location()) {
5530 all_gathered =
false;
5535 if(o.get_army().get_battle_from_army_battle_participation()) {
5536 all_gathered =
false;
5545 if(ar.get_ai_province() == ar.get_location_from_army_location()) {
5546 for(
auto o : ar.get_location_from_army_location().get_army_location()) {
5547 if(o.get_army().get_ai_province() == ar.get_ai_province()
5548 && o.get_army().get_path().size() == 0) {
5550 o.get_army().set_ai_activity(
uint8_t(army_activity::attack_gathered));
5553 }
else if(
auto path =
province::make_land_path(state, ar.get_location_from_army_location(), ar.get_ai_province(), ar.get_controller_from_army_control(), ar); path.size() > 0) {
5555 for(
auto o : ar.get_location_from_army_location().get_army_location()) {
5556 if(o.get_army().get_ai_province() == ar.get_ai_province()
5557 && o.get_army().get_path().size() == 0) {
5559 auto existing_path = o.get_army().get_path();
5560 auto new_size =
uint32_t(path.size());
5561 existing_path.resize(new_size);
5563 for(
uint32_t i = 0; i < new_size; ++i) {
5565 existing_path[i] = path[i];
5568 o.get_army().set_dig_in(0);
5569 o.get_army().set_ai_activity(
uint8_t(army_activity::attack_gathered));
5573 for(
auto o : ar.get_location_from_army_location().get_army_location()) {
5574 if(o.get_army().get_ai_province() == ar.get_ai_province()
5575 && o.get_army().get_path().size() == 0) {
5577 require_transport.push_back(o.get_army().id);
5578 ar.set_ai_activity(
uint8_t(army_activity::attack_transport));
5583 ar.set_ai_activity(
uint8_t(army_activity::on_guard));
5584 ar.set_ai_province(dcon::province_id{});
5590 for(
uint32_t i = 0; i < require_transport.size(); ++i) {
5591 auto coastal_target_prov = state.world.army_get_location_from_army_location(require_transport[i]);
5592 auto controller = state.world.army_get_controller_from_army_control(require_transport[i]);
5596 auto regs = state.world.army_get_army_membership(require_transport[i]);
5599 tcap -= int32_t(regs.end() - regs.begin());
5601 if(tcap < 0 || (state.world.nation_get_is_at_war(controller) && !
naval_advantage(state, controller))) {
5603 if(state.world.army_get_controller_from_army_control(require_transport[j]) == controller) {
5604 state.world.army_set_ai_activity(require_transport[j],
uint8_t(army_activity::on_guard));
5605 state.world.army_set_ai_province(require_transport[j], dcon::province_id{});
5606 require_transport[j] = require_transport.back();
5607 require_transport.pop_back();
5610 state.world.army_set_ai_activity(require_transport[i],
uint8_t(army_activity::on_guard));
5611 state.world.army_set_ai_province(require_transport[i], dcon::province_id{});
5615 if(!state.world.province_get_is_coast(coastal_target_prov)) {
5618 state.world.army_set_ai_activity(require_transport[i],
uint8_t(army_activity::on_guard));
5619 state.world.army_set_ai_province(require_transport[i], dcon::province_id{});
5622 coastal_target_prov = path.front();
5624 auto existing_path = state.world.army_get_path(require_transport[i]);
5625 auto new_size =
uint32_t(path.size());
5626 existing_path.resize(new_size);
5628 for(
uint32_t k = 0; k < new_size; ++k) {
5630 existing_path[k] = path[k];
5632 state.world.army_set_arrival_time(require_transport[i],
military::arrival_time_to(state, require_transport[i], path.back()));
5633 state.world.army_set_dig_in(require_transport[i], 0);
5639 if(fleet_destination == state.world.navy_get_location_from_navy_location(transport_fleet)) {
5640 state.world.navy_get_path(transport_fleet).clear();
5641 state.world.navy_set_arrival_time(transport_fleet,
sys::date{});
5642 state.world.navy_set_ai_activity(transport_fleet,
uint8_t(fleet_activity::boarding));
5643 }
else if(
auto fleet_path =
province::make_naval_path(state, state.world.navy_get_location_from_navy_location(transport_fleet), fleet_destination); fleet_path.empty()) {
5646 auto existing_path = state.world.navy_get_path(transport_fleet);
5647 auto new_size =
uint32_t(fleet_path.size());
5648 existing_path.resize(new_size);
5650 for(
uint32_t k = 0; k < new_size; ++k) {
5652 existing_path[k] = fleet_path[k];
5654 state.world.navy_set_arrival_time(transport_fleet,
military::arrival_time_to(state, transport_fleet, fleet_path.back()));
5655 state.world.navy_set_ai_activity(transport_fleet,
uint8_t(fleet_activity::boarding));
5659 state.world.army_set_ai_activity(require_transport[i],
uint8_t(army_activity::transport_attack));
5661 auto destination_region = state.world.province_get_connected_region_id(state.world.army_get_ai_province(require_transport[i]));
5665 if(state.world.army_get_controller_from_army_control(require_transport[j]) == controller) {
5666 auto jregs = state.world.army_get_army_membership(require_transport[j]);
5667 if(tcap >= (jregs.end() - jregs.begin())) {
5668 if(state.world.province_get_connected_region_id(state.world.army_get_ai_province(require_transport[j])) != destination_region)
5671 if(state.world.army_get_location_from_army_location(require_transport[j]) == coastal_target_prov) {
5672 state.world.army_set_ai_activity(require_transport[i],
uint8_t(army_activity::transport_attack));
5673 tcap -= int32_t(jregs.end() - jregs.begin());
5675 auto jpath = state.world.army_get_black_flag(require_transport[j])
5676 ?
province::make_land_path(state, state.world.army_get_location_from_army_location(require_transport[j]), coastal_target_prov, controller, require_transport[j])
5678 if(!jpath.empty()) {
5679 auto existing_path = state.world.army_get_path(require_transport[j]);
5680 auto new_size =
uint32_t(jpath.size());
5681 existing_path.resize(new_size);
5683 for(
uint32_t k = 0; k < new_size; ++k) {
5685 existing_path[k] = jpath[k];
5687 state.world.army_set_arrival_time(require_transport[j],
military::arrival_time_to(state, require_transport[j], jpath.back()));
5688 state.world.army_set_dig_in(require_transport[j], 0);
5689 state.world.army_set_ai_activity(require_transport[i],
uint8_t(army_activity::transport_attack));
5690 tcap -= int32_t(jregs.end() - jregs.begin());
5695 require_transport[j] = require_transport.back();
5696 require_transport.pop_back();
5705 auto total = fid.get_active_regiments();
5708 for(
auto ar : state.world.nation_get_army_control(n)) {
5709 for(
auto r : ar.get_army().get_army_membership()) {
5710 if(r.get_regiment().get_strength() < 0.8f) {
5713 if(unfull > total * 0.1) {
5724 for(
auto n : state.world.in_nation) {
5725 if(n.get_is_player_controlled() || n.get_owned_province_count() == 0)
5727 auto disarm = n.get_disarmed_until();
5728 if(disarm && state.current_date < disarm)
5731 static std::vector<dcon::province_land_construction_id> hopeless_construction;
5732 hopeless_construction.clear();
5734 state.world.nation_for_each_province_land_construction(n, [&](dcon::province_land_construction_id plcid) {
5736 auto prov = fat_plc.get_pop().get_province_from_pop_location();
5737 if(prov.get_nation_from_province_control() != n)
5738 hopeless_construction.push_back(plcid);
5741 for(
auto item : hopeless_construction) {
5742 state.world.delete_province_land_construction(item);
5745 auto constructions = state.world.nation_get_province_land_construction(n);
5746 if(constructions.begin() != constructions.end())
5749 int32_t num_frontline = 0;
5750 int32_t num_support = 0;
5757 art_def = state.military_definitions.unit_base_definitions[art_type];
5761 for(
auto ar : state.world.nation_get_army_control(n)) {
5762 for(
auto r : ar.get_army().get_army_membership()) {
5763 auto type = r.get_regiment().get_type();
5764 auto etype = state.military_definitions.unit_base_definitions[type].type;
5775 auto primary_culture = r.get_regiment().get_pop_from_regiment_source().get_culture() == n.get_primary_culture();
5778 if(primary_culture) {
5784 r.get_regiment().set_type(pc_adj_inf_type);
5785 r.get_regiment().set_strength(0.01f);
5787 r.get_regiment().set_type(pc_adj_art_type);
5788 r.get_regiment().set_strength(0.01f);
5790 r.get_regiment().set_type(pc_adj_cav_type);
5791 r.get_regiment().set_strength(0.01f);
5797 r.get_regiment().set_type(inf_type);
5798 r.get_regiment().set_strength(0.01f);
5800 r.get_regiment().set_type(art_type);
5801 r.get_regiment().set_strength(0.01f);
5803 r.get_regiment().set_type(cav_type);
5804 r.get_regiment().set_strength(0.01f);
5811 const auto decide_type = [&](
bool pc) {
5812 if(art_type && (!art_req_pc || (art_req_pc && pc))) {
5813 if(num_frontline > num_support) {
5827 for(
auto p : state.world.nation_get_province_ownership(n)) {
5828 if(p.get_province().get_nation_from_province_control() != n)
5831 if(p.get_province().get_is_colonial()) {
5832 float divisor = state.defines.pop_size_per_regiment * state.defines.pop_min_size_for_regiment_colony_multiplier;
5833 float minimum = state.defines.pop_min_size_for_regiment;
5835 for(
auto pop : p.get_province().get_pop_location()) {
5836 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
5837 if(pop.get_pop().get_size() >= minimum) {
5838 auto amount = int32_t((pop.get_pop().get_size() / divisor) + 1);
5839 auto regs = pop.get_pop().get_regiment_source();
5840 auto building = pop.get_pop().get_province_land_construction();
5841 auto num_to_make_local = amount - ((regs.end() - regs.begin()) + (building.end() - building.begin()));
5842 while(num_to_make_local > 0 && num_to_build_nation > 0) {
5843 auto t = decide_type(pop.get_pop().get_is_primary_or_accepted_culture());
5845 auto c = fatten(state.world, state.world.try_create_province_land_construction(pop.get_pop().id, n));
5847 --num_to_make_local;
5848 --num_to_build_nation;
5853 }
else if(!p.get_province().get_is_owner_core()) {
5854 float divisor = state.defines.pop_size_per_regiment * state.defines.pop_min_size_for_regiment_noncore_multiplier;
5855 float minimum = state.defines.pop_min_size_for_regiment;
5857 dcon::pop_id non_preferred;
5858 for(
auto pop : p.get_province().get_pop_location()) {
5859 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
5860 if(pop.get_pop().get_size() >= minimum) {
5861 auto amount = int32_t((pop.get_pop().get_size() / divisor) + 1);
5862 auto regs = pop.get_pop().get_regiment_source();
5863 auto building = pop.get_pop().get_province_land_construction();
5864 auto num_to_make_local = amount - ((regs.end() - regs.begin()) + (building.end() - building.begin()));
5865 while(num_to_make_local > 0 && num_to_build_nation > 0) {
5866 auto t = decide_type(pop.get_pop().get_is_primary_or_accepted_culture());
5868 auto c = fatten(state.world, state.world.try_create_province_land_construction(pop.get_pop().id, n));
5870 --num_to_make_local;
5871 --num_to_build_nation;
5877 float divisor = state.defines.pop_size_per_regiment;
5878 float minimum = state.defines.pop_min_size_for_regiment;
5880 dcon::pop_id non_preferred;
5881 for(
auto pop : p.get_province().get_pop_location()) {
5882 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
5883 if(pop.get_pop().get_size() >= minimum) {
5884 auto amount = int32_t((pop.get_pop().get_size() / divisor) + 1);
5885 auto regs = pop.get_pop().get_regiment_source();
5886 auto building = pop.get_pop().get_province_land_construction();
5887 auto num_to_make_local = amount - ((regs.end() - regs.begin()) + (building.end() - building.begin()));
5888 while(num_to_make_local > 0 && num_to_build_nation) {
5889 auto t = decide_type(pop.get_pop().get_is_primary_or_accepted_culture());
5891 auto c = fatten(state.world, state.world.try_create_province_land_construction(pop.get_pop().id, n));
5893 --num_to_make_local;
5894 --num_to_build_nation;
5905 for(
auto ar : state.world.in_army) {
5906 auto controller = ar.get_controller_from_army_control();
5909 && !ar.get_battle_from_army_battle_participation()
5910 && !ar.get_navy_from_army_transport()
5911 && !ar.get_arrival_time()) {
5913 auto location = ar.get_location_from_army_location();
5915 if(ar.get_black_flag() ||
army_activity(ar.get_ai_activity()) == army_activity::unspecified) {
5916 auto regs = ar.get_army_membership();
5917 if(regs.begin() == regs.end()) {
5919 }
else if(regs.end() - regs.begin() > 1) {
5921 ar.set_ai_activity(
uint8_t(army_activity::on_guard));
5923 auto type = (*regs.begin()).get_regiment().get_type();
5924 auto etype = state.military_definitions.unit_base_definitions[type].type;
5926 dcon::province_id target_location;
5927 float nearest_distance = 1.0f;
5930 for(
auto o : controller.get_army_control()) {
5931 auto other_location = o.get_army().get_location_from_army_location();
5933 if(
army_activity(o.get_army().get_ai_activity()) == army_activity::on_guard
5934 && other_location.get_connected_region_id() == location.get_connected_region_id()
5935 && (!target_location || sdist < nearest_distance)) {
5937 int32_t num_support = 0;
5938 int32_t num_frontline = 0;
5939 for(
auto r : o.get_army().get_army_membership()) {
5940 auto stype = r.get_regiment().get_type();
5941 auto setype = state.military_definitions.unit_base_definitions[stype].type;
5949 if((is_art && num_support < 5) || (!is_art && num_frontline < 5)) {
5950 target_location = other_location;
5951 nearest_distance = sdist;
5956 if(target_location) {
5957 if(target_location == location) {
5958 ar.set_ai_province(target_location);
5959 ar.set_ai_activity(
uint8_t(army_activity::merging));
5960 }
else if(
auto path =
province::make_land_path(state, location, target_location, controller, ar); path.size() > 0) {
5961 auto existing_path = ar.get_path();
5962 auto new_size =
uint32_t(path.size());
5963 existing_path.resize(new_size);
5965 for(
uint32_t i = 0; i < new_size; ++i) {
5967 existing_path[i] = path[i];
5971 ar.set_ai_province(target_location);
5972 ar.set_ai_activity(
uint8_t(army_activity::merging));
5974 ar.set_ai_activity(
uint8_t(army_activity::on_guard));
5977 ar.set_ai_activity(
uint8_t(army_activity::on_guard));
5980 }
else if(
army_activity(ar.get_ai_activity()) == army_activity::merging) {
5981 auto regs = ar.get_army_membership();
5982 if(regs.begin() == regs.end()) {
5986 auto type = (*regs.begin()).get_regiment().get_type();
5987 auto etype = state.military_definitions.unit_base_definitions[type].type;
5989 for(
auto o : location.get_army_location()) {
5990 if(o.get_army().get_ai_activity() ==
uint8_t(army_activity::on_guard)
5991 && o.get_army().get_controller_from_army_control() == controller) {
5993 int32_t num_support = 0;
5994 int32_t num_frontline = 0;
5995 for(
auto r : o.get_army().get_army_membership()) {
5996 auto stype = r.get_regiment().get_type();
5997 auto setype = state.military_definitions.unit_base_definitions[stype].type;
6005 if((is_art && num_support < 5) || (!is_art && num_frontline < 5)) {
6006 (*regs.begin()).get_regiment().set_army_from_army_membership(o.get_army());
6011 ar.set_ai_activity(
uint8_t(army_activity::unspecified));
6019 auto v = state.current_date.value;
6051 for(
auto nation : state.world.in_nation) {
6052 if(state.world.nation_get_is_player_controlled(nation)) {
6056 if(nation.get_is_great_power()) {
6057 nation.set_ai_strategy(ai_strategies::militant);
6060 nation.set_ai_strategy(ai_strategies::industrious);
6068 for(
auto ar : state.world.province_get_army_location(p))
6069 if(ar.get_army().get_controller_from_army_rebel_control())
#define assert(condition)
void update_crisis_leaders(sys::state &state)
void get_craved_factory_types(sys::state &state, dcon::nation_id nid, dcon::market_id mid, std::vector< dcon::factory_type_id > &desired_types)
void initialize_ai_tech_weights(sys::state &state)
void place_instance_in_result_war(sys::state &state, std::vector< possible_cb > &result, dcon::nation_id n, dcon::nation_id target, dcon::war_id w, dcon::cb_type_id cb, std::vector< dcon::state_instance_id > const &target_states)
void daily_cleanup(sys::state &state)
bool naval_supremacy(sys::state &state, dcon::nation_id n, dcon::nation_id target)
void take_reforms(sys::state &state)
void form_alliances(sys::state &state)
float estimate_balanced_composition_factor(sys::state &state, dcon::army_id a)
void sort_available_declaration_cbs(std::vector< possible_cb > &result, sys::state &state, dcon::nation_id n, dcon::nation_id target)
void update_ai_ruling_party(sys::state &state)
void make_war_decs(sys::state &state)
void upgrade_colonies(sys::state &state)
void add_free_ai_cbs_to_war(sys::state &state, dcon::nation_id n, dcon::war_id w)
void update_cb_fabrication(sys::state &state)
bool ai_will_accept_alliance(sys::state &state, dcon::nation_id target, dcon::nation_id from)
bool will_accept_peace_offer(sys::state &state, dcon::nation_id n, dcon::nation_id from, dcon::peace_offer_id p)
void pickup_idle_ships(sys::state &state)
void state_target_list(std::vector< dcon::state_instance_id > &result, sys::state &state, dcon::nation_id for_nation, dcon::nation_id within)
void make_defense(sys::state &state)
void assign_targets(sys::state &state, dcon::nation_id n)
float estimate_army_offensive_strength(sys::state &state, dcon::army_id a)
bool ai_will_grant_access(sys::state &state, dcon::nation_id target, dcon::nation_id from)
float estimate_army_defensive_strength(sys::state &state, dcon::army_id a)
void refresh_home_ports(sys::state &state)
void send_fleet_home(sys::state &state, dcon::navy_id n, fleet_activity moving_status=fleet_activity::returning_to_base, fleet_activity at_base=fleet_activity::idle)
bool ai_is_close_enough(sys::state &state, dcon::nation_id target, dcon::nation_id from)
bool set_fleet_target(sys::state &state, dcon::nation_id n, dcon::province_id start, dcon::navy_id for_navy)
void remove_ai_data(sys::state &state, dcon::nation_id n)
void sort_possible_justification_cbs(std::vector< possible_cb > &result, sys::state &state, dcon::nation_id n, dcon::nation_id target)
bool valid_construction_target(sys::state &state, dcon::nation_id from, dcon::nation_id target)
void distribute_guards(sys::state &state, dcon::nation_id n)
bool will_be_crisis_primary_attacker(sys::state &state, dcon::nation_id n)
possible_cb pick_fabrication_type(sys::state &state, dcon::nation_id from, dcon::nation_id target)
float estimate_enemy_defensive_force(sys::state &state, dcon::province_id target, dcon::nation_id by)
bool will_join_crisis_with_offer(sys::state &state, dcon::nation_id n, sys::full_wg offer)
void update_ai_colony_starting(sys::state &state)
bool ai_offer_cb(sys::state &state, dcon::cb_type_id t)
void gather_to_battle(sys::state &state, dcon::nation_id n, dcon::province_id p)
crisis_str estimate_crisis_str(sys::state &state)
void update_naval_transport(sys::state &state)
void update_focuses(sys::state &state)
void get_desired_factory_types(sys::state &state, dcon::nation_id nid, dcon::market_id mid, std::vector< dcon::factory_type_id > &desired_types)
int32_t future_rebels_in_nation(sys::state &state, dcon::nation_id n)
dcon::province_id get_home_port(sys::state &state, dcon::nation_id n)
void add_wg_to_great_war(sys::state &state, dcon::nation_id n, dcon::war_id w)
constexpr float ally_overestimate
float estimate_strength(sys::state &state, dcon::nation_id n)
void place_instance_in_result(sys::state &state, std::vector< possible_cb > &result, dcon::nation_id n, dcon::nation_id target, dcon::cb_type_id cb, std::vector< dcon::state_instance_id > const &target_states)
void update_budget(sys::state &state)
bool ai_can_appoint_political_party(sys::state &state, dcon::nation_id n)
void new_units_and_merging(sys::state &state)
void move_gathered_attackers(sys::state &state)
float estimate_rebel_strength(sys::state &state, dcon::province_id p)
void update_ai_colonial_investment(sys::state &state)
dcon::cb_type_id pick_gw_extra_cb_type(sys::state &state, dcon::nation_id from, dcon::nation_id target)
void perform_influence_actions(sys::state &state)
void make_attacks(sys::state &state)
void update_ships(sys::state &state)
void update_ai_econ_construction(sys::state &state)
bool will_join_war(sys::state &state, dcon::nation_id n, dcon::war_id w, bool as_attacker)
void build_ships(sys::state &state)
void prune_alliances(sys::state &state)
float estimate_pop_party_support(sys::state &state, dcon::nation_id n, dcon::political_party_id pid)
void update_war_intervention(sys::state &state)
dcon::navy_id find_transport_fleet(sys::state &state, dcon::nation_id controller)
void get_state_desired_factory_types(sys::state &state, dcon::nation_id nid, dcon::market_id mid, std::vector< dcon::factory_type_id > &desired_types)
float estimate_defensive_strength(sys::state &state, dcon::nation_id n)
void unload_units_from_transport(sys::state &state, dcon::navy_id n)
bool unit_on_ai_control(sys::state &state, dcon::army_id a)
void explain_ai_access_reasons(sys::state &state, dcon::nation_id target, text::layout_base &contents, int32_t indent)
void explain_ai_alliance_reasons(sys::state &state, dcon::nation_id target, text::layout_base &contents, int32_t indent)
void update_influence_priorities(sys::state &state)
void update_ai_research(sys::state &state)
bool navy_needs_repair(sys::state &state, dcon::navy_id n)
void update_ai_general_status(sys::state &state)
void update_factory_types_priority(sys::state &state)
void update_land_constructions(sys::state &state)
int16_t calculate_desired_army_size(sys::state &state, dcon::nation_id nation)
bool will_be_crisis_primary_defender(sys::state &state, dcon::nation_id n)
void sort_available_cbs(std::vector< possible_cb > &result, sys::state &state, dcon::nation_id n, dcon::war_id w)
void identify_focuses(sys::state &state)
void civilize(sys::state &state)
void make_peace_offers(sys::state &state)
bool will_accept_crisis_peace_offer(sys::state &state, dcon::nation_id to, bool is_concession, bool missing_wg)
bool naval_advantage(sys::state &state, dcon::nation_id n)
bool army_ready_for_battle(sys::state &state, dcon::nation_id n, dcon::army_id a)
void take_ai_decisions(sys::state &state)
bool will_upgrade_units(sys::state &state, dcon::nation_id n)
void general_ai_unit_tick(sys::state &state)
float estimate_additional_offensive_strength(sys::state &state, dcon::nation_id n, dcon::nation_id target)
bool has_cores_occupied(sys::state &state, dcon::nation_id n)
bool will_accept_peace_offer_value(sys::state &state, dcon::nation_id n, dcon::nation_id from, dcon::nation_id prime_attacker, dcon::nation_id prime_defender, float primary_warscore, float scoreagainst_me, bool offer_from_attacker, bool concession, int32_t overall_po_value, int32_t my_po_target, int32_t target_personal_po_value, int32_t potential_peace_score_against, int32_t my_side_against_target, int32_t my_side_peace_cost, int32_t war_duration, bool contains_sq)
void move_idle_guards(sys::state &state)
void add_gw_goals(sys::state &state)
dcon::nation_id pick_gw_target(sys::state &state, dcon::nation_id from, dcon::war_id w, bool is_attacker)
bool merge_fleet(sys::state &state, dcon::navy_id n, dcon::province_id p, dcon::nation_id owner)
void get_state_craved_factory_types(sys::state &state, dcon::nation_id nid, dcon::market_id mid, std::vector< dcon::factory_type_id > &desired_types)
bool can_increase_opinion(sys::state &state, dcon::nation_id source, dcon::nation_id influence_target)
void execute_send_peace_offer(sys::state &state, dcon::nation_id source)
bool can_send_crisis_peace_offer(sys::state &state, dcon::nation_id source)
bool can_add_to_sphere(sys::state &state, dcon::nation_id source, dcon::nation_id influence_target)
void execute_start_crisis_peace_offer(sys::state &state, dcon::nation_id source, bool is_concession)
bool can_intervene_in_war(sys::state &state, dcon::nation_id source, dcon::war_id w, bool for_attacker)
void execute_declare_war(sys::state &state, dcon::nation_id source, dcon::nation_id target, dcon::cb_type_id primary_cb, dcon::state_definition_id cb_state, dcon::national_identity_id cb_tag, dcon::nation_id cb_secondary_nation, bool call_attacker_allies, bool run_conference)
bool can_start_crisis_peace_offer(sys::state &state, dcon::nation_id source, bool is_concession)
void execute_add_to_sphere(sys::state &state, dcon::nation_id source, dcon::nation_id influence_target)
void execute_intervene_in_war(sys::state &state, dcon::nation_id source, dcon::war_id w, bool for_attacker)
bool can_set_national_focus(sys::state &state, dcon::nation_id source, dcon::state_instance_id target_state, dcon::national_focus_id focus)
void execute_start_peace_offer(sys::state &state, dcon::nation_id source, dcon::nation_id target, dcon::war_id war, bool is_concession)
bool can_start_peace_offer(sys::state &state, dcon::nation_id source, dcon::nation_id target, dcon::war_id war, bool is_concession)
bool can_start_land_unit_construction(sys::state &state, dcon::nation_id source, dcon::province_id location, dcon::culture_id soldier_culture, dcon::unit_type_id type, dcon::province_id template_province)
void execute_remove_from_sphere(sys::state &state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp)
void execute_send_crisis_peace_offer(sys::state &state, dcon::nation_id source)
void execute_increase_opinion(sys::state &state, dcon::nation_id source, dcon::nation_id influence_target)
bool can_send_peace_offer(sys::state &state, dcon::nation_id source)
bool can_add_to_crisis_peace_offer(sys::state &state, dcon::nation_id source, dcon::nation_id wargoal_from, dcon::nation_id target, dcon::cb_type_id primary_cb, dcon::state_definition_id cb_state, dcon::national_identity_id cb_tag, dcon::nation_id cb_secondary_nation)
bool can_remove_from_sphere(sys::state &state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp)
void execute_cancel_alliance(sys::state &state, dcon::nation_id source, dcon::nation_id target)
bool can_cancel_alliance(sys::state &state, dcon::nation_id source, dcon::nation_id target, bool ignore_cost)
bool can_declare_war(sys::state &state, dcon::nation_id source, dcon::nation_id target, dcon::cb_type_id primary_cb, dcon::state_definition_id cb_state, dcon::national_identity_id cb_tag, dcon::nation_id cb_secondary_nation)
bool can_enact_issue(sys::state &state, dcon::nation_id source, dcon::issue_option_id i)
bool can_start_naval_unit_construction(sys::state &state, dcon::nation_id source, dcon::province_id location, dcon::unit_type_id type, dcon::province_id template_province)
float effective_technology_cost(sys::state &state, uint32_t current_year, dcon::nation_id target_nation, dcon::technology_id tech_id)
constexpr uint64_t to_bits(dcon::ideology_id id)
pop_satisfaction_wrapper_fat fatten(data_container const &c, pop_satisfaction_wrapper_id id) noexcept
constexpr dcon::demographics_key rich_militancy(10)
constexpr dcon::demographics_key middle_total(21)
constexpr dcon::demographics_key total(0)
constexpr dcon::demographics_key poor_militancy(8)
constexpr dcon::demographics_key middle_militancy(9)
dcon::demographics_key to_key(sys::state const &state, dcon::pop_type_id v)
constexpr dcon::demographics_key rich_total(22)
constexpr dcon::demographics_key poor_total(20)
dcon::demographics_key to_employment_key(sys::state const &state, dcon::pop_type_id v)
void post(sys::state &state, message const &m)
Pushes a diplomatic message to the list of pending diplomatic requests for the specified recipient (m...
float factory_type_output_cost(sys::state &state, dcon::nation_id n, dcon::market_id m, dcon::factory_type_id factory_type)
float estimate_construction_spending_from_budget(sys::state &state, dcon::nation_id n, float current_budget)
int32_t state_factory_count(sys::state &state, dcon::state_instance_id sid, dcon::nation_id n)
float supply(sys::state &state, dcon::market_id s, dcon::commodity_id c)
float estimate_pop_payouts_by_income_type(sys::state &state, dcon::nation_id n, culture::income_type in)
float estimate_domestic_investment(sys::state &state, dcon::nation_id n)
float estimate_overseas_penalty_spending(sys::state &state, dcon::nation_id n)
float estimate_land_spending(sys::state &state, dcon::nation_id n)
float estimate_daily_income(sys::state &state, dcon::nation_id n)
float price(sys::state const &state, dcon::state_instance_id s, dcon::commodity_id c)
constexpr dcon::commodity_id money(0)
float factory_type_build_cost(sys::state &state, dcon::nation_id n, dcon::market_id m, dcon::factory_type_id factory_type)
float demand_satisfaction(sys::state &state, dcon::market_id s, dcon::commodity_id c)
float estimate_naval_spending(sys::state &state, dcon::nation_id n)
void bound_budget_settings(sys::state &state, dcon::nation_id n)
float demand(sys::state &state, dcon::market_id s, dcon::commodity_id c)
float factory_type_input_cost(sys::state &state, dcon::nation_id n, dcon::market_id m, dcon::factory_type_id factory_type)
void execute(sys::state &state, dcon::effect_key key, int32_t primary, int32_t this_slot, int32_t from_slot, uint32_t r_lo, uint32_t r_hi)
constexpr uint32_t pop_open_factory_invest
constexpr uint32_t pop_expand_factory_invest
constexpr uint32_t pop_open_factory
constexpr uint32_t build_railway
constexpr uint32_t pop_build_factory_invest
constexpr uint32_t build_factory
constexpr uint32_t pop_expand_factory
constexpr uint32_t build_bank
constexpr uint32_t build_university
constexpr uint32_t pop_build_factory
constexpr uint32_t expand_factory
float sin(float x) noexcept
float sqrt(float x) noexcept
constexpr uint32_t po_transfer_provinces
constexpr uint32_t po_demand_state
constexpr uint32_t all_allowed_states
constexpr uint32_t po_annex
constexpr uint32_t po_status_quo
constexpr uint32_t is_not_constructing_cb
constexpr uint32_t always
bool province_is_under_siege(sys::state const &state, dcon::province_id ids)
bool are_allied_in_war(sys::state const &state, dcon::nation_id a, dcon::nation_id b)
bool cb_conditions_satisfied(sys::state &state, dcon::nation_id actor, dcon::nation_id target, dcon::cb_type_id cb)
float primary_warscore(sys::state &state, dcon::war_id w)
bool is_artillery_better(sys::state &state, dcon::nation_id n, dcon::unit_type_id best, dcon::unit_type_id given)
float directed_warscore(sys::state &state, dcon::war_id w, dcon::nation_id primary, dcon::nation_id secondary)
bool rebel_army_in_province(sys::state &state, dcon::province_id p)
int32_t defender_peace_cost(sys::state &state, dcon::war_id war)
bool can_use_cb_against(sys::state &state, dcon::nation_id from, dcon::nation_id target)
dcon::unit_type_id get_best_artillery(sys::state &state, dcon::nation_id n, bool primary_culture)
bool is_cavalry_better(sys::state &state, dcon::nation_id n, dcon::unit_type_id best, dcon::unit_type_id given)
bool has_truce_with(sys::state &state, dcon::nation_id attacker, dcon::nation_id target)
war_role get_role(sys::state const &state, dcon::war_id w, dcon::nation_id n)
int32_t attacker_peace_cost(sys::state &state, dcon::war_id war)
bool is_attacker(sys::state &state, dcon::war_id w, dcon::nation_id n)
bool is_infantry_better(sys::state &state, dcon::nation_id n, dcon::unit_type_id best, dcon::unit_type_id given)
dcon::unit_type_id get_best_cavalry(sys::state &state, dcon::nation_id n, bool primary_culture)
void add_wargoal(sys::state &state, dcon::war_id wfor, dcon::nation_id added_by, dcon::nation_id target, dcon::cb_type_id type, dcon::state_definition_id sd, dcon::national_identity_id tag, dcon::nation_id secondary_nation)
bool cb_requires_selection_of_a_valid_nation(sys::state const &state, dcon::cb_type_id t)
dcon::unit_type_id get_best_infantry(sys::state &state, dcon::nation_id n, bool primary_culture)
sys::date arrival_time_to(sys::state &state, dcon::army_id a, dcon::province_id p)
bool cb_instance_conditions_satisfied(sys::state &state, dcon::nation_id actor, dcon::nation_id target, dcon::cb_type_id cb, dcon::state_definition_id st, dcon::national_identity_id tag, dcon::nation_id secondary)
float cb_infamy(sys::state &state, dcon::cb_type_id t, dcon::nation_id target, dcon::state_definition_id cb_state)
bool are_at_war(sys::state const &state, dcon::nation_id a, dcon::nation_id b)
bool attackers_have_status_quo_wargoal(sys::state const &state, dcon::war_id w)
int32_t transport_capacity(sys::state &state, dcon::navy_id n)
float relative_attrition_amount(sys::state &state, dcon::navy_id a, dcon::province_id prov)
bool cb_requires_selection_of_a_liberatable_tag(sys::state const &state, dcon::cb_type_id t)
float peacetime_attrition_limit(sys::state &state, dcon::nation_id n, dcon::province_id prov)
int32_t peace_cost(sys::state &state, dcon::war_id war, dcon::cb_type_id wargoal, dcon::nation_id from, dcon::nation_id target, dcon::nation_id secondary_nation, dcon::state_definition_id wargoal_state, dcon::national_identity_id wargoal_tag)
bool defenders_have_status_quo_wargoal(sys::state const &state, dcon::war_id w)
bool war_goal_would_be_duplicate(sys::state &state, dcon::nation_id source, dcon::war_id w, dcon::nation_id target, dcon::cb_type_id cb_type, dcon::state_definition_id cb_state, dcon::national_identity_id cb_tag, dcon::nation_id cb_secondary_nation)
bool cb_requires_selection_of_a_state(sys::state const &state, dcon::cb_type_id t)
constexpr uint8_t is_banned
constexpr uint8_t level_friendly
constexpr uint8_t priority_three
constexpr uint8_t priority_one
constexpr uint8_t level_in_sphere
constexpr uint8_t level_mask
constexpr uint8_t priority_two
bool is_great_power(sys::state const &state, dcon::nation_id id)
void enact_reform(sys::state &state, dcon::nation_id source, dcon::reform_option_id r)
int32_t free_colonial_points(sys::state &state, dcon::nation_id n)
bool are_allied(sys::state &state, dcon::nation_id a, dcon::nation_id b)
void make_alliance(sys::state &state, dcon::nation_id a, dcon::nation_id b)
void enact_issue(sys::state &state, dcon::nation_id source, dcon::issue_option_id i)
bool is_landlocked(sys::state &state, dcon::nation_id n)
void make_civilized(sys::state &state, dcon::nation_id n)
void adjust_relationship(sys::state &state, dcon::nation_id a, dcon::nation_id b, float delta)
int32_t max_national_focuses(sys::state &state, dcon::nation_id n)
void post(sys::state &state, message &&m)
float get_military_reform_multiplier(sys::state &state, dcon::nation_id n)
float get_economic_reform_multiplier(sys::state &state, dcon::nation_id n)
bool can_appoint_ruling_party(sys::state &state, dcon::nation_id nation)
bool political_party_is_active(sys::state &state, dcon::nation_id n, dcon::political_party_id p)
bool has_elections(sys::state &state, dcon::nation_id nation)
void appoint_ruling_party(sys::state &state, dcon::nation_id n, dcon::political_party_id p)
bool is_election_ongoing(sys::state &state, dcon::nation_id nation)
std::vector< dcon::province_id > make_land_path(sys::state &state, dcon::province_id start, dcon::province_id end, dcon::nation_id nation_as, dcon::army_id a)
float sorting_distance(sys::state &state, dcon::province_id a, dcon::province_id b)
void upgrade_colonial_state(sys::state &state, dcon::nation_id source, dcon::state_instance_id si)
std::vector< dcon::province_id > make_safe_land_path(sys::state &state, dcon::province_id start, dcon::province_id end, dcon::nation_id nation_as)
bool has_access_to_province(sys::state &state, dcon::nation_id nation_as, dcon::province_id prov)
bool has_naval_base_being_built(sys::state &state, dcon::province_id id)
bool is_overseas(sys::state const &state, dcon::province_id ids)
bool has_safe_access_to_province(sys::state &state, dcon::nation_id nation_as, dcon::province_id prov)
void for_each_province_in_state_instance(sys::state &state, dcon::state_instance_id s, F const &func)
std::vector< dcon::province_id > make_path_to_nearest_coast(sys::state &state, dcon::nation_id nation_as, dcon::province_id start)
bool has_province_building_being_built(sys::state &state, dcon::province_id id, economy::province_building_type t)
bool can_integrate_colony(sys::state &state, dcon::state_instance_id id)
bool fast_can_start_colony(sys::state &state, dcon::nation_id n, dcon::state_definition_id d, int32_t free_points, dcon::province_id coastal_target, bool &adjacent)
bool state_is_coastal(sys::state &state, dcon::state_instance_id s)
void for_each_land_province(sys::state &state, F const &func)
std::vector< dcon::province_id > make_naval_path(sys::state &state, dcon::province_id start, dcon::province_id end)
std::vector< dcon::province_id > make_unowned_land_path(sys::state &state, dcon::province_id start, dcon::province_id end)
bool has_naval_access_to_province(sys::state &state, dcon::nation_id nation_as, dcon::province_id prov)
bool has_fort_being_built(sys::state &state, dcon::province_id id)
std::vector< dcon::province_id > make_unowned_path_to_nearest_coast(sys::state &state, dcon::province_id start)
bool state_borders_nation(sys::state &state, dcon::nation_id n, dcon::state_instance_id si)
void increase_colonial_investment(sys::state &state, dcon::nation_id source, dcon::state_definition_id state_def)
uint32_t reduce(uint32_t value_in, uint32_t upper_bound)
uint64_t get_random(sys::state const &state, uint32_t value_in)
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression, cppcoreguidelines-noexcept-swap, performance-noexcept-swap) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
@ entered_automatic_alliance
void add_line(sys::state &state, layout_base &dest, dcon::text_key txt, int32_t indent)
void add_line_with_condition(sys::state &state, layout_base &dest, std::string_view key, bool condition_met, int32_t indent)
std::string produce_simple_string(sys::state const &state, dcon::text_key id)
int32_t to_generic(dcon::province_id v)
bool evaluate(sys::state &state, dcon::trigger_key key, int32_t primary, int32_t this_slot, int32_t from_slot)
void effect_description(sys::state &state, text::layout_base &layout, dcon::effect_key k, int32_t primary_slot, int32_t this_slot, int32_t from_slot, uint32_t r_lo, uint32_t r_hi)
dcon::state_definition_id state_def
dcon::national_identity_id associated_tag
dcon::nation_id secondary_nation
Holds data regarding a diplomatic message between two specified nations at a certain date,...
static constexpr uint32_t set_size
dcon::nation_id target_nation
static constexpr uint32_t modifier_definition_size
Holds important data about the game world, state, and other data regarding windowing,...