16 float value = state.world.nation_get_military_score(n);
17 for(
auto subj : state.world.nation_get_overlord_as_ruler(n))
18 value += subj.get_subject().get_military_score();
24 for(
auto dr : state.world.nation_get_diplomatic_relation(n)) {
25 if(!dr.get_are_allied())
28 auto other = dr.get_related_nations(0) != n ? dr.get_related_nations(0) : dr.get_related_nations(1);
29 if(other.get_overlord_as_subject().get_ruler() != n)
32 if(
auto sl = state.world.nation_get_in_sphere_of(n); sl)
39 for(
auto dr : state.world.nation_get_diplomatic_relation(n)) {
40 if(!dr.get_are_allied())
43 auto other = dr.get_related_nations(0) != n ? dr.get_related_nations(0) : dr.get_related_nations(1);
47 return value * state.defines.alice_ai_offensive_strength_overestimate;
51 for(
auto n : state.world.in_nation) {
52 if(state.world.nation_get_owned_province_count(n) == 0) {
53 state.world.nation_set_ai_is_threatened(n,
false);
54 state.world.nation_set_ai_rival(n, dcon::nation_id{});
58 auto ll = state.world.nation_get_last_war_loss(n);
59 float safety_factor = 1.2f;
60 if(ll && state.current_date < ll + 365 * 4) {
63 auto in_sphere_of = state.world.nation_get_in_sphere_of(n);
65 float greatest_neighbor = 0.0f;
66 for(
auto b : state.world.nation_get_nation_adjacency_as_connected_nations(n)) {
67 auto other = b.get_connected_nations(0) != n ? b.get_connected_nations(0) : b.get_connected_nations(1);
68 if(!
nations::are_allied(state, n, other) && (!in_sphere_of || in_sphere_of != other.get_in_sphere_of())) {
73 float self_str = float(state.world.nation_get_military_score(n));
74 for(
auto subj : n.get_overlord_as_ruler())
75 self_str += 0.75f * float(subj.get_subject().get_military_score());
78 bool threatened = defensive_str < safety_factor * greatest_neighbor;
79 state.world.nation_set_ai_is_threatened(n, threatened);
81 if(!n.get_ai_rival()) {
83 dcon::nation_id potential;
84 for(
auto adj : n.get_nation_adjacency()) {
85 auto other = adj.get_connected_nations(0) != n ? adj.get_connected_nations(0) : adj.get_connected_nations(1);
86 auto ol = other.get_overlord_as_subject().get_ruler();
87 if(!ol && other.get_in_sphere_of() != n && (!threatened || !
nations::are_allied(state, n, other))) {
89 if(self_str * 0.5f < other_str && other_str <= self_str * 1.5f && min_str > self_str) {
101 n.set_ai_rival(potential);
105 auto ol = n.get_ai_rival().get_overlord_as_subject().get_ruler();
106 if(ol || n.get_ai_rival().get_in_sphere_of() == n || rival_str * 2 < self_str || self_str * 2 < rival_str) {
107 n.set_ai_rival(dcon::nation_id{});
113static 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) {
114 for(
auto nb : state.world.nation_get_nation_adjacency(adj)) {
115 auto other = nb.get_connected_nations(0) != adj ? nb.get_connected_nations(0) : nb.get_connected_nations(1);
117 bool b = other.get_is_player_controlled()
118 ? state.world.unilateral_relationship_get_interested_in_alliance(state.world.get_unilateral_relationship_by_unilateral_pair(n, other))
121 alliance_targets.push_back(other.id);
125static void internal_get_alliance_targets(
sys::state& state, dcon::nation_id n, std::vector<dcon::nation_id>& alliance_targets) {
127 internal_get_alliance_targets_by_adjacency(state, n, n, alliance_targets);
128 if(!alliance_targets.empty())
132 if(
auto rival =
state.world.nation_get_ai_rival(n);
bool(rival)) {
133 internal_get_alliance_targets_by_adjacency(state, n, rival, alliance_targets);
134 if(!alliance_targets.empty())
139 for(
auto wp :
state.world.nation_get_war_participant(n)) {
140 for(
auto p :
state.world.war_get_war_participant(wp.get_war())) {
141 if(p.get_is_attacker() == !wp.get_is_attacker()) {
142 internal_get_alliance_targets_by_adjacency(state, n, p.get_nation(), alliance_targets);
143 if(!alliance_targets.empty())
151 static std::vector<dcon::nation_id> alliance_targets;
152 for(
auto n : state.world.in_nation) {
153 if(!n.get_is_player_controlled() && n.get_ai_is_threatened() && !(n.get_overlord_as_subject().get_ruler())) {
154 alliance_targets.clear();
155 internal_get_alliance_targets(state, n, alliance_targets);
156 if(!alliance_targets.empty()) {
157 std::sort(alliance_targets.begin(), alliance_targets.end(), [&](dcon::nation_id a, dcon::nation_id b) {
158 if(estimate_strength(state, a) != estimate_strength(state, b))
159 return estimate_strength(state, a) > estimate_strength(state, b);
161 return a.index() > b.index();
163 if(state.world.nation_get_is_player_controlled(alliance_targets[0])) {
168 "msg_entered_automatic_alliance_title",
169 n, dcon::nation_id{}, dcon::nation_id{},
180 static std::vector<dcon::nation_id> prune_targets;
181 for(
auto n : state.world.in_nation) {
182 if(!n.get_is_player_controlled()
183 && !n.get_ai_is_threatened()
184 && !(n.get_overlord_as_subject().get_ruler())) {
185 prune_targets.clear();
186 for(
auto dr : n.get_diplomatic_relation()) {
187 if(dr.get_are_allied()) {
188 auto other = dr.get_related_nations(0) != n ? dr.get_related_nations(0) : dr.get_related_nations(1);
189 if(other.get_in_sphere_of() != n
191 prune_targets.push_back(other);
196 if(prune_targets.empty())
199 std::sort(prune_targets.begin(), prune_targets.end(), [&](dcon::nation_id a, dcon::nation_id b) {
200 if(estimate_strength(state, a) != estimate_strength(state, b))
201 return estimate_strength(state, a) < estimate_strength(state, b);
203 return a.index() > b.index();
206 float greatest_neighbor = 0.0f;
207 auto in_sphere_of = state.world.nation_get_in_sphere_of(n);
209 for(
auto b : state.world.nation_get_nation_adjacency_as_connected_nations(n)) {
210 auto other = b.get_connected_nations(0) != n ? b.get_connected_nations(0) : b.get_connected_nations(1);
211 if(!
nations::are_allied(state, n, other) && (!in_sphere_of || in_sphere_of != other.get_in_sphere_of())) {
212 greatest_neighbor = std::max(greatest_neighbor,
estimate_strength(state, other));
217 auto ll = state.world.nation_get_last_war_loss(n);
218 float safety_factor = 1.2f;
219 if(ll && state.current_date < ll + 365 * 4) {
220 safety_factor = 1.8f;
223 auto safety_margin = defensive_str - safety_factor * greatest_neighbor;
225 for(
auto pt : prune_targets) {
227 if(weakest_str * 1.25 < safety_margin) {
228 safety_margin -= weakest_str;
231 }
else if(state.world.nation_get_infamy(pt) >= state.defines.badboy_limit) {
232 safety_margin -= weakest_str;
244 auto target_continent = state.world.province_get_continent(state.world.nation_get_capital(target));
245 auto source_continent = state.world.province_get_continent(state.world.nation_get_capital(from));
246 return (target_continent == source_continent) || bool(state.world.get_nation_adjacency_by_nation_adjacency_pair(target, from));
249static bool ai_has_mutual_enemy(
sys::state& state, dcon::nation_id from, dcon::nation_id target) {
250 auto rival_a = state.world.nation_get_ai_rival(target);
251 auto rival_b = state.world.nation_get_ai_rival(from);
253 if(rival_a && rival_a == rival_b)
276 if(!state.world.nation_get_ai_is_threatened(target))
280 if(state.world.nation_get_infamy(target) >= state.defines.badboy_limit * 0.75f)
284 if(state.world.nation_get_ai_rival(target) == from || state.world.nation_get_ai_rival(from) == target)
289 if(
bool(state.defines.alice_artificial_gp_limitant) && state.world.nation_get_is_great_power(target)) {
290 int32_t gp_count = 0;
291 for(
const auto rel : state.world.nation_get_diplomatic_relation(from)) {
292 auto n = rel.get_related_nations(rel.get_related_nations(0) == from ? 1 : 0);
293 if(rel.get_are_allied() && n.get_is_great_power()) {
301 if(
bool(state.defines.alice_spherelings_only_ally_sphere)) {
302 auto spherelord = state.world.nation_get_in_sphere_of(from);
305 if(state.world.nation_get_in_sphere_of(target) != spherelord && target != spherelord)
307 if(target == spherelord)
311 if(ai_has_mutual_enemy(state, from, target))
336 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);
344 if(!state.world.nation_get_is_at_war(from))
346 if(state.world.nation_get_ai_rival(target) == from)
351 for(
auto wa : state.world.nation_get_war_participant(target)) {
352 auto is_attacker = wa.get_is_attacker();
353 for(
auto o : wa.get_war().get_war_participant()) {
354 if(o.get_is_attacker() != is_attacker) {
368 auto ymd_date = state.current_date.to_ymd(state.start_date);
369 auto year =
uint32_t(ymd_date.year);
370 concurrency::parallel_for(
uint32_t(0), state.world.nation_size(), [&](
uint32_t id) {
371 dcon::nation_id n{ dcon::nation_id::value_base_t(id) };
373 if(state.world.nation_get_is_player_controlled(n)
374 || state.world.nation_get_current_research(n)
375 || !state.world.nation_get_is_civilized(n)
376 || state.world.nation_get_owned_province_count(n) == 0) {
382 struct potential_techs {
383 dcon::technology_id id;
387 std::vector<potential_techs> potential;
389 for(
auto tid : state.world.in_technology) {
390 if(state.world.nation_get_active_technologies(n, tid))
393 if(state.current_date.to_ymd(state.start_date).year >= state.world.technology_get_year(tid)) {
395 dcon::technology_id prev_tech = dcon::technology_id(dcon::technology_id::value_base_t(tid.id.index() - 1));
397 if(tid.id.index() != 0 && state.world.technology_get_folder_index(prev_tech) == state.world.technology_get_folder_index(tid)) {
399 if(state.world.nation_get_active_technologies(n, prev_tech))
400 potential.push_back(potential_techs{ tid, 0.0f });
402 potential.push_back(potential_techs{ tid, 0.0f });
407 for(
auto& pt : potential) {
408 auto base = state.world.technology_get_ai_weight(pt.id);
409 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) {
413 pt.weight = base / cost;
416 std::sort(potential.begin(), potential.end(), [&](potential_techs& a, potential_techs& b) {
417 if(a.weight != b.weight)
418 return a.weight > b.weight;
420 return (a.id.index() ^ rval) > (b.id.index() ^ rval);
423 if(!potential.empty()) {
424 state.world.nation_set_current_research(n, potential[0].
id);
430 for(
auto t : state.world.in_technology) {
431 float base = 1000.0f;
440 auto mod = t.get_modifier();
441 auto& vals = mod.get_national_values();
443 if(vals.offsets[i] == sys::national_mod_offsets::research_points) {
445 }
else if(vals.offsets[i] == sys::national_mod_offsets::research_points_modifier) {
447 }
else if(vals.offsets[i] == sys::national_mod_offsets::education_efficiency) {
449 }
else if(vals.offsets[i] == sys::national_mod_offsets::education_efficiency_modifier) {
451 }
else if(vals.offsets[i] == sys::national_mod_offsets::pop_growth) {
453 }
else if(vals.offsets[i] == sys::national_mod_offsets::max_national_focus) {
455 }
else if(vals.offsets[i] == sys::national_mod_offsets::colonial_life_rating) {
457 }
else if(vals.offsets[i] == sys::national_mod_offsets::rgo_output) {
459 }
else if(vals.offsets[i] == sys::national_mod_offsets::factory_output) {
461 }
else if(vals.offsets[i] == sys::national_mod_offsets::factory_throughput) {
463 }
else if(vals.offsets[i] == sys::national_mod_offsets::factory_input) {
465 }
else if(vals.offsets[i] == sys::national_mod_offsets::tax_efficiency) {
470 t.set_ai_weight(base);
475 struct weighted_nation {
479 static std::vector<weighted_nation> targets;
481 for(
auto gprl : state.world.in_gp_relationship) {
482 if(gprl.get_great_power().get_is_player_controlled()) {
485 auto& status = gprl.get_status();
486 status &=
~nations::influence::priority_mask;
493 for(
auto& n : state.great_nations) {
494 if(state.world.nation_get_is_player_controlled(n.nation))
498 for(
auto t : state.world.in_nation) {
499 if(t.get_is_great_power())
501 if(t.get_owned_province_count() == 0)
503 if(t.get_in_sphere_of() == n.nation)
510 for(
auto c : state.world.in_commodity) {
511 if(
auto d = state.world.nation_get_real_demand(n.nation, c); d > 0.001f) {
512 auto cweight = std::min(1.0f, t.get_domestic_market_pool(c) / d) * (1.0f - state.world.nation_get_demand_satisfaction(n.nation, c));
518 if(t.get_in_sphere_of()) {
523 if(t.get_primary_culture() == state.world.nation_get_primary_culture(n.nation)) {
528 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()) {
537 bool is_reachable =
false;
538 for(
auto adj : state.world.nation_get_nation_adjacency(t)) {
539 auto casted_adj = adj.get_connected_nations(0) != t ? adj.get_connected_nations(0) : adj.get_connected_nations(1);
540 if(casted_adj == n.nation) {
544 if(casted_adj.get_in_sphere_of() == n.nation) {
551 if(state.world.nation_get_central_ports(t) > 0) {
556 if(state.world.get_nation_adjacency_by_nation_adjacency_pair(n.nation, t.id)) {
565 targets.push_back(weighted_nation{ t.id, weight });
568 std::sort(targets.begin(), targets.end(), [](weighted_nation
const& a, weighted_nation
const& b) {
569 if(a.weight != b.weight)
570 return a.weight > b.weight;
572 return a.id.index() < b.id.index();
576 for(; i < 2 && i < targets.size(); ++i) {
577 auto rel = state.world.get_gp_relationship_by_gp_influence_pair(targets[i].
id, n.nation);
579 rel = state.world.force_create_gp_relationship(targets[i].
id, n.nation);
582 for(; i < 4 && i < targets.size(); ++i) {
583 auto rel = state.world.get_gp_relationship_by_gp_influence_pair(targets[i].
id, n.nation);
585 rel = state.world.force_create_gp_relationship(targets[i].
id, n.nation);
588 for(; i < 6 && i < targets.size(); ++i) {
589 auto rel = state.world.get_gp_relationship_by_gp_influence_pair(targets[i].
id, n.nation);
591 rel = state.world.force_create_gp_relationship(targets[i].
id, n.nation);
598 for(
auto gprl : state.world.in_gp_relationship) {
599 if(gprl.get_great_power().get_is_player_controlled()) {
612 auto current_sphere = gprl.get_influence_target().get_in_sphere_of();
625 && state.defines.removefromsphere_influence_cost <= gprl.get_influence()
628 && (state.world.nation_get_infamy(gprl.get_great_power()) + state.defines.removefromsphere_infamy_cost) < state.defines.badboy_limit
638 for(
auto f : state.world.in_national_focus) {
639 if(f.get_promotion_amount() > 0) {
640 if(f.get_promotion_type() == state.culture_definitions.clergy)
641 state.national_definitions.clergy_focus = f;
642 if(f.get_promotion_type() == state.culture_definitions.soldiers)
643 state.national_definitions.soldier_focus = f;
644 if(f.get_promotion_type() == state.culture_definitions.aristocrat)
645 state.national_definitions.aristocrat_focus = f;
646 if(f.get_promotion_type() == state.culture_definitions.capitalists)
647 state.national_definitions.capitalist_focus = f;
648 if(f.get_promotion_type() == state.culture_definitions.primary_factory_worker)
649 state.national_definitions.primary_factory_worker_focus = f;
650 if(f.get_promotion_type() == state.culture_definitions.secondary_factory_worker)
651 state.national_definitions.secondary_factory_worker_focus = f;
657 for(
auto si : state.world.in_state_instance) {
658 if(!si.get_nation_from_state_ownership().get_is_player_controlled())
659 si.set_owner_focus(dcon::national_focus_id{});
662 for(
auto n : state.world.in_nation) {
663 if(n.get_is_player_controlled())
665 if(n.get_owned_province_count() == 0)
668 n.set_state_from_flashpoint_focus(dcon::state_instance_id{});
671 if(num_focuses_total <= 0)
674 auto base_opt = state.world.pop_type_get_research_optimum(state.culture_definitions.clergy);
676 bool max_clergy = clergy_frac >= base_opt;
678 static std::vector<dcon::state_instance_id> ordered_states;
679 ordered_states.clear();
680 for(
auto si : n.get_state_ownership()) {
681 ordered_states.push_back(si.get_state().id);
683 std::sort(ordered_states.begin(), ordered_states.end(), [&](
auto a,
auto b) {
684 auto apop = state.world.state_instance_get_demographics(a, demographics::total);
685 auto bpop = state.world.state_instance_get_demographics(b, demographics::total);
689 return a.index() < b.index();
691 bool threatened = n.get_ai_is_threatened() || n.get_is_at_war();
692 for(
uint32_t i = 0; num_focuses_total > 0 && i < ordered_states.size(); ++i) {
693 auto prov = state.world.state_instance_get_capital(ordered_states[i]);
696 auto nf = state.national_definitions.soldier_focus;
697 auto k = state.world.national_focus_get_limit(nf);
700 state.world.state_instance_set_owner_focus(ordered_states[i], state.national_definitions.soldier_focus);
704 auto total = state.world.state_instance_get_demographics(ordered_states[i],
demographics::total);
705 auto cfrac = state.world.state_instance_get_demographics(ordered_states[i],
demographics::to_key(state, state.culture_definitions.clergy)) / total;
706 if(cfrac < state.defines.max_clergy_for_literacy * 0.8f) {
707 auto nf = state.national_definitions.clergy_focus;
708 auto k = state.world.national_focus_get_limit(nf);
711 state.world.state_instance_set_owner_focus(ordered_states[i], state.national_definitions.clergy_focus);
718 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);
719 if(cfrac < base_opt * 1.2f) {
720 auto nf = state.national_definitions.clergy_focus;
721 auto k = state.world.national_focus_get_limit(nf);
724 state.world.state_instance_set_owner_focus(ordered_states[i], state.national_definitions.clergy_focus);
731 for(
uint32_t i = 0; num_focuses_total > 0 && i < ordered_states.size(); ++i) {
732 auto prov = state.world.state_instance_get_capital(ordered_states[i]);
733 auto total = state.world.state_instance_get_demographics(ordered_states[i],
demographics::total);
734 auto pw_num = state.world.state_instance_get_demographics(ordered_states[i],
demographics::to_key(state, state.culture_definitions.primary_factory_worker));
735 auto pw_employed = state.world.state_instance_get_demographics(ordered_states[i],
demographics::to_employment_key(state, state.culture_definitions.primary_factory_worker));
736 auto sw_num = state.world.state_instance_get_demographics(ordered_states[i],
demographics::to_key(state, state.culture_definitions.secondary_factory_worker));
737 auto sw_employed = state.world.state_instance_get_demographics(ordered_states[i],
demographics::to_employment_key(state, state.culture_definitions.secondary_factory_worker));
738 auto sw_frac = sw_num / std::max(pw_num + sw_num, 1.0f);
739 auto ideal_swfrac = (1.f - state.economy_definitions.craftsmen_fraction);
742 if((pw_employed >= pw_num || pw_num < 1.0f)) {
743 auto nf = state.national_definitions.primary_factory_worker_focus;
744 auto k = state.world.national_focus_get_limit(nf);
749 state.world.state_instance_set_owner_focus(ordered_states[i], nf);
752 }
else if(pw_num > 1.0f && pw_employed > 1.0f && int8_t(sw_frac * 100.f) != int8_t(ideal_swfrac * 100.f)) {
753 auto nf = state.national_definitions.secondary_factory_worker_focus;
754 auto k = state.world.national_focus_get_limit(nf);
759 state.world.state_instance_set_owner_focus(ordered_states[i], nf);
766 auto rules = n.get_combined_issue_rules();
768 auto nf = state.national_definitions.capitalist_focus;
769 auto k = state.world.national_focus_get_limit(nf);
772 state.world.state_instance_set_owner_focus(ordered_states[i], nf);
776 auto nf = state.national_definitions.aristocrat_focus;
777 auto k = state.world.national_focus_get_limit(nf);
780 state.world.state_instance_set_owner_focus(ordered_states[i], nf);
790 for(
auto d : state.world.in_decision) {
791 auto e = d.get_effect();
795 auto potential = d.get_potential();
796 auto allow = d.get_allow();
797 auto ai_will_do = d.get_ai_will_do();
799 ve::execute_serial_fast<dcon::nation_id>(state.world.nation_size(), [&](
auto ids) {
800 ve::vbitfield_type filter_a = potential
801 ? (ve::compress_mask(trigger::evaluate(state, potential, trigger::to_generic(ids), trigger::to_generic(ids), 0)) & !state.world.nation_get_is_player_controlled(ids))
802 : !state.world.nation_get_is_player_controlled(ids);
804 if(filter_a.v != 0) {
806 ve::mask_vector filter_c = allow
807 ? (trigger::evaluate(state, allow, trigger::to_generic(ids), trigger::to_generic(ids), 0) && (state.world.nation_get_owned_province_count(ids) != 0)) && filter_a
808 : ve::mask_vector{ filter_a } && (state.world.nation_get_owned_province_count(ids) != 0);
809 ve::mask_vector filter_b = ai_will_do
810 ? filter_c && (trigger::evaluate_multiplicative_modifier(state, ai_will_do, trigger::to_generic(ids), trigger::to_generic(ids), 0) > 0.0f)
813 ve::apply([&](dcon::nation_id n, bool passed_filter) {
815 auto second_validity = potential
816 ? trigger::evaluate(state, potential, trigger::to_generic(n), trigger::to_generic(n), 0)
818 second_validity = second_validity && (allow
819 ? trigger::evaluate(state, allow, trigger::to_generic(n), trigger::to_generic(n), 0)
821 if(second_validity) {
822 effect::execute(state, e, trigger::to_generic(n), trigger::to_generic(n), 0, uint32_t(state.current_date.value),
823 uint32_t(n.index() << 4 ^ d.id.index()));
824 notification::post(state, notification::message{
825 [e, n, did = d.id, when = state.current_date](sys::state& state, text::layout_base& contents) {
826 text::add_line(state, contents,
"msg_decision_1", text::variable_type::x, n, text::variable_type::y, state.world.decision_get_name(did));
827 text::add_line(state, contents,
"msg_decision_2");
828 ui::effect_description(state, contents, e, trigger::to_generic(n), trigger::to_generic(n), 0, uint32_t(when.value), uint32_t(n.index() << 4 ^ did.index()));
830 "msg_decision_title",
831 n, dcon::nation_id{}, dcon::nation_id{},
832 sys::message_base_type::decision
844 auto iid = state.world.political_party_get_ideology(pid);
858 auto last_change = state.world.nation_get_ruling_party_last_appointed(n);
859 if(last_change && state.current_date < last_change + 365)
870 for(
auto n : state.world.in_nation) {
872 if(n.get_is_player_controlled() || n.get_owned_province_count() == 0)
876 auto gov = n.get_government_type();
877 auto identity = n.get_identity_from_identity_holder();
878 auto start = state.world.national_identity_get_political_party_first(identity).id.index();
879 auto end = start + state.world.national_identity_get_political_party_count(identity);
881 dcon::political_party_id target;
883 for(int32_t i = start; i < end; i++) {
884 auto pid = dcon::political_party_id(uint16_t(i));
887 if(support > max_support) {
889 max_support = support;
894 assert(target != state.world.nation_get_ruling_party(n));
903 assert(desired_types.empty());
929 if(desired_types.empty()) {
930 for(
auto type : state.world.in_factory_type) {
931 if(n.get_active_building(type) || type.get_is_available_from_start()) {
932 auto& inputs = type.get_inputs();
933 bool lacking_input =
false;
934 bool lacking_output = n.get_demand_satisfaction(type.get_output()) < 0.98f;
936 float input_total = 0.f;
938 if(inputs.commodity_type[i]) {
939 input_total += inputs.commodity_amounts[i] * state.world.commodity_get_current_price(inputs.commodity_type[i]);
940 if(n.get_demand_satisfaction(inputs.commodity_type[i]) < 0.98f)
941 lacking_input =
true;
947 float output_total = type.get_output_amount() * state.world.commodity_get_current_price(type.get_output());
949 float input_multiplier = std::max(0.1f, (state.defines.alice_inputs_base_factor +
950 state.world.nation_get_modifier_values(n, sys::national_mod_offsets::factory_input)));
952 float output_multiplier = state.world.nation_get_factory_goods_output(n, type.get_output()) +
953 state.world.nation_get_modifier_values(n, sys::national_mod_offsets::factory_output) + 1.0f;
956 if(!lacking_input && (lacking_output || (input_total * input_multiplier * 0.9 <= output_total * output_multiplier)))
957 desired_types.push_back(type.id);
964 for(
auto n : state.world.in_nation) {
966 if(n.get_owned_province_count() == 0 || !n.get_is_civilized())
969 if(n.get_is_player_controlled()) {
985 if(0.7 * n.get_recruitable_regiments() > n.get_active_regiments())
989 int32_t max_projects = std::max(8, int32_t(treasury / 64000.0f));
990 auto rules = n.get_combined_issue_rules();
996 static std::vector<dcon::state_instance_id> ordered_states;
997 ordered_states.clear();
998 for(
auto si : n.get_state_ownership()) {
999 if(si.get_state().get_capital().get_is_colonial() ==
false)
1000 ordered_states.push_back(si.get_state().id);
1002 std::sort(ordered_states.begin(), ordered_states.end(), [&](
auto a,
auto b) {
1003 auto apop = state.world.state_instance_get_demographics(a, demographics::total);
1004 auto bpop = state.world.state_instance_get_demographics(b, demographics::total);
1008 return a.index() < b.index();
1013 for(
auto si : ordered_states) {
1014 if(max_projects <= 0)
1018 for(
auto fac : state.world.province_get_factory_location(p)) {
1019 auto type = fac.get_factory().get_building_type();
1021 auto unprofitable = fac.get_factory().get_unprofitable();
1022 auto factory_level = fac.get_factory().get_level();
1023 auto primary_employment = fac.get_factory().get_primary_employment();
1025 if(!unprofitable && factory_level < uint8_t(255) && primary_employment >= 0.9f) {
1027 auto ug_in_progress = false;
1028 for(auto c : state.world.state_instance_get_state_building_construction(si)) {
1029 if(c.get_type() == type) {
1030 ug_in_progress = true;
1035 if(!ug_in_progress) {
1036 auto new_up = fatten(state.world, state.world.force_create_state_building_construction(si, n));
1037 new_up.set_is_pop_project(false);
1038 new_up.set_is_upgrade(true);
1039 new_up.set_type(type);
1051 static::std::vector<dcon::factory_type_id> desired_types;
1052 desired_types.clear();
1056 if(!desired_types.empty()) {
1060 for(
auto si : ordered_states) {
1061 if(max_projects <= 0)
1065 auto pw_num = state.world.state_instance_get_demographics(si,
1067 pw_num += state.world.state_instance_get_demographics(si,
1069 auto pw_employed = state.world.state_instance_get_demographics(si,
1071 pw_employed += state.world.state_instance_get_demographics(si,
1074 if(pw_employed >=
float(pw_num) * 2.5f && pw_num > 0.0f)
1077 auto type_selection = desired_types[
rng::get_random(state,
uint32_t(n.id.index() + max_projects)) % desired_types.size()];
1083 bool already_in_progress = [&]() {
1084 for(
auto p : state.world.state_instance_get_state_building_construction(si)) {
1085 if(p.get_type() == type_selection)
1091 if(already_in_progress)
1095 bool present_in_location =
false;
1096 bool under_cap =
false;
1099 for(
auto fac : state.world.province_get_factory_location(p)) {
1100 auto type = fac.get_factory().get_building_type();
1101 if(type_selection == type) {
1102 under_cap = fac.get_factory().get_production_scale() < 0.9f || fac.get_factory().get_primary_employment() < 0.9f;
1103 present_in_location = true;
1111 if(present_in_location) {
1113 auto new_up = fatten(state.world, state.world.force_create_state_building_construction(si, n));
1114 new_up.set_is_pop_project(
false);
1115 new_up.set_is_upgrade(
true);
1116 new_up.set_type(type_selection);
1124 if(num_factories < int32_t(state.defines.factories_per_state)) {
1125 auto new_up = fatten(state.world, state.world.force_create_state_building_construction(si, n));
1126 new_up.set_is_pop_project(
false);
1127 new_up.set_is_upgrade(
false);
1128 new_up.set_type(type_selection);
1139 static std::vector<dcon::province_id> project_provs;
1140 project_provs.clear();
1143 if(max_projects > 0) {
1144 project_provs.clear();
1145 for(
auto o : n.get_province_ownership()) {
1146 if(!o.get_province().get_is_coast())
1148 if(n != o.get_province().get_nation_from_province_control())
1160 int32_t min_build = int32_t(o.get_province().get_modifier_values(sys::provincial_mod_offsets::min_build_naval_base));
1162 if(max_local_lvl - current_lvl - min_build <= 0)
1166 project_provs.push_back(o.get_province().id);
1169 auto cap =
n.get_capital();
1170 std::sort(project_provs.begin(), project_provs.end(), [&](dcon::province_id a, dcon::province_id b) {
1171 auto a_dist = province::sorting_distance(state, a, cap);
1172 auto b_dist = province::sorting_distance(state, b, cap);
1173 if(a_dist != b_dist)
1174 return a_dist < b_dist;
1176 return a.index() < b.index();
1178 if(!project_provs.empty()) {
1179 auto si =
state.world.province_get_state_membership(project_provs[0]);
1181 si.set_naval_base_is_taken(
true);
1182 auto new_rr =
fatten(
state.world,
state.world.force_create_province_building_construction(project_provs[0], n));
1183 new_rr.set_is_pop_project(
false);
1193 dcon::provincial_modifier_value mod;
1194 } econ_buildable[3] = {
1199 for(
auto i = 0; i < 3; i++) {
1200 if(econ_buildable[i].buildable && max_projects > 0) {
1201 project_provs.clear();
1202 for(
auto o :
n.get_province_ownership()) {
1203 if(n != o.get_province().get_nation_from_province_control())
1207 int32_t current_lvl =
state.world.province_get_building_level(o.get_province(),
uint8_t(econ_buildable[i].type));
1208 int32_t max_local_lvl =
state.world.nation_get_max_building_level(n,
uint8_t(econ_buildable[i].type));
1209 int32_t min_build = int32_t(
state.world.province_get_modifier_values(o.get_province(), econ_buildable[i].mod));
1210 if(max_local_lvl - current_lvl - min_build <= 0)
1213 project_provs.push_back(o.get_province().id);
1216 auto cap =
n.get_capital();
1217 std::sort(project_provs.begin(), project_provs.end(), [&](dcon::province_id a, dcon::province_id b) {
1218 auto a_dist = province::sorting_distance(state, a, cap);
1219 auto b_dist = province::sorting_distance(state, b, cap);
1220 if(a_dist != b_dist)
1221 return a_dist < b_dist;
1223 return a.index() < b.index();
1225 for(
uint32_t j = 0; j < project_provs.size() && max_projects > 0; ++j) {
1226 auto new_proj =
fatten(
state.world,
state.world.force_create_province_building_construction(project_provs[j], n));
1227 new_proj.set_is_pop_project(
false);
1228 new_proj.set_type(
uint8_t(econ_buildable[i].type));
1235 if(max_projects > 0) {
1236 project_provs.clear();
1238 for(
auto o :
n.get_province_ownership()) {
1239 if(n != o.get_province().get_nation_from_province_control())
1252 int32_t min_build = int32_t(
state.world.province_get_modifier_values(o.get_province(), sys::provincial_mod_offsets::min_build_fort));
1254 if(max_local_lvl - current_lvl - min_build <= 0)
1258 project_provs.push_back(o.get_province().id);
1262 auto cap =
n.get_capital();
1263 std::sort(project_provs.begin(), project_provs.end(), [&](dcon::province_id a, dcon::province_id b) {
1264 auto a_dist = province::sorting_distance(state, a, cap);
1265 auto b_dist = province::sorting_distance(state, b, cap);
1266 if(a_dist != b_dist)
1267 return a_dist < b_dist;
1269 return a.index() < b.index();
1272 for(
uint32_t i = 0; i < project_provs.size() && max_projects > 0; ++i) {
1273 auto new_rr =
fatten(
state.world,
state.world.force_create_province_building_construction(project_provs[i], n));
1274 new_rr.set_is_pop_project(
false);
1283 static std::vector<dcon::state_definition_id> investments;
1284 static std::vector<int32_t> free_points;
1286 investments.clear();
1287 investments.resize(
uint32_t(state.defines.colonial_rank));
1289 free_points.clear();
1290 free_points.resize(
uint32_t(state.defines.colonial_rank), -1);
1292 for(
auto col : state.world.in_colonization) {
1293 auto n = col.get_colonizer();
1294 if(n.get_is_player_controlled() ==
false
1295 && n.get_rank() <= uint16_t(state.defines.colonial_rank)
1296 && !investments[n.get_rank() - 1]
1297 && col.get_state().get_colonization_stage() <=
uint8_t(2)
1298 && state.crisis_colony != col.get_state()
1299 && (!state.crisis_war || n.get_is_at_war() ==
false)
1302 auto crange = col.get_state().get_colonization();
1303 if(crange.end() - crange.begin() > 1) {
1304 if(col.get_last_investment() + int32_t(state.defines.colonization_days_between_investment) <= state.current_date) {
1306 if(free_points[n.get_rank() - 1] < 0) {
1311 if(col.get_state().get_colonization_stage() == 1) {
1312 cost = int32_t(state.defines.colonization_interest_cost);
1313 }
else if(col.get_level() <= 4) {
1314 cost = int32_t(state.defines.colonization_influence_cost);
1317 int32_t(state.defines.colonization_extra_guard_cost * (col.get_level() - 4) + state.defines.colonization_influence_cost);
1319 if(free_points[n.get_rank() - 1] >= cost) {
1320 investments[n.get_rank() - 1] = col.get_state().id;
1326 for(
uint32_t i = 0; i < investments.size(); ++i) {
1332 static std::vector<int32_t> free_points;
1333 free_points.clear();
1334 free_points.resize(
uint32_t(state.defines.colonial_rank), -1);
1335 for(int32_t i = 0; i < int32_t(state.defines.colonial_rank); ++i) {
1336 if(state.world.nation_get_is_player_controlled(state.nations_by_rank[i])) {
1346 for(
auto sd : state.world.in_state_definition) {
1347 if(sd.get_colonization_stage() <= 1) {
1348 bool has_unowned_land =
false;
1350 dcon::province_id coastal_target;
1351 for(
auto p : state.world.state_definition_get_abstract_state_membership(sd)) {
1352 if(!p.get_province().get_nation_from_province_ownership()) {
1353 if(p.get_province().get_is_coast() && !coastal_target) {
1354 coastal_target = p.get_province();
1356 if(p.get_province().id.index() < state.province_definitions.first_sea_province.index())
1357 has_unowned_land =
true;
1360 if(has_unowned_land) {
1361 for(int32_t i = 0; i < int32_t(state.defines.colonial_rank); ++i) {
1362 if(free_points[i] > 0) {
1363 bool adjacent =
false;
1365 free_points[i] -= int32_t(state.defines.colonization_interest_cost_initial + (adjacent ? state.defines.colonization_interest_cost_neighbor_modifier : 0.0f));
1367 auto new_rel = fatten(state.world, state.world.force_create_colonization(sd, state.nations_by_rank[i]));
1368 new_rel.set_level(
uint8_t(1));
1369 new_rel.set_last_investment(state.current_date);
1370 new_rel.set_points_invested(uint16_t(state.defines.colonization_interest_cost_initial + (adjacent ? state.defines.colonization_interest_cost_neighbor_modifier : 0.0f)));
1372 state.world.state_definition_set_colonization_stage(sd,
uint8_t(1));
1382 for(
auto si : state.world.in_state_instance) {
1383 if(si.get_capital().get_is_colonial() && si.get_nation_from_state_ownership().get_is_player_controlled() ==
false) {
1392 for(
auto n : state.world.in_nation) {
1393 if(!n.get_is_player_controlled() && !n.get_is_civilized() && n.get_modifier_values(sys::national_mod_offsets::civilization_progress_modifier) >= 1.0f) {
1400 for(
auto n : state.world.in_nation) {
1401 if(n.get_is_player_controlled() || n.get_owned_province_count() == 0)
1404 if(n.get_is_civilized()) {
1407 dcon::issue_option_id iss;
1408 float max_support = 0.0f;
1410 for(
auto m : state.world.nation_get_movement_within(n)) {
1411 if(m.get_movement().get_associated_issue_option() && m.get_movement().get_pop_support() > max_support) {
1412 iss = m.get_movement().get_associated_issue_option();
1413 max_support = m.get_movement().get_pop_support();
1418 iss = dcon::issue_option_id{};
1419 state.world.for_each_issue_option([&](dcon::issue_option_id io) {
1421 float support = 0.f;
1422 for(
const auto poid : state.world.nation_get_province_ownership_as_nation(n)) {
1423 for(auto plid : state.world.province_get_pop_location_as_province(poid.get_province())) {
1424 float weigth = plid.get_pop().get_size() * 0.001f;
1425 support += pop_demographics::get_demo(state, plid.get_pop(), pop_demographics::to_key(state, io)) * weigth;
1428 if(support > max_support) {
1430 max_support = support;
1439 dcon::reform_option_id cheap_r;
1440 float cheap_cost = 0.0f;
1445 for(
auto r : state.world.in_reform_option) {
1448 auto reform = state.world.reform_option_get_parent_reform(r);
1449 auto current = state.world.nation_get_reforms(n, reform.id).id;
1450 auto allow = state.world.reform_option_get_allow(r);
1454 float base_cost = float(state.world.reform_option_get_technology_cost(r));
1455 float reform_factor = is_military ? m_mul : e_mul;
1457 if(!cheap_r || base_cost * reform_factor < cheap_cost) {
1458 cheap_cost = base_cost * reform_factor;
1464 if(cheap_r && cheap_cost <= n.get_research_points()) {
1474 auto colonizers = state.world.state_definition_get_colonization(state.crisis_colony);
1475 if(colonizers.end() - colonizers.begin() < 2)
1478 auto defending_colonizer = (*(colonizers.begin() + 1)).get_colonizer();
1479 if(state.world.nation_get_in_sphere_of(defending_colonizer) == n)
1481 if(state.world.nation_get_ai_rival(n) == defending_colonizer
1482 || (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())) {
1485 if(state.primary_crisis_defender && state.world.nation_get_ai_rival(n) == state.primary_crisis_defender)
1490 auto state_owner = state.world.state_instance_get_nation_from_state_ownership(state.crisis_state);
1491 auto liberated = state.world.national_identity_get_nation_from_identity_holder(state.crisis_liberation_tag);
1493 if(state_owner == n)
1497 if(state.world.nation_get_in_sphere_of(state_owner) == n ||
nations::are_allied(state, n, state_owner))
1499 if(state.world.nation_get_ai_rival(n) == state_owner)
1501 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))
1503 if(state.world.nation_get_in_sphere_of(liberated) == n ||
nations::are_allied(state, n, liberated))
1505 if(state.primary_crisis_defender && state.world.nation_get_ai_rival(n) == state.primary_crisis_defender)
1514 auto colonizers = state.world.state_definition_get_colonization(state.crisis_colony);
1515 if(colonizers.end() - colonizers.begin() < 2)
1518 auto attacking_colonizer = (*colonizers.begin()).get_colonizer();
1520 if(state.world.nation_get_in_sphere_of(attacking_colonizer) == n)
1522 if(state.world.nation_get_ai_rival(n) == attacking_colonizer
1523 || (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())
1524 || state.world.nation_get_ai_rival(n) == state.primary_crisis_attacker) {
1527 if(state.primary_crisis_attacker && state.world.nation_get_ai_rival(n) == state.primary_crisis_attacker)
1532 auto state_owner = state.world.state_instance_get_nation_from_state_ownership(state.crisis_state);
1533 auto liberated = state.world.national_identity_get_nation_from_identity_holder(state.crisis_liberation_tag);
1535 if(state_owner == n)
1539 if(state.world.nation_get_in_sphere_of(liberated) == n ||
nations::are_allied(state, n, liberated))
1541 if(state.world.nation_get_ai_rival(n) == liberated)
1543 if(state.world.nation_get_in_sphere_of(liberated) && state.world.nation_get_ai_rival(n) == state.world.nation_get_in_sphere_of(liberated))
1545 if(state.world.nation_get_in_sphere_of(state_owner) == n ||
nations::are_allied(state, n, state_owner))
1547 if(state.primary_crisis_attacker && state.world.nation_get_ai_rival(n) == state.primary_crisis_attacker)
1556 float attacker = 0.0f;
1557 float defender = 0.0f;
1561 float atotal = 0.0f;
1562 float dtotal = 0.0f;
1564 dcon::nation_id secondary_attacker;
1565 dcon::nation_id secondary_defender;
1568 auto colonizers = state.world.state_definition_get_colonization(state.crisis_colony);
1569 if(colonizers.end() - colonizers.begin() >= 2) {
1570 secondary_defender = (*(colonizers.begin() + 1)).get_colonizer();
1571 secondary_attacker = (*(colonizers.begin())).get_colonizer();
1574 secondary_defender = state.world.state_instance_get_nation_from_state_ownership(state.crisis_state);
1575 secondary_attacker = state.world.national_identity_get_nation_from_identity_holder(state.crisis_liberation_tag);
1578 if(secondary_attacker && secondary_attacker != state.primary_crisis_attacker) {
1581 if(secondary_defender && secondary_defender != state.primary_crisis_defender) {
1584 for(
auto& i : state.crisis_participants) {
1587 if(!i.merely_interested) {
1588 if(i.supports_attacker) {
1599 if(offer.
target == state.world.nation_get_ai_rival(n))
1601 auto offer_bits = state.world.cb_type_get_type_bits(offer.
wargoal_type);
1608 auto offer_bits = state.world.cb_type_get_type_bits(t);
1622 for(
auto si : state.world.nation_get_state_ownership(within)) {
1623 result.push_back(si.get_state().id);
1626 auto distance_from = state.world.nation_get_capital(for_nation).id;
1629 if(state.world.get_nation_adjacency_by_nation_adjacency_pair(for_nation, within)) {
1630 int32_t last = int32_t(result.size());
1631 while(first < last - 1) {
1638 if(first < last - 1) {
1639 std::swap(result[first], result[last - 1]);
1645 std::sort(result.begin(), result.begin() + first, [&](dcon::state_instance_id a, dcon::state_instance_id b) {
1646 auto a_distance = province::sorting_distance(state, state.world.state_instance_get_capital(a), distance_from);
1647 auto b_distance = province::sorting_distance(state, state.world.state_instance_get_capital(b), distance_from);
1648 if(a_distance != b_distance)
1649 return a_distance < b_distance;
1651 return a.index() < b.index();
1654 if(state.world.nation_get_total_ports(for_nation) > 0 && state.world.nation_get_total_ports(within) > 0) {
1655 int32_t last = int32_t(result.size());
1656 while(first < last - 1) {
1663 if(first < last - 1) {
1664 std::swap(result[first], result[last - 1]);
1669 std::sort(result.begin(), result.begin() + first, [&](dcon::state_instance_id a, dcon::state_instance_id b) {
1670 auto a_distance = province::sorting_distance(state, state.world.state_instance_get_capital(a), distance_from);
1671 auto b_distance = province::sorting_distance(state, state.world.state_instance_get_capital(b), distance_from);
1672 if(a_distance != b_distance)
1673 return a_distance < b_distance;
1675 return a.index() < b.index();
1678 if(first < int32_t(result.size())) {
1679 std::sort(result.begin() + first, result.end(), [&](dcon::state_instance_id a, dcon::state_instance_id b) {
1680 auto a_distance = province::sorting_distance(state, state.world.state_instance_get_capital(a), distance_from);
1681 auto b_distance = province::sorting_distance(state, state.world.state_instance_get_capital(b), distance_from);
1682 if(a_distance != b_distance)
1683 return a_distance < b_distance;
1685 return a.index() < b.index();
1691 if(state.crisis_temperature > 0.75f) {
1694 bool defender_victory = str_est.attacker < str_est.defender * 0.66f;
1695 if(state.world.nation_get_is_player_controlled(state.primary_crisis_attacker) ==
false) {
1698 auto pending = state.world.nation_get_peace_offer_from_pending_peace_offer(state.primary_crisis_attacker);
1699 for(
auto& par : state.crisis_participants) {
1702 bool side_ood = defender_victory ? !par.supports_attacker : par.supports_attacker;
1703 if(!par.merely_interested && side_ood && par.joined_with_offer.wargoal_type) {
1704 auto wg = fatten(state.world, state.world.create_wargoal());
1705 wg.set_peace_offer_from_peace_offer_item(pending);
1706 wg.set_added_by(par.id);
1707 wg.set_associated_state(par.joined_with_offer.wargoal_state);
1708 wg.set_associated_tag(par.joined_with_offer.wargoal_tag);
1709 wg.set_secondary_nation(par.joined_with_offer.wargoal_secondary_nation);
1710 wg.set_target_nation(par.joined_with_offer.target);
1711 wg.set_type(par.joined_with_offer.wargoal_type);
1712 assert(
command::can_add_to_crisis_peace_offer(state, state.primary_crisis_attacker, par.id, par.joined_with_offer.target, par.joined_with_offer.wargoal_type, par.joined_with_offer.wargoal_state, par.joined_with_offer.wargoal_tag, par.joined_with_offer.wargoal_secondary_nation));
1717 }
else if(state.world.nation_get_is_player_controlled(state.primary_crisis_defender) ==
false) {
1720 auto pending = state.world.nation_get_peace_offer_from_pending_peace_offer(state.primary_crisis_defender);
1721 for(
auto& par : state.crisis_participants) {
1724 bool side_ood = !defender_victory ? par.supports_attacker : !par.supports_attacker;
1725 if(!par.merely_interested && side_ood && par.joined_with_offer.wargoal_type) {
1726 auto wg = fatten(state.world, state.world.create_wargoal());
1727 wg.set_peace_offer_from_peace_offer_item(pending);
1728 wg.set_added_by(par.id);
1729 wg.set_associated_state(par.joined_with_offer.wargoal_state);
1730 wg.set_associated_tag(par.joined_with_offer.wargoal_tag);
1731 wg.set_secondary_nation(par.joined_with_offer.wargoal_secondary_nation);
1732 wg.set_target_nation(par.joined_with_offer.target);
1733 wg.set_type(par.joined_with_offer.wargoal_type);
1734 assert(
command::can_add_to_crisis_peace_offer(state, state.primary_crisis_defender, par.id, par.joined_with_offer.target, par.joined_with_offer.wargoal_type, par.joined_with_offer.wargoal_state, par.joined_with_offer.wargoal_tag, par.joined_with_offer.wargoal_secondary_nation));
1740 }
else if(state.crisis_temperature > 0.2f) {
1742 if(str_est.attacker < str_est.defender && state.world.nation_get_is_player_controlled(state.primary_crisis_attacker) ==
false) {
1743 for(
auto& par : state.crisis_participants) {
1746 if(par.merely_interested) {
1747 auto other_cbs = state.world.nation_get_available_cbs(par.id);
1748 dcon::cb_type_id offer_cb;
1749 dcon::nation_id target;
1752 for(
auto& op_par : state.crisis_participants) {
1755 if(!op_par.merely_interested && op_par.supports_attacker ==
false) {
1756 for(
auto& cb : other_cbs) {
1758 offer_cb = cb.cb_type;
1763 for(
auto cb : state.world.in_cb_type) {
1778 std::vector < dcon::state_instance_id> potential_states;
1780 for(
auto s : potential_states) {
1786 m.from = state.primary_crisis_attacker;
1787 m.data.crisis_offer.target = target;
1788 m.data.crisis_offer.wargoal_secondary_nation = dcon::nation_id{};
1789 m.data.crisis_offer.wargoal_state = state.world.state_instance_get_definition(s);
1790 m.data.crisis_offer.wargoal_tag = dcon::national_identity_id{};
1791 m.data.crisis_offer.wargoal_type = offer_cb;
1802 m.from = state.primary_crisis_attacker;
1803 m.data.crisis_offer.target = target;
1804 m.data.crisis_offer.wargoal_secondary_nation = dcon::nation_id{};
1805 m.data.crisis_offer.wargoal_state = dcon::state_definition_id{};
1806 m.data.crisis_offer.wargoal_tag = dcon::national_identity_id{};
1807 m.data.crisis_offer.wargoal_type = offer_cb;
1814 }
else if(str_est.attacker < str_est.defender && state.world.nation_get_is_player_controlled(state.primary_crisis_defender) ==
false) {
1815 for(
auto& par : state.crisis_participants) {
1818 if(par.merely_interested) {
1819 auto other_cbs = state.world.nation_get_available_cbs(par.id);
1820 dcon::cb_type_id offer_cb;
1821 dcon::nation_id target;
1824 for(
auto& op_par : state.crisis_participants) {
1827 if(!op_par.merely_interested && op_par.supports_attacker ==
true) {
1828 for(
auto& cb : other_cbs) {
1830 offer_cb = cb.cb_type;
1835 for(
auto cb : state.world.in_cb_type) {
1850 std::vector < dcon::state_instance_id> potential_states;
1852 for(
auto s : potential_states) {
1858 m.from = state.primary_crisis_defender;
1859 m.data.crisis_offer.target = target;
1860 m.data.crisis_offer.wargoal_secondary_nation = dcon::nation_id{};
1861 m.data.crisis_offer.wargoal_state = state.world.state_instance_get_definition(s);
1862 m.data.crisis_offer.wargoal_tag = dcon::national_identity_id{};
1863 m.data.crisis_offer.wargoal_type = offer_cb;
1874 m.from = state.primary_crisis_defender;
1875 m.data.crisis_offer.target = target;
1876 m.data.crisis_offer.wargoal_secondary_nation = dcon::nation_id{};
1877 m.data.crisis_offer.wargoal_state = dcon::state_definition_id{};
1878 m.data.crisis_offer.wargoal_tag = dcon::national_identity_id{};
1879 m.data.crisis_offer.wargoal_type = offer_cb;
1891 if(state.crisis_temperature < 50.0f)
1896 if(to == state.primary_crisis_attacker) {
1897 if(str_est.attacker < str_est.defender * 0.66f)
1899 if(str_est.attacker < str_est.defender * 0.75f)
1900 return is_concession;
1905 dcon::nation_id attacker = state.primary_crisis_attacker;
1907 auto colonizers = state.world.state_definition_get_colonization(state.crisis_colony);
1908 if(colonizers.end() - colonizers.begin() >= 2) {
1909 attacker = (*(colonizers.begin())).get_colonizer();
1917 }
else if(to == state.primary_crisis_defender) {
1918 if(str_est.defender < str_est.attacker * 0.66f)
1920 if(str_est.defender < str_est.attacker * 0.75f)
1921 return is_concession;
1935 if(state.crisis_temperature < 50.0f)
1940 if(to == state.primary_crisis_attacker) {
1941 if(str_est.attacker < str_est.defender * 0.66f)
1943 if(str_est.attacker < str_est.defender * 0.75f)
1944 return state.world.peace_offer_get_is_concession(peace);
1946 if(!state.world.peace_offer_get_is_concession(peace))
1949 dcon::nation_id attacker = state.primary_crisis_attacker;
1951 auto colonizers = state.world.state_definition_get_colonization(state.crisis_colony);
1952 if(colonizers.end() - colonizers.begin() >= 2) {
1953 attacker = (*(colonizers.begin())).get_colonizer();
1957 bool missing_wg =
true;
1958 for(
auto wg : state.world.peace_offer_get_peace_offer_item(peace)) {
1959 if(wg.get_wargoal().get_added_by() == attacker)
1966 for(
auto& i : state.crisis_participants) {
1969 if(!i.merely_interested) {
1970 if(i.supports_attacker && i.joined_with_offer.wargoal_type) {
1971 bool missing_wg =
true;
1972 for(
auto wg : state.world.peace_offer_get_peace_offer_item(peace)) {
1973 if(wg.get_wargoal().get_added_by() == i.id)
1983 }
else if(to == state.primary_crisis_defender) {
1984 if(str_est.defender < str_est.attacker * 0.66f)
1986 if(str_est.defender < str_est.attacker * 0.75f)
1987 return state.world.peace_offer_get_is_concession(peace);
1989 if(!state.world.peace_offer_get_is_concession(peace))
1993 auto colonizers = state.world.state_definition_get_colonization(state.crisis_colony);
1994 if(colonizers.end() - colonizers.begin() >= 2) {
1995 auto defender = (*(colonizers.begin() + 1)).get_colonizer();
1997 bool missing_wg =
true;
1998 for(
auto wg : state.world.peace_offer_get_peace_offer_item(peace)) {
1999 if(wg.get_wargoal().get_added_by() == defender)
2007 for(
auto& i : state.crisis_participants) {
2010 if(!i.merely_interested) {
2011 if(!i.supports_attacker && i.joined_with_offer.wargoal_type) {
2012 bool missing_wg =
true;
2013 for(
auto wg : state.world.peace_offer_get_peace_offer_item(peace)) {
2014 if(wg.get_wargoal().get_added_by() == i.id)
2028 for(
auto& gp : state.great_nations) {
2029 if(state.world.nation_get_is_player_controlled(gp.nation) ==
false && state.world.nation_get_is_at_war(gp.nation) ==
false){
2030 bool as_attacker =
false;
2031 dcon::war_id intervention_target;
2033 for(
auto w : state.world.in_war) {
2036 auto par = state.world.war_get_primary_defender(w);
2037 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()
2040 intervention_target = w;
2044 if(w.get_is_great()) {
2046 for(
auto par : w.get_war_participant()) {
2048 intervention_target = w;
2054 for(
auto par : w.get_war_participant()) {
2056 intervention_target = w;
2064 intervention_target = w;
2070 if(intervention_target) {
2079 static std::vector<dcon::cb_type_id> possibilities;
2080 possibilities.clear();
2082 for(
auto c : state.world.in_cb_type) {
2083 auto bits = state.world.cb_type_get_type_bits(c);
2089 float infamy_limit = state.world.nation_get_is_civilized(from) ? state.defines.badboy_limit / 2.f : state.defines.badboy_limit;
2094 auto sl = state.world.nation_get_in_sphere_of(target);
2097 possibilities.push_back(c);
2100 if(!possibilities.empty()) {
2103 return dcon::cb_type_id{};
2111 if(state.world.nation_get_constructing_cb_type(from))
2113 auto ol = state.world.nation_get_overlord_as_subject(from);
2114 if(state.world.overlord_get_ruler(ol) && state.world.overlord_get_ruler(ol) != target)
2116 if(state.world.nation_get_in_sphere_of(target) == from)
2122 auto sl = state.world.nation_get_in_sphere_of(target);
2126 if(state.world.nation_get_is_at_war(target)) {
2132 if(state.world.nation_get_owned_province_count(target) <= 2)
2135 if(state.world.province_get_continent(state.world.nation_get_capital(from)) != state.world.province_get_continent(state.world.nation_get_capital(target))) {
2137 if(state.world.nation_get_capital_ship_score(from) < std::max(1.f, 1.5f * state.world.nation_get_capital_ship_score(target)))
2144 for(
auto n : state.world.in_nation) {
2145 if(!n.get_is_player_controlled() && n.get_owned_province_count() > 0) {
2146 if(n.get_is_at_war())
2149 float infamy_limit = state.world.nation_get_is_civilized(n) ? state.defines.badboy_limit / 2.5f : state.defines.badboy_limit;
2150 if(n.get_infamy() > infamy_limit)
2152 if(n.get_constructing_cb_type())
2154 auto ol = n.get_overlord_as_subject().get_ruler().id;
2156 && n.get_ai_rival().get_in_sphere_of() != n
2157 && (!ol || ol == n.get_ai_rival())
2164 n.set_constructing_cb_target(n.get_ai_rival());
2165 n.set_constructing_cb_type(cb);
2168 static std::vector<dcon::nation_id> possible_targets;
2169 possible_targets.clear();
2170 for(
auto i : state.world.in_nation) {
2173 possible_targets.push_back(i.id);
2174 if(!i.get_is_civilized())
2175 possible_targets.push_back(i.id);
2178 if(!possible_targets.empty()) {
2181 n.set_constructing_cb_target(t);
2182 n.set_constructing_cb_type(cb);
2192 if(
bool(state.defines.alice_unciv_civ_forbid_war) && !state.world.nation_get_is_civilized(n)
2193 && !state.world.nation_get_is_substate(n) && !state.world.nation_get_in_sphere_of(n)
2194 && !state.world.overlord_get_ruler(state.world.nation_get_overlord_as_subject(n))) {
2195 auto pa = state.world.war_get_primary_attacker(w);
2196 auto pd = state.world.war_get_primary_defender(w);
2197 auto pa_cap = state.world.nation_get_capital(pa);
2198 auto pd_cap = state.world.nation_get_capital(pd);
2199 auto cap = state.world.nation_get_capital(n);
2200 if(state.world.province_get_continent(pa_cap) != state.world.province_get_continent(cap))
2202 if(state.world.province_get_continent(pd_cap) != state.world.province_get_continent(cap))
2208 for(
auto par : state.world.war_get_war_participant(w)) {
2209 if(par.get_is_attacker() == !as_attacker) {
2214 if(state.world.nation_get_ai_rival(n) == par.get_nation())
2229void 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) {
2230 auto can_use = state.world.cb_type_get_can_use(cb);
2231 auto allowed_substates = state.world.cb_type_get_allowed_substate_regions(cb);
2232 if(allowed_substates) {
2233 if(!state.world.nation_get_is_substate(target))
2235 auto ruler = state.world.overlord_get_ruler(state.world.nation_get_overlord_as_subject(target));
2245 auto allowed_countries = state.world.cb_type_get_allowed_countries(cb);
2246 auto allowed_states = state.world.cb_type_get_allowed_states(cb);
2248 if(!allowed_countries && allowed_states) {
2249 for(
auto si : target_states) {
2253 result.push_back(
possible_cb{ target, dcon::nation_id{}, dcon::national_identity_id{}, state.world.state_instance_get_definition(si), cb });
2259 }
else if(allowed_substates) {
2260 for(
auto si : target_states) {
2264 result.push_back(
possible_cb{ target, dcon::nation_id{}, dcon::national_identity_id{}, state.world.state_instance_get_definition(si), cb });
2270 }
else if(allowed_countries) {
2272 for(
auto other_nation : state.world.in_nation) {
2273 if(other_nation != n) {
2275 if(allowed_states) {
2276 for(
auto i = target_states.size(); i-- > 0;) {
2277 auto si = target_states[i];
2280 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{})) {
2282 result.push_back(
possible_cb{ target, dcon::nation_id{}, other_nation.get_identity_from_identity_holder(), state.world.state_instance_get_definition(si), cb });
2288 result.push_back(
possible_cb{ target, other_nation, dcon::national_identity_id{}, state.world.state_instance_get_definition(si), cb });
2298 result.push_back(
possible_cb{ target, dcon::nation_id{}, other_nation.get_identity_from_identity_holder(), dcon::state_definition_id{}, cb });
2304 result.push_back(
possible_cb{ target, other_nation, dcon::national_identity_id{}, dcon::state_definition_id{}, cb });
2315 result.push_back(
possible_cb{ target, dcon::nation_id{}, dcon::national_identity_id{}, dcon::state_definition_id{}, cb });
2324 for(
auto par : state.world.war_get_war_participant(w)) {
2325 if(par.get_is_attacker() != is_attacker) {
2326 static std::vector<dcon::state_instance_id> target_states;
2328 for(
auto& cb : state.world.nation_get_available_cbs(n)) {
2329 if(cb.target == par.get_nation())
2332 for(
auto cb : state.world.in_cb_type) {
2341 if((state.world.nation_get_ai_rival(n) == a.target) != (state.world.nation_get_ai_rival(n) == b.target)) {
2342 return state.world.nation_get_ai_rival(n) == a.target;
2347 if(a_annexes != b_annexes)
2356 auto rel_a = state.world.get_diplomatic_relation_by_diplomatic_pair(n, a.
target);
2357 auto rel_b = state.world.get_diplomatic_relation_by_diplomatic_pair(n, b.
target);
2358 if(state.world.diplomatic_relation_get_value(rel_a) != state.world.diplomatic_relation_get_value(rel_b))
2359 return state.world.diplomatic_relation_get_value(rel_a) < state.world.diplomatic_relation_get_value(rel_b);
2362 return a.
cb.index() < b.
cb.index();
2373void 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) {
2374 auto can_use = state.world.cb_type_get_can_use(cb);
2375 auto allowed_substates = state.world.cb_type_get_allowed_substate_regions(cb);
2377 if(allowed_substates) {
2378 if(!state.world.nation_get_is_substate(target))
2380 auto ruler = state.world.overlord_get_ruler(state.world.nation_get_overlord_as_subject(target));
2390 auto allowed_countries = state.world.cb_type_get_allowed_countries(cb);
2391 auto allowed_states = state.world.cb_type_get_allowed_states(cb);
2393 if(!allowed_countries && allowed_states) {
2394 bool any_allowed =
false;
2395 for(
auto si : target_states) {
2398 result.push_back(
possible_cb{ target, dcon::nation_id{}, dcon::national_identity_id{}, state.world.state_instance_get_definition(si), cb });
2403 }
else if(allowed_substates) {
2404 for(
auto si : target_states) {
2407 result.push_back(
possible_cb{ target, dcon::nation_id{}, dcon::national_identity_id{}, state.world.state_instance_get_definition(si), cb });
2412 }
else if(allowed_countries) {
2414 for(
auto other_nation : state.world.in_nation) {
2415 if(other_nation != n) {
2418 if(allowed_states) {
2419 for(
auto i = target_states.size(); i-- > 0;) {
2420 auto si = target_states[i];
2424 result.push_back(
possible_cb{ target, dcon::nation_id{}, other_nation.get_identity_from_identity_holder(), state.world.state_instance_get_definition(si), cb });
2428 result.push_back(
possible_cb{ target, other_nation, dcon::national_identity_id{}, state.world.state_instance_get_definition(si), cb });
2436 result.push_back(
possible_cb{ target, dcon::nation_id{}, other_nation.get_identity_from_identity_holder(), dcon::state_definition_id{}, cb });
2440 result.push_back(
possible_cb{ target, other_nation, dcon::national_identity_id{}, dcon::state_definition_id{}, cb });
2450 result.push_back(
possible_cb{ target, dcon::nation_id{}, dcon::national_identity_id{}, dcon::state_definition_id{}, cb });
2458 static std::vector<dcon::state_instance_id> target_states;
2461 auto other_cbs = state.world.nation_get_available_cbs(n);
2462 for(
auto& cb : other_cbs) {
2463 if(cb.target == target)
2466 for(
auto cb : state.world.in_cb_type) {
2473 if((state.world.nation_get_ai_rival(n) == a.target) != (state.world.nation_get_ai_rival(n) == b.target)) {
2474 return state.world.nation_get_ai_rival(n) == a.target;
2479 if(a_annexes != b_annexes)
2488 auto rel_a = state.world.get_diplomatic_relation_by_diplomatic_pair(n, a.
target);
2489 auto rel_b = state.world.get_diplomatic_relation_by_diplomatic_pair(n, b.
target);
2490 if(state.world.diplomatic_relation_get_value(rel_a) != state.world.diplomatic_relation_get_value(rel_b))
2491 return state.world.diplomatic_relation_get_value(rel_a) < state.world.diplomatic_relation_get_value(rel_b);
2494 return a.
cb.index() < b.
cb.index();
2515 static std::vector<possible_cb> potential;
2517 for(
auto& p : potential) {
2519 military::add_wargoal(state, w, n, p.target, p.cb, p.state_def, p.associated_tag, p.secondary_nation);
2529 static std::vector<dcon::cb_type_id> possibilities;
2530 possibilities.clear();
2532 auto free_infamy = state.defines.badboy_limit - state.world.nation_get_infamy(from);
2534 for(
auto c : state.world.in_cb_type) {
2535 auto bits = state.world.cb_type_get_type_bits(c);
2540 if(
military::cb_infamy(state, c) * state.defines.gw_justify_cb_badboy_impact > free_infamy)
2545 possibilities.push_back(c);
2548 if(!possibilities.empty()) {
2551 return dcon::cb_type_id{};
2558 return state.world.nation_get_ai_rival(from);
2560 return state.world.nation_get_ai_rival(from);
2562 static std::vector<dcon::nation_id> possibilities;
2563 possibilities.clear();
2565 for(
auto par : state.world.war_get_war_participant(w)) {
2566 if(par.get_is_attacker() != is_attacker) {
2567 if(state.world.get_nation_adjacency_by_nation_adjacency_pair(from, par.get_nation()))
2568 possibilities.push_back(par.get_nation().id);
2571 if(possibilities.empty()) {
2572 for(
auto par : state.world.war_get_war_participant(w)) {
2573 if(par.get_is_attacker() != is_attacker) {
2575 possibilities.push_back(par.get_nation().id);
2579 if(!possibilities.empty()) {
2582 return dcon::nation_id{};
2591 if(n == state.world.war_get_primary_attacker(w) || n == state.world.war_get_primary_defender(w)) {
2592 if(((rval >> 1) & 1) == 0) {
2598 auto jingoism_perc = totalpop > 0 ? state.world.nation_get_demographics(n,
demographics::to_key(state, state.culture_definitions.jingoism)) / totalpop : 0.0f;
2600 if(jingoism_perc < state.defines.wargoal_jingoism_requirement * state.defines.gw_wargoal_jingoism_requirement_mod)
2616 static std::vector<dcon::state_instance_id> target_states;
2618 static std::vector<possible_cb> result;
2621 if(!result.empty() && result[0].target) {
2622 military::add_wargoal(state, w, n, target, cb, result[0].state_def, result[0].associated_tag, result[0].secondary_nation);
2624 state.world.nation_get_infamy(n) +=
military::cb_infamy(state, cb) * state.defines.gw_justify_cb_badboy_impact;
2629 for(
auto w : state.world.in_war) {
2630 if(w.get_is_great()) {
2631 for(
auto par : w.get_war_participant()) {
2632 if(par.get_nation().get_is_player_controlled() ==
false) {
2641 if(
bool(state.defines.alice_surrender_on_cores_lost)) {
2642 auto i = state.world.nation_get_identity_from_identity_holder(n);
2643 auto cores = state.world.national_identity_get_core(i);
2644 bool has_owned_cores =
false;
2645 for(
auto c : cores) {
2646 if(c.get_province().get_nation_from_province_ownership() == n) {
2647 has_owned_cores =
true;
2648 }
if(c.get_province().get_nation_from_province_control() == n) {
2652 auto pc = state.world.nation_get_province_control(n);
2653 return has_owned_cores || pc.begin() == pc.end();
2659 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) {
2660 if(
auto off = state.world.nation_get_peace_offer_from_pending_peace_offer(from); off) {
2661 if(state.world.peace_offer_get_is_crisis_offer(off) ==
true || state.world.peace_offer_get_war_from_war_settlement(off))
2663 state.world.delete_peace_offer(off);
2668 auto pending = state.world.nation_get_peace_offer_from_pending_peace_offer(from);
2672 score_max = std::min(score_max, 100);
2673 int32_t current_value = 0;
2674 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
2676 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());
2677 if(current_value + goal_cost <= score_max) {
2678 current_value += goal_cost;
2679 state.world.force_create_peace_offer_item(pending, wg.get_wargoal().id);
2688 for(
auto w : state.world.in_war) {
2689 if((w.get_primary_attacker().get_is_player_controlled() ==
false || w.get_primary_defender().get_is_player_controlled() ==
false)
2690 && w.get_primary_attacker().get_owned_province_count() > 0
2691 && w.get_primary_defender().get_owned_province_count() > 0) {
2699 if(overall_score >= 0) {
2702 if(w.get_primary_attacker().get_is_player_controlled() ==
false) {
2703 if(defender_surrender || (overall_score >= 100 || (overall_score >= 50 && overall_score >= total_po_cost * 2))) {
2704 send_offer_up_to(w.get_primary_attacker(), w.get_primary_defender(), w,
true, int32_t(overall_score),
false);
2707 if(w.get_primary_defender().get_is_player_controlled() ==
false) {
2708 auto war_duration = state.current_date.value - state.world.war_get_start_date(w).value;
2709 if(war_duration >= 365) {
2710 float willingness_factor = float(war_duration - 365) * 10.f / 365.0f;
2711 if(defender_surrender || (overall_score > (total_po_cost - willingness_factor) && (-overall_score / 2 + total_po_cost - willingness_factor) < 0)) {
2712 send_offer_up_to(w.get_primary_attacker(), w.get_primary_defender(), w,
true, int32_t(total_po_cost),
false);
2717 }
else if(w.get_primary_defender().get_is_player_controlled() ==
false) {
2718 if(defender_surrender || (overall_score >= 100 || (overall_score >= 50 && overall_score >= total_po_cost * 2))) {
2719 send_offer_up_to(w.get_primary_defender(), w.get_primary_attacker(), w,
false, int32_t(overall_score),
true);
2726 if(w.get_primary_defender().get_is_player_controlled() ==
false) {
2727 if(attacker_surrender || (overall_score <= -100 || (overall_score <= -50 && overall_score <= -total_po_cost * 2))) {
2728 send_offer_up_to(w.get_primary_defender(), w.get_primary_attacker(), w,
false, int32_t(-overall_score),
false);
2731 if(w.get_primary_attacker().get_is_player_controlled() ==
false) {
2732 auto war_duration = state.current_date.value - state.world.war_get_start_date(w).value;
2733 if(war_duration >= 365) {
2734 float willingness_factor = float(war_duration - 365) * 10.f / 365.0f;
2735 if(attacker_surrender || (-overall_score > (total_po_cost - willingness_factor) && (overall_score / 2 + total_po_cost - willingness_factor) < 0)) {
2736 send_offer_up_to(w.get_primary_defender(), w.get_primary_attacker(), w,
false, int32_t(total_po_cost),
false);
2741 }
else if(w.get_primary_attacker().get_is_player_controlled() ==
false) {
2742 if(attacker_surrender || (overall_score <= -100 || (overall_score <= -50 && overall_score <= -total_po_cost * 2))) {
2743 send_offer_up_to(w.get_primary_attacker(), w.get_primary_defender(), w,
true, int32_t(-overall_score),
true);
2753 dcon::nation_id n, dcon::nation_id from,
2754 dcon::nation_id prime_attacker, dcon::nation_id prime_defender,
2755 float primary_warscore,
float scoreagainst_me,
2756 bool offer_from_attacker,
bool concession,
2757 int32_t overall_po_value, int32_t my_po_target,
2758 int32_t target_personal_po_value, int32_t potential_peace_score_against,
2759 int32_t my_side_against_target, int32_t my_side_peace_cost,
2760 int32_t war_duration,
bool contains_sq) {
2761 bool is_attacking = !offer_from_attacker;
2763 auto overall_score = primary_warscore;
2764 if(concession && overall_score <= -50.0f) {
2769 overall_po_value = -overall_po_value;
2771 if(overall_po_value < -100)
2774 auto personal_score_saved = target_personal_po_value - potential_peace_score_against;
2776 if((prime_attacker == n || prime_defender == n) && (prime_attacker == from || prime_defender == from)) {
2777 if(overall_score <= -50 && overall_score <= overall_po_value * 2)
2780 if(concession && my_side_peace_cost <= overall_po_value)
2782 if(war_duration < 365) {
2785 float willingness_factor = float(war_duration - 365) * 10.f / 365.0f;
2786 if(overall_score >= 0) {
2787 if(concession && ((overall_score * 2 - overall_po_value - willingness_factor) < 0))
2790 if((overall_score - willingness_factor) <= overall_po_value && (overall_score / 2 - overall_po_value - willingness_factor) < 0)
2794 }
else if((prime_attacker == n || prime_defender == n) && concession) {
2795 if(scoreagainst_me > 50)
2798 if(overall_score < 0.0f) {
2799 if(my_side_against_target - scoreagainst_me <= overall_po_value + personal_score_saved)
2802 if(my_side_against_target <= overall_po_value)
2810 if(scoreagainst_me > 50 && scoreagainst_me > -overall_po_value * 2)
2813 if(overall_score < 0.0f) {
2814 if(personal_score_saved > 0 && scoreagainst_me + personal_score_saved - my_po_target >= -overall_po_value)
2818 if(my_po_target > 0 && my_po_target >= overall_po_value)
2830 auto w = state.world.peace_offer_get_war_from_war_settlement(p);
2831 auto prime_attacker = state.world.war_get_primary_attacker(w);
2832 auto prime_defender = state.world.war_get_primary_defender(w);
2834 bool contains_sq =
false;
2838 overall_score = -overall_score;
2840 auto concession = state.world.peace_offer_get_is_concession(p);
2842 if(concession && overall_score <= -50.0f) {
2846 int32_t overall_po_value = 0;
2847 int32_t personal_po_value = 0;
2848 int32_t my_po_target = 0;
2849 for(
auto wg : state.world.peace_offer_get_peace_offer_item(p)) {
2850 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());
2851 overall_po_value += wg_value;
2856 if(wg.get_wargoal().get_target_nation() == n) {
2857 personal_po_value += wg_value;
2861 overall_po_value = -overall_po_value;
2863 if(overall_po_value < -100)
2866 int32_t potential_peace_score_against = 0;
2867 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
2868 if(wg.get_wargoal().get_target_nation() == n || wg.get_wargoal().get_added_by() == n) {
2869 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());
2871 if(wg.get_wargoal().get_target_nation() == n && (wg.get_wargoal().get_added_by() == from || from == prime_attacker || from == prime_defender)) {
2872 potential_peace_score_against += wg_value;
2874 if(wg.get_wargoal().get_added_by() == n && (wg.get_wargoal().get_target_nation() == from || from == prime_attacker || from == prime_defender)) {
2875 my_po_target += wg_value;
2879 auto personal_score_saved = personal_po_value - potential_peace_score_against;
2881 if((prime_attacker == n || prime_defender == n) && (prime_attacker == from || prime_defender == from)) {
2882 if(overall_score <= -50 && overall_score <= overall_po_value * 2)
2885 auto war_duration = state.current_date.value - state.world.war_get_start_date(w).value;
2888 if(war_duration < 365) {
2891 float willingness_factor = float(war_duration - 365) * 10.f / 365.0f;
2892 if(overall_score >= 0) {
2893 if(concession && ((overall_score * 2 - overall_po_value - willingness_factor) < 0))
2896 if((overall_score - willingness_factor) <= overall_po_value && (overall_score / 2 - overall_po_value - willingness_factor) < 0)
2900 }
else if((prime_attacker == n || prime_defender == n) && concession) {
2903 if(scoreagainst_me > 50)
2906 int32_t my_side_against_target = 0;
2907 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
2908 if(wg.get_wargoal().get_target_nation() == from) {
2909 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());
2911 my_side_against_target += wg_value;
2915 if(overall_score < 0.0f) {
2916 if(my_side_against_target - scoreagainst_me <= overall_po_value + personal_score_saved)
2919 if(my_side_against_target <= overall_po_value)
2928 if(scoreagainst_me > 50 && scoreagainst_me > -overall_po_value * 2)
2931 if(overall_score < 0.0f) {
2932 if(personal_score_saved > 0 && scoreagainst_me + personal_score_saved - my_po_target >= -overall_po_value)
2936 if(my_po_target > 0 && my_po_target >= overall_po_value)
2948 auto self_sup = state.world.nation_get_used_naval_supply_points(n);
2950 auto real_target = state.world.overlord_get_ruler(state.world.nation_get_overlord_as_subject(target));
2952 real_target = target;
2954 if(self_sup <= state.world.nation_get_used_naval_supply_points(real_target))
2957 if(self_sup <= state.world.nation_get_in_sphere_of(real_target).get_used_naval_supply_points())
2960 for(
auto a : state.world.nation_get_diplomatic_relation(real_target)) {
2961 if(!a.get_are_allied())
2963 auto other = a.get_related_nations(0) != real_target ? a.get_related_nations(0) : a.get_related_nations(1);
2964 if(self_sup <= other.get_used_naval_supply_points())
2972 auto targets = ve::vectorizable_buffer<dcon::nation_id, dcon::nation_id>(state.world.nation_size());
2973 concurrency::parallel_for(
uint32_t(0), state.world.nation_size(), [&](
uint32_t i) {
2974 dcon::nation_id n{ dcon::nation_id::value_base_t(i) };
2975 if(state.world.nation_get_owned_province_count(n) == 0)
2977 if(state.world.nation_get_is_at_war(n))
2979 if(state.world.nation_get_is_player_controlled(n))
2981 if(state.world.nation_get_military_score(n) == 0)
2983 if(
auto ol = state.world.nation_get_overlord_as_subject(n); state.world.overlord_get_ruler(ol))
2986 float best_difference = 2.0f;
2989 for(
auto target : state.world.in_nation) {
2990 auto real_target = target.get_overlord_as_subject().get_ruler() ? target.get_overlord_as_subject().get_ruler() : target;
2991 if(target == n || real_target == n)
2993 if(state.world.nation_get_owned_province_count(real_target) == 0)
2995 if(nations::are_allied(state, n, real_target))
2997 if(target.get_in_sphere_of() == n)
2999 if(military::has_truce_with(state, n, real_target))
3001 if(!military::can_use_cb_against(state, n, target))
3005 for(auto adj : state.world.nation_get_nation_adjacency(target)) {
3006 auto other = adj.get_connected_nations(0) != n ? adj.get_connected_nations(0) : adj.get_connected_nations(1);
3007 auto neighbor = other;
3008 if(neighbor.get_in_sphere_of() == n){
3009 auto path = province::make_safe_land_path(state, state.world.nation_get_capital(n), state.world.nation_get_capital(neighbor), n);
3013 auto str_difference = base_strength + estimate_additional_offensive_strength(state, n, real_target) - estimate_defensive_strength(state, real_target);
3014 if(str_difference > best_difference) {
3015 best_difference = str_difference;
3016 targets.set(n, target.id);
3021 if(!state.world.get_nation_adjacency_by_nation_adjacency_pair(n, target) && !
naval_supremacy(state, n, target))
3024 if(str_difference > best_difference) {
3025 best_difference = str_difference;
3026 targets.set(n, target.id);
3030 for(
auto adj : state.world.nation_get_nation_adjacency(n)) {
3031 auto other = adj.get_connected_nations(0) != n ? adj.get_connected_nations(0) : adj.get_connected_nations(1);
3032 auto real_target = other.get_overlord_as_subject().get_ruler() ? other.get_overlord_as_subject().get_ruler() : other;
3033 if(real_target == n)
3037 if(real_target.get_in_sphere_of() == n)
3039 if(state.world.nation_get_in_sphere_of(other) == n)
3045 if(!state.world.get_nation_adjacency_by_nation_adjacency_pair(n, other) && !naval_supremacy(state, n, other))
3047 auto str_difference = base_strength + estimate_additional_offensive_strength(state, n, real_target) - estimate_defensive_strength(state, real_target);
3048 if(str_difference > best_difference) {
3049 best_difference = str_difference;
3050 targets.set(n, other.id);
3053 if(
state.world.nation_get_central_ports(n) > 0) {
3058 dcon::nation_id
other{ dcon::nation_id::value_base_t(reduced_value) };
3059 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);
3060 if(other == n || real_target == n)
3062 if(
state.world.nation_get_owned_province_count(other) == 0 ||
state.world.nation_get_owned_province_count(real_target) == 0)
3064 if(
state.world.nation_get_central_ports(other) == 0 ||
state.world.nation_get_central_ports(real_target) == 0)
3068 if(real_target.get_in_sphere_of() == n)
3070 if(
state.world.nation_get_in_sphere_of(other) == n)
3076 if(!
state.world.get_nation_adjacency_by_nation_adjacency_pair(n, other) && !
naval_supremacy(state, n, other))
3079 if(str_difference > best_difference) {
3080 best_difference = str_difference;
3081 targets.set(n, other);
3086 for(
auto n :
state.world.in_nation) {
3087 if(
n.get_is_at_war() ==
false && targets.get(n)) {
3088 static std::vector<possible_cb> potential;
3090 if(!potential.empty()) {
3091 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));
3092 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);
3099 concurrency::parallel_for(
uint32_t(0), state.world.nation_size(), [&](
uint32_t i) {
3100 dcon::nation_id nid{ dcon::nation_id::value_base_t(i) };
3101 auto n = fatten(state.world, nid);
3102 if(n.get_is_player_controlled() || n.get_owned_province_count() == 0)
3113 float land_budget_ratio = 0.15f;
3114 float sea_budget_ratio = 0.05f;
3115 float education_budget_ratio = 0.30f;
3116 float investments_budget_ratio = 0.05f;
3117 float soldiers_budget_ratio = 0.40f;
3118 float construction_budget_ratio = 0.50f;
3119 float administration_budget_ratio = 0.15f;
3120 float overseas_maintenance_budget_ratio = 0.10f;
3122 if(n.get_is_at_war()) {
3123 land_budget_ratio = 2.f;
3124 sea_budget_ratio = 2.f;
3126 administration_budget_ratio *= 0.15f;
3127 education_budget_ratio *= 0.15f;
3128 overseas_maintenance_budget_ratio *= 0.15f;
3131 }
else if(n.get_ai_is_threatened()) {
3132 land_budget_ratio = 0.5f;
3133 sea_budget_ratio = 0.25f;
3135 administration_budget_ratio *= 0.75f;
3136 education_budget_ratio *= 0.75f;
3137 overseas_maintenance_budget_ratio *= 0.75f;
3144 float land_budget = land_budget_ratio * base_income;
3145 float naval_budget = sea_budget_ratio * base_income;
3146 float education_budget = education_budget_ratio * base_income;
3147 float construction_budget = construction_budget_ratio * base_income;
3148 float administration_budget = administration_budget_ratio * base_income;
3149 float soldiers_budget = soldiers_budget_ratio * base_income;
3150 float overseas_budget = overseas_maintenance_budget_ratio * base_income;
3155 ratio_land = std::clamp(ratio_land, 0.f, 100.f);
3156 ratio_naval = std::clamp(ratio_naval, 0.f, 100.f);
3157 n.set_land_spending(int8_t(ratio_land));
3158 n.set_naval_spending(int8_t(ratio_naval));
3162 ratio_construction = std::clamp(ratio_construction, 1.f, 100.f);
3163 n.set_construction_spending(int8_t(ratio_construction));
3172 float ratio_education = 100.f *
math::sqrt(education_budget / max_education_budget);
3173 ratio_education = std::clamp(ratio_education, 1.f, 100.f);
3174 n.set_education_spending(int8_t(ratio_education));
3176 if(n.get_is_civilized()) {
3177 float investment_budget = investments_budget_ratio * base_income;
3179 float investment_ratio = 100.f *
math::sqrt(investment_budget / max_investment_budget);
3180 investment_ratio = std::clamp(investment_ratio, 0.f, 100.f);
3181 n.set_domestic_investment_spending(int8_t(investment_ratio));
3183 n.set_domestic_investment_spending(int8_t(0));
3186 float soldiers_max_ratio = 100.f *
math::sqrt(soldiers_budget / max_soldiers_budget);
3187 soldiers_max_ratio = std::clamp(soldiers_max_ratio, 0.f, 100.f);
3189 float administration_max_ratio = 100.f *
math::sqrt(administration_budget / max_admin_budget);
3190 administration_max_ratio = std::clamp(administration_max_ratio, 0.f, 100.f);
3192 float overseas_max_ratio = std::clamp(100.f * overseas_budget / max_overseas_budget, 0.f, 100.f);
3194 n.set_tariffs(int8_t(0));
3200 auto rules = n.get_combined_issue_rules();
3203 int max_poor_tax = int(10.f + 70.f * (1.f - poor_militancy));
3204 int max_mid_tax = int(10.f + 80.f * (1.f - mid_militancy));
3205 int max_rich_tax = int(10.f + 90.f * (1.f - rich_militancy));
3206 int max_social = int(100.f * poor_militancy);
3209 bool enough_tax =
true;
3210 if(ratio_education < 50.f || ratio_construction < 50.f) {
3212 n.set_poor_tax(int8_t(std::clamp(n.get_poor_tax() + 2, 10, std::max(10, max_poor_tax))));
3213 n.set_middle_tax(int8_t(std::clamp(n.get_middle_tax() + 3, 10, std::max(10, max_mid_tax))));
3214 n.set_rich_tax(int8_t(std::clamp(n.get_rich_tax() + 5, 10, std::max(10, max_rich_tax))));
3217 if(n.get_spending_level() < 1.0f || n.get_last_treasury() >= n.get_stockpiles(
economy::money) || ratio_education < 50.f || ratio_construction < 50.f) {
3221 if(!n.get_ai_is_threatened()) {
3222 n.set_military_spending(int8_t(std::max(50, n.get_military_spending() - 5)));
3224 n.set_social_spending(int8_t(std::max(0, n.get_social_spending() - 2)));
3226 n.set_poor_tax(int8_t(std::clamp(n.get_poor_tax() + 2, 10, std::max(10, max_poor_tax))));
3227 n.set_middle_tax(int8_t(std::clamp(n.get_middle_tax() + 3, 10, std::max(10, max_mid_tax))));
3228 n.set_rich_tax(int8_t(std::clamp(n.get_rich_tax() + 5, 10, std::max(10, max_rich_tax))));
3229 }
else if(n.get_last_treasury() < n.get_stockpiles(
economy::money)) {
3233 if(n.get_ai_is_threatened()) {
3234 n.set_military_spending(int8_t(std::min(100, n.get_military_spending() + 10)));
3236 n.set_military_spending(int8_t(std::min(75, n.get_military_spending() + 10)));
3238 n.set_social_spending(int8_t(std::min(max_social, n.get_social_spending() + 2)));
3241 n.set_poor_tax(int8_t(std::clamp(n.get_poor_tax() - 2, 10, std::max(10, max_poor_tax))));
3242 n.set_middle_tax(int8_t(std::clamp(n.get_middle_tax() - 3, 10, std::max(10, max_mid_tax))));
3243 n.set_rich_tax(int8_t(std::clamp(n.get_rich_tax() - 5, 10, std::max(10, max_rich_tax))));
3247 int max_poor_tax = int(10.f + 90.f * (1.f - poor_militancy));
3248 int max_mid_tax = int(10.f + 90.f * (1.f - mid_militancy));
3249 int max_rich_tax = int(10.f + 40.f * (1.f - rich_militancy));
3250 int max_social = int(100.f * poor_militancy);
3253 bool enough_tax =
true;
3254 if(ratio_education < 50.f || ratio_construction < 50.f) {
3256 n.set_poor_tax(int8_t(std::clamp(n.get_poor_tax() + 5, 10, std::max(10, max_poor_tax))));
3257 n.set_middle_tax(int8_t(std::clamp(n.get_middle_tax() + 3, 10, std::max(10, max_mid_tax))));
3258 n.set_rich_tax(int8_t(std::clamp(n.get_rich_tax() + 2, 10, std::max(10, max_rich_tax))));
3262 if(n.get_spending_level() < 1.0f || n.get_last_treasury() >= n.get_stockpiles(
economy::money) || ratio_education < 50.f || ratio_construction < 50.f) {
3266 if(!n.get_ai_is_threatened()) {
3267 n.set_military_spending(int8_t(std::max(50, n.get_military_spending() - 5)));
3269 n.set_social_spending(int8_t(std::max(0, n.get_social_spending() - 2)));
3271 n.set_poor_tax(int8_t(std::clamp(n.get_poor_tax() + 5, 10, std::max(10, max_poor_tax))));
3272 n.set_middle_tax(int8_t(std::clamp(n.get_middle_tax() + 3, 10, std::max(10, max_mid_tax))));
3273 n.set_rich_tax(int8_t(std::clamp(n.get_rich_tax() + 2, 10, std::max(10, max_rich_tax))));
3274 }
else if(n.get_last_treasury() < n.get_stockpiles(
economy::money)) {
3278 if(n.get_ai_is_threatened()) {
3279 n.set_military_spending(int8_t(std::min(100, n.get_military_spending() + 10)));
3281 n.set_military_spending(int8_t(std::min(75, n.get_military_spending() + 10)));
3283 n.set_social_spending(int8_t(std::min(max_social, n.get_social_spending() + 2)));
3286 n.set_poor_tax(int8_t(std::clamp(n.get_poor_tax() - 5, 10, std::max(10, max_poor_tax))));
3287 n.set_middle_tax(int8_t(std::clamp(n.get_middle_tax() - 3, 10, std::max(10, max_mid_tax))));
3288 n.set_rich_tax(int8_t(std::clamp(n.get_rich_tax() - 2, 10, std::max(10, max_rich_tax))));
3293 n.set_administrative_spending(int8_t(std::min(int8_t(administration_max_ratio), n.get_administrative_spending())));
3294 n.set_administrative_spending(int8_t(administration_max_ratio));
3295 n.set_military_spending(int8_t(std::min(int8_t(soldiers_max_ratio), n.get_military_spending())));
3296 n.set_overseas_spending(int8_t(overseas_max_ratio));
3304 for(
auto ar : state.world.nation_get_army_control(n)) {
3305 ar.get_army().set_ai_activity(0);
3306 ar.get_army().set_ai_province(dcon::province_id{});
3308 for(
auto v : state.world.nation_get_navy_control(n)) {
3309 v.get_navy().set_ai_activity(0);
3315 return fat_id.get_controller_from_army_control().get_is_player_controlled()
3316 ? fat_id.get_is_ai_controlled()
3327 static std::vector<dcon::ship_id> to_delete;
3329 for(
auto n : state.world.in_nation) {
3330 if(n.get_is_player_controlled())
3333 for(
auto v : n.get_navy_control()) {
3334 if(!v.get_navy().get_battle_from_navy_battle_participation()) {
3335 for(
auto shp : v.get_navy().get_navy_membership()) {
3336 to_delete.push_back(shp.get_ship().id);
3340 }
else if(n.get_is_at_war() ==
false) {
3341 dcon::unit_type_id best_transport;
3342 dcon::unit_type_id best_light;
3343 dcon::unit_type_id best_big;
3344 for(
uint32_t i = 2; i < state.military_definitions.unit_base_definitions.size(); ++i) {
3345 dcon::unit_type_id j{ dcon::unit_type_id::value_base_t(i) };
3346 if(!n.get_active_unit(j) && !state.military_definitions.unit_base_definitions[j].active)
3349 if(!best_transport || state.military_definitions.unit_base_definitions[best_transport].defence_or_hull < state.military_definitions.unit_base_definitions[j].defence_or_hull) {
3353 if(!best_light || state.military_definitions.unit_base_definitions[best_light].defence_or_hull < state.military_definitions.unit_base_definitions[j].defence_or_hull) {
3357 if(!best_big || state.military_definitions.unit_base_definitions[best_big].defence_or_hull < state.military_definitions.unit_base_definitions[j].defence_or_hull) {
3362 for(
auto v : n.get_navy_control()) {
3363 if(!v.get_navy().get_battle_from_navy_battle_participation()) {
3364 auto trange = v.get_navy().get_army_transport();
3367 for(
auto shp : v.get_navy().get_navy_membership()) {
3368 auto type = shp.get_ship().get_type();
3371 if(best_transport && type != best_transport)
3372 to_delete.push_back(shp.get_ship().id);
3374 if(best_light && type != best_light)
3375 to_delete.push_back(shp.get_ship().id);
3377 if(best_big && type != best_big)
3378 to_delete.push_back(shp.get_ship().id);
3385 for(
auto s : to_delete) {
3386 state.world.delete_ship(s);
3391 for(
auto n : state.world.in_nation) {
3392 if(!n.get_is_player_controlled() && n.get_province_naval_construction().begin() == n.get_province_naval_construction().end()) {
3393 auto disarm = n.get_disarmed_until();
3394 if(disarm && state.current_date < disarm)
3397 dcon::unit_type_id best_transport;
3398 dcon::unit_type_id best_light;
3399 dcon::unit_type_id best_big;
3401 for(
uint32_t i = 2; i < state.military_definitions.unit_base_definitions.size(); ++i) {
3402 dcon::unit_type_id j{ dcon::unit_type_id::value_base_t(i) };
3403 if(!n.get_active_unit(j) && !state.military_definitions.unit_base_definitions[j].active)
3407 if(!best_transport || state.military_definitions.unit_base_definitions[best_transport].defence_or_hull < state.military_definitions.unit_base_definitions[j].defence_or_hull) {
3411 if(!best_light || state.military_definitions.unit_base_definitions[best_light].defence_or_hull < state.military_definitions.unit_base_definitions[j].defence_or_hull) {
3415 if(!best_big || state.military_definitions.unit_base_definitions[best_big].defence_or_hull < state.military_definitions.unit_base_definitions[j].defence_or_hull) {
3421 int32_t num_transports = 0;
3422 int32_t fleet_cap_in_transports = 0;
3423 int32_t fleet_cap_in_small = 0;
3424 int32_t fleet_cap_in_big = 0;
3426 for(
auto v : n.get_navy_control()) {
3427 for(
auto s : v.get_navy().get_navy_membership()) {
3428 auto type = s.get_ship().get_type();
3431 fleet_cap_in_transports += state.military_definitions.unit_base_definitions[type].supply_consumption_score;
3433 fleet_cap_in_big += state.military_definitions.unit_base_definitions[type].supply_consumption_score;
3435 fleet_cap_in_small += state.military_definitions.unit_base_definitions[type].supply_consumption_score;
3440 static std::vector<dcon::province_id> owned_ports;
3441 owned_ports.clear();
3442 for(
auto p : n.get_province_ownership()) {
3443 if(p.get_province().get_is_coast() && p.get_province().get_nation_from_province_control() == n) {
3444 owned_ports.push_back(p.get_province().id);
3447 auto cap = n.get_capital().id;
3448 std::sort(owned_ports.begin(), owned_ports.end(), [&](dcon::province_id a, dcon::province_id b) {
3449 auto a_dist = province::sorting_distance(state, a, cap);
3450 auto b_dist = province::sorting_distance(state, b, cap);
3451 if(a_dist != b_dist)
3452 return a_dist < b_dist;
3454 return a.index() < b.index();
3457 int32_t constructing_fleet_cap = 0;
3458 if(best_transport) {
3459 if(fleet_cap_in_transports * 3 < n.get_naval_supply_points()) {
3460 auto overseas_allowed = state.military_definitions.unit_base_definitions[best_transport].can_build_overseas;
3461 auto level_req = state.military_definitions.unit_base_definitions[best_transport].min_port_level;
3462 auto supply_pts = state.military_definitions.unit_base_definitions[best_transport].supply_consumption_score;
3464 for(
uint32_t j = 0; j < owned_ports.size() && (fleet_cap_in_transports + constructing_fleet_cap) * 3 < n.get_naval_supply_points(); ++j) {
3468 auto c = fatten(state.world, state.world.try_create_province_naval_construction(owned_ports[j], n));
3469 c.set_type(best_transport);
3470 constructing_fleet_cap += supply_pts;
3473 }
else if(num_transports < 10) {
3474 auto overseas_allowed = state.military_definitions.unit_base_definitions[best_transport].can_build_overseas;
3475 auto level_req = state.military_definitions.unit_base_definitions[best_transport].min_port_level;
3476 auto supply_pts = state.military_definitions.unit_base_definitions[best_transport].supply_consumption_score;
3478 for(
uint32_t j = 0; j < owned_ports.size() && num_transports < 10; ++j) {
3482 auto c = fatten(state.world, state.world.try_create_province_naval_construction(owned_ports[j], n));
3483 c.set_type(best_transport);
3485 constructing_fleet_cap += supply_pts;
3491 int32_t used_points = n.get_used_naval_supply_points();
3492 auto rem_free = n.get_naval_supply_points() - (fleet_cap_in_transports + fleet_cap_in_small + fleet_cap_in_big + constructing_fleet_cap);
3493 fleet_cap_in_small = std::max(fleet_cap_in_small, 1);
3494 fleet_cap_in_big = std::max(fleet_cap_in_big, 1);
3496 auto free_big_points = best_light ? rem_free * fleet_cap_in_small / (fleet_cap_in_small + fleet_cap_in_big) : rem_free;
3497 auto free_small_points = best_big ? rem_free * fleet_cap_in_big / (fleet_cap_in_small + fleet_cap_in_big) : rem_free;
3500 auto overseas_allowed = state.military_definitions.unit_base_definitions[best_light].can_build_overseas;
3501 auto level_req = state.military_definitions.unit_base_definitions[best_light].min_port_level;
3502 auto supply_pts = state.military_definitions.unit_base_definitions[best_light].supply_consumption_score;
3504 for(
uint32_t j = 0; j < owned_ports.size() && supply_pts <= free_small_points; ++j) {
3508 auto c = fatten(state.world, state.world.try_create_province_naval_construction(owned_ports[j], n));
3509 c.set_type(best_light);
3510 free_small_points -= supply_pts;
3515 auto overseas_allowed = state.military_definitions.unit_base_definitions[best_big].can_build_overseas;
3516 auto level_req = state.military_definitions.unit_base_definitions[best_big].min_port_level;
3517 auto supply_pts = state.military_definitions.unit_base_definitions[best_big].supply_consumption_score;
3519 for(
uint32_t j = 0; j < owned_ports.size() && supply_pts <= free_big_points; ++j) {
3523 auto c = fatten(state.world, state.world.try_create_province_naval_construction(owned_ports[j], n));
3524 c.set_type(best_big);
3525 free_big_points -= supply_pts;
3534 auto cap = state.world.nation_get_capital(n);
3535 int32_t max_level = -1;
3536 dcon::province_id result;
3537 float current_distance = 1.0f;
3538 for(
auto p : state.world.nation_get_province_ownership(n)) {
3539 if(p.get_province().get_is_coast() && p.get_province().get_nation_from_province_control() == n) {
3542 result = p.get_province();
3546 result = p.get_province();
3554 for(
auto n : state.world.in_nation) {
3555 if(!n.get_is_player_controlled() && n.get_owned_province_count() > 0) {
3579 for(
auto shp : state.world.navy_get_navy_membership(n)) {
3580 if(shp.get_ship().get_strength() < 0.5f)
3589 for(
auto par : state.world.nation_get_war_participant(n)) {
3590 for(
auto other : par.get_war().get_war_participant()) {
3591 if(other.get_is_attacker() != par.get_is_attacker()) {
3592 if(other.get_nation().get_used_naval_supply_points() > state.world.nation_get_used_naval_supply_points(n))
3601 auto v = fatten(state.world, n);
3602 auto home_port = v.get_controller_from_navy_control().get_ai_home_port();
3603 if(v.get_location_from_navy_location() == home_port) {
3604 v.set_ai_activity(
uint8_t(at_base));
3605 }
else if(!home_port) {
3606 v.set_ai_activity(
uint8_t(fleet_activity::unspecified));
3607 }
else if(
auto naval_path =
province::make_naval_path(state, v.get_location_from_navy_location(), home_port); naval_path.size() > 0) {
3608 auto new_size =
uint32_t(naval_path.size());
3609 auto existing_path = v.get_path();
3610 existing_path.resize(new_size);
3612 for(
uint32_t i = 0; i < new_size; ++i) {
3613 existing_path[i] = naval_path[i];
3616 v.set_ai_activity(
uint8_t(moving_status));
3618 v.set_ai_activity(
uint8_t(fleet_activity::unspecified));
3623 dcon::province_id result;
3624 float closest = 0.0f;
3625 for(
auto par : state.world.nation_get_war_participant(n)) {
3626 for(
auto other : par.get_war().get_war_participant()) {
3627 if(other.get_is_attacker() != par.get_is_attacker()) {
3628 for(
auto nv : other.get_nation().get_navy_control()) {
3629 auto loc = nv.get_navy().get_location_from_navy_location();
3631 if(!result || dist < closest) {
3632 if(loc.id.index() < state.province_definitions.first_sea_province.index()) {
3633 result = loc.get_port_to();
3648 auto existing_path = state.world.navy_get_path(for_navy);
3650 if(path.size() > 0) {
3652 existing_path.resize(new_size);
3653 for(
uint32_t i = new_size; i-- > 0;) {
3654 assert(path[path.size() - 1 - i]);
3655 existing_path[new_size - 1 - i] = path[path.size() - 1 - i];
3658 state.world.navy_set_ai_activity(for_navy,
uint8_t(fleet_activity::attacking));
3669 auto transported_armies = state.world.navy_get_army_transport(n);
3670 auto location = state.world.navy_get_location_from_navy_location(n);
3673 for(
auto ar : transported_armies) {
3674 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());
3675 if(path.size() > 0) {
3676 auto existing_path = ar.get_army().get_path();
3677 auto new_size =
uint32_t(path.size());
3678 existing_path.resize(new_size);
3680 for(
uint32_t i = 0; i < new_size; ++i) {
3682 existing_path[i] = path[i];
3685 ar.get_army().set_dig_in(0);
3686 auto activity =
army_activity(ar.get_army().get_ai_activity());
3687 if(activity == army_activity::transport_guard) {
3688 ar.get_army().set_ai_activity(
uint8_t(army_activity::on_guard));
3689 }
else if(activity == army_activity::transport_attack) {
3690 ar.get_army().set_ai_activity(
uint8_t(army_activity::attack_gathered));
3695 state.world.navy_set_ai_activity(n,
uint8_t(fleet_activity::unloading));
3699 auto merge_target = [&]() {
3700 dcon::navy_id largest;
3701 int32_t largest_size = 0;
3702 for(
auto on : state.world.province_get_navy_location(p)) {
3703 if(on.get_navy() != n && on.get_navy().get_controller_from_navy_control() == owner) {
3704 auto other_mem = on.get_navy().get_navy_membership();
3705 if(
auto sz = int32_t(other_mem.end() - other_mem.begin()); sz > largest_size) {
3706 largest = on.get_navy().id;
3718 auto regs = state.world.navy_get_navy_membership(n);
3719 while(regs.begin() != regs.end()) {
3720 auto reg = (*regs.begin()).get_ship();
3721 reg.set_navy_from_navy_membership(merge_target);
3724 auto transported = state.world.navy_get_army_transport(n);
3725 while(transported.begin() != transported.end()) {
3726 auto arm = (*transported.begin()).get_army();
3727 arm.set_navy_from_army_transport(merge_target);
3733 for(
auto n : state.world.in_navy) {
3734 if(n.get_battle_from_navy_battle_participation())
3736 if(n.get_arrival_time())
3739 auto owner = n.get_controller_from_navy_control();
3741 if(!owner || owner.get_is_player_controlled() || owner.get_owned_province_count() == 0)
3744 auto home_port = state.world.nation_get_ai_home_port(owner);
3748 auto location = state.world.navy_get_location_from_navy_location(n);
3749 auto activity =
fleet_activity(state.world.navy_get_ai_activity(n));
3752 case fleet_activity::unspecified:
3753 if(location == home_port) {
3755 state.world.navy_set_ai_activity(n,
uint8_t(fleet_activity::idle));
3756 }
else if(!home_port) {
3763 case fleet_activity::boarding:
3765 bool all_loaded =
true;
3766 for(
auto ar : state.world.nation_get_army_control(owner)) {
3767 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)) {
3768 if(ar.get_army().get_navy_from_army_transport() != n)
3774 auto transporting_range = n.get_army_transport();
3775 if(transporting_range.begin() == transporting_range.end()) {
3778 auto transported_dest = (*(transporting_range.begin())).get_army().get_ai_province();
3781 if(transported_dest.get_is_coast()) {
3782 auto target_prov = transported_dest.id;
3784 target_prov = state.world.province_get_port_to(target_prov);
3788 auto existing_path = n.get_path();
3789 auto new_size =
uint32_t(naval_path.size());
3790 existing_path.resize(new_size);
3792 for(
uint32_t k = 0; k < new_size; ++k) {
3793 existing_path[k] = naval_path[k];
3797 n.set_ai_activity(
uint8_t(fleet_activity::transporting));
3806 auto target_prov = path.front();
3808 target_prov = state.world.province_get_port_to(target_prov);
3812 auto existing_path = n.get_path();
3813 auto new_size =
uint32_t(naval_path.size());
3814 existing_path.resize(new_size);
3816 for(
uint32_t k = 0; k < new_size; ++k) {
3817 existing_path[k] = naval_path[k];
3821 n.set_ai_activity(
uint8_t(fleet_activity::transporting));
3831 case fleet_activity::transporting:
3834 case fleet_activity::failed_transport:
3835 if(location == home_port) {
3837 state.world.navy_set_ai_activity(n,
uint8_t(fleet_activity::idle));
3838 }
else if(home_port) {
3839 auto existing_path = state.world.navy_get_path(n);
3841 if(path.size() > 0) {
3842 auto new_size =
uint32_t(path.size());
3843 existing_path.resize(new_size);
3845 for(
uint32_t i = 0; i < new_size; ++i) {
3847 existing_path[i] = path[i];
3853 case fleet_activity::returning_to_base:
3854 if(location == home_port) {
3856 state.world.navy_set_ai_activity(n,
uint8_t(fleet_activity::idle));
3861 case fleet_activity::attacking:
3862 if(state.world.nation_get_is_at_war(owner) ==
false) {
3874 case fleet_activity::merging:
3875 if(location == home_port) {
3877 state.world.navy_set_ai_activity(n,
uint8_t(fleet_activity::idle));
3882 case fleet_activity::idle:
3883 if(location != home_port) {
3884 state.world.navy_set_ai_activity(n,
uint8_t(fleet_activity::unspecified));
3885 }
else if(owner.get_is_at_war()) {
3887 bool valid_attacker =
true;
3888 auto self_ships = state.world.navy_get_navy_membership(n);
3889 int32_t self_sz = int32_t(self_ships.end() - self_ships.begin());
3890 for(
auto o : owner.get_navy_control()) {
3891 if(o.get_navy() != n) {
3892 if(o.get_navy().get_ai_activity() ==
uint8_t(fleet_activity::attacking)) {
3893 valid_attacker =
false;
3896 auto orange = o.get_navy().get_navy_membership();
3897 if(int32_t(orange.end() - orange.begin()) >= self_sz) {
3898 valid_attacker =
false;
3904 set_fleet_target(state, owner, state.world.navy_get_location_from_navy_location(n), n);
3909 case fleet_activity::unloading:
3913 auto transporting = state.world.navy_get_army_transport(n);
3915 if(ar.get_army().get_path().size() != 0) {
3922 state.world.navy_set_ai_activity(n,
uint8_t(fleet_activity::unspecified));
3925 state.world.navy_set_ai_activity(n,
uint8_t(fleet_activity::failed_transport));
3952 std::vector<classified_province> provinces;
3953 provinces.reserve(state.world.province_size());
3955 auto cap = state.world.nation_get_capital(n);
3957 for(
auto c : state.world.nation_get_province_control(n)) {
3958 province_class cls = c.get_province().get_is_coast() ? province_class::coast : province_class::interior;
3959 if(c.get_province() == cap)
3960 cls = province_class::border;
3962 for(
auto padj : c.get_province().get_province_adjacency()) {
3963 auto other = padj.get_connected_provinces(0) == c.get_province() ? padj.get_connected_provinces(1) : padj.get_connected_provinces(0);
3964 auto n_controller = other.get_nation_from_province_control();
3965 auto ovr = n_controller.get_overlord_as_subject().get_ruler();
3967 if(n_controller == n) {
3969 }
else if(!n_controller && !other.get_rebel_faction_from_province_rebel_control()) {
3971 }
else if(other.get_rebel_faction_from_province_rebel_control()) {
3972 cls = province_class::hostile_border;
3975 cls = province_class::hostile_border;
3979 if(
uint8_t(cls) <
uint8_t(province_class::low_priority_border)) {
3980 cls = province_class::low_priority_border;
3986 bool is_threat =
false;
3988 is_threat |= n_controller.get_ai_rival() == n;
3989 is_threat |= state.world.nation_get_ai_rival(n) == n_controller.id;
3992 is_threat |= ovr.get_ai_rival() == n;
3993 is_threat |= state.world.nation_get_ai_rival(n) == ovr.id;
3995 is_threat |= ovr.get_constructing_cb_target() == n;
3996 for(
auto cb : ovr.get_available_cbs())
3997 is_threat |= cb.target == n;
3999 is_threat |= n_controller.get_constructing_cb_target() == n;
4000 for(
auto cb : n_controller.get_available_cbs())
4001 is_threat |= cb.target == n;
4006 cls = province_class::threat_border;
4010 cls = province_class::border;
4020 return uint8_t(a.c) > uint8_t(b.c);
4024 if(adist != bdist) {
4025 return adist < bdist;
4027 return a.
id.index() < b.
id.index();
4031 std::vector<dcon::army_id> guards_list;
4032 guards_list.reserve(state.world.army_size());
4033 for(
auto a : state.world.nation_get_army_control(n)) {
4034 if(a.get_army().get_ai_activity() ==
uint8_t(army_activity::on_guard)) {
4035 guards_list.push_back(a.get_army().id);
4042 for(
uint8_t stage =
uint8_t(province_class::count); stage-- > 0 && !guards_list.empty(); ) {
4043 uint32_t start_of_stage = end_of_stage;
4045 for(; end_of_stage <
provinces.size(); ++end_of_stage) {
4046 if(
uint8_t(provinces[end_of_stage].c) != stage)
4051 bool guard_assigned =
false;
4053 guard_assigned =
false;
4054 for(
uint32_t j = start_of_stage; j < end_of_stage && !guards_list.empty(); ++j) {
4056 auto p_region =
state.world.province_get_connected_region_id(provinces[j].
id);
4058 bool p_region_is_coastal =
state.province_definitions.connected_region_is_coastal[p_region - 1];
4062 dcon::army_id nearest;
4063 float nearest_distance = 1.0f;
4065 auto guard_loc =
state.world.army_get_location_from_army_location(guards_list[k]);
4085 nearest_distance =
d;
4086 nearest = guards_list[k];
4092 state.world.army_set_ai_province(nearest, p);
4093 guards_list[nearest_index] = guards_list.back();
4094 guards_list.pop_back();
4096 guard_assigned =
true;
4101 ++full_loops_through;
4102 }
while(guard_assigned);
4109 dcon::navy_id transport_fleet;
4111 for(
auto v : state.world.nation_get_navy_control(controller)) {
4112 if(v.get_navy().get_battle_from_navy_battle_participation())
4114 auto members = v.get_navy().get_navy_membership();
4116 auto tsize = int32_t(members.end() - members.begin());
4117 if(tsize <= n_size || tsize <= 1)
4121 transport_fleet = dcon::navy_id{};
4124 if(activity == fleet_activity::attacking || activity == fleet_activity::idle || activity == fleet_activity::returning_to_base) {
4125 auto in_transport = v.get_navy().get_army_transport();
4126 if(in_transport.begin() == in_transport.end()) {
4127 transport_fleet = v.get_navy();
4132 return transport_fleet;
4136 std::vector<dcon::army_id> require_transport;
4137 require_transport.reserve(state.world.army_size());
4139 for(
auto ar : state.world.in_army) {
4140 if(ar.get_ai_activity() ==
uint8_t(army_activity::on_guard)
4141 && ar.get_ai_province()
4142 && ar.get_ai_province() != ar.get_location_from_army_location()
4143 && ar.get_controller_from_army_control()
4145 && !ar.get_arrival_time()
4146 && !ar.get_battle_from_army_battle_participation()
4147 && !ar.get_navy_from_army_transport()) {
4150 if(path.size() > 0) {
4151 auto existing_path = ar.get_path();
4152 auto new_size =
uint32_t(path.size());
4153 existing_path.resize(new_size);
4155 for(
uint32_t i = 0; i < new_size; ++i) {
4157 existing_path[i] = path[i];
4163 if(!ar.get_controller_from_army_control().get_is_player_controlled())
4164 require_transport.push_back(ar.id);
4169 for(
uint32_t i = 0; i < require_transport.size(); ++i) {
4170 auto coastal_target_prov = state.world.army_get_location_from_army_location(require_transport[i]);
4171 auto controller = state.world.army_get_controller_from_army_control(require_transport[i]);
4175 auto regs = state.world.army_get_army_membership(require_transport[i]);
4178 tcap -= int32_t(regs.end() - regs.begin());
4180 if(tcap < 0 || (state.world.nation_get_is_at_war(controller) && !
naval_advantage(state, controller))) {
4182 if(state.world.army_get_controller_from_army_control(require_transport[j]) == controller) {
4183 state.world.army_set_ai_province(require_transport[j], dcon::province_id{});
4184 require_transport[j] = require_transport.back();
4185 require_transport.pop_back();
4188 state.world.army_set_ai_province(require_transport[i], dcon::province_id{});
4192 if(!state.world.province_get_is_coast(coastal_target_prov)) {
4193 auto path = state.world.army_get_black_flag(require_transport[i])
4197 state.world.army_set_ai_province(require_transport[i], dcon::province_id{});
4200 coastal_target_prov = path.front();
4202 auto existing_path = state.world.army_get_path(require_transport[i]);
4203 auto new_size =
uint32_t(path.size());
4204 existing_path.resize(new_size);
4206 for(
uint32_t k = 0; k < new_size; ++k) {
4208 existing_path[k] = path[k];
4210 state.world.army_set_arrival_time(require_transport[i],
military::arrival_time_to(state, require_transport[i], path.back()));
4211 state.world.army_set_dig_in(require_transport[i], 0);
4212 state.world.army_set_dig_in(require_transport[i], 0);
4218 if(fleet_destination == state.world.navy_get_location_from_navy_location(transport_fleet)) {
4219 state.world.navy_get_path(transport_fleet).clear();
4220 state.world.navy_set_arrival_time(transport_fleet,
sys::date{});
4221 state.world.navy_set_ai_activity(transport_fleet,
uint8_t(fleet_activity::boarding));
4222 }
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()) {
4225 auto existing_path = state.world.navy_get_path(transport_fleet);
4226 auto new_size =
uint32_t(fleet_path.size());
4227 existing_path.resize(new_size);
4229 for(
uint32_t k = 0; k < new_size; ++k) {
4231 existing_path[k] = fleet_path[k];
4233 state.world.navy_set_arrival_time(transport_fleet,
military::arrival_time_to(state, transport_fleet, fleet_path.back()));
4234 state.world.navy_set_ai_activity(transport_fleet,
uint8_t(fleet_activity::boarding));
4238 state.world.army_set_ai_activity(require_transport[i],
uint8_t(army_activity::transport_guard));
4240 auto destination_region = state.world.province_get_connected_region_id(state.world.army_get_ai_province(require_transport[i]));
4244 if(state.world.army_get_controller_from_army_control(require_transport[j]) == controller) {
4245 auto jregs = state.world.army_get_army_membership(require_transport[j]);
4246 if(tcap >= (jregs.end() - jregs.begin())) {
4247 if(state.world.province_get_connected_region_id(state.world.army_get_ai_province(require_transport[j])) != destination_region)
4250 if(state.world.army_get_location_from_army_location(require_transport[j]) == coastal_target_prov) {
4251 state.world.army_set_ai_activity(require_transport[i],
uint8_t(army_activity::transport_guard));
4252 tcap -= int32_t(jregs.end() - jregs.begin());
4254 auto jpath = state.world.army_get_black_flag(require_transport[j])
4255 ?
province::make_land_path(state, state.world.army_get_location_from_army_location(require_transport[j]), coastal_target_prov, controller, require_transport[j])
4257 if(!jpath.empty()) {
4258 auto existing_path = state.world.army_get_path(require_transport[j]);
4259 auto new_size =
uint32_t(jpath.size());
4260 existing_path.resize(new_size);
4262 for(
uint32_t k = 0; k < new_size; ++k) {
4264 existing_path[k] = jpath[k];
4266 state.world.army_set_arrival_time(require_transport[j],
military::arrival_time_to(state, require_transport[j], jpath.back()));
4267 state.world.army_set_dig_in(require_transport[j], 0);
4268 state.world.army_set_ai_activity(require_transport[i],
uint8_t(army_activity::transport_guard));
4269 tcap -= int32_t(jregs.end() - jregs.begin());
4274 require_transport[j] = require_transport.back();
4275 require_transport.pop_back();
4284 for(
auto ar : state.world.in_army) {
4285 if(ar.get_battle_from_army_battle_participation())
4287 if(ar.get_navy_from_army_transport())
4289 if(ar.get_arrival_time())
4292 if(ar.get_ai_activity() ==
uint8_t(army_activity::transport_guard) || ar.get_ai_activity() ==
uint8_t(army_activity::transport_attack)) {
4293 auto controller = ar.get_controller_from_army_control();
4294 dcon::navy_id transports;
4295 for(
auto v : controller.get_navy_control()) {
4296 if(v.get_navy().get_ai_activity() ==
uint8_t(fleet_activity::boarding)) {
4297 transports = v.get_navy();
4301 ar.set_ai_activity(
uint8_t(army_activity::on_guard));
4302 ar.set_ai_province(dcon::province_id{});
4305 if(state.world.navy_get_arrival_time(transports) || state.world.navy_get_battle_from_navy_battle_participation(transports))
4308 auto army_location = ar.get_location_from_army_location();
4309 auto transport_location = state.world.navy_get_location_from_navy_location(transports);
4310 if(transport_location == army_location) {
4311 ar.set_navy_from_army_transport(transports);
4312 ar.set_black_flag(
false);
4313 }
else if(army_location.get_port_to() == transport_location) {
4314 auto existing_path = ar.get_path();
4315 existing_path.resize(1);
4316 assert(transport_location);
4317 existing_path[0] = transport_location;
4321 ar.set_ai_activity(
uint8_t(army_activity::on_guard));
4322 ar.set_ai_province(dcon::province_id{});
4329 dcon::regiment_id sample_reg;
4330 auto regs = state.world.army_get_army_membership(a);
4331 if(regs.begin() != regs.end()) {
4332 sample_reg = (*regs.begin()).get_regiment().id;
4338 auto spending_level = state.world.nation_get_effective_land_spending(n);
4339 auto max_org = 0.25f + 0.75f * spending_level;
4341 return state.world.regiment_get_org(sample_reg) > 0.7f * max_org;
4345 for(
auto ar : state.world.nation_get_army_control(n)) {
4347 if(ar.get_army().get_battle_from_army_battle_participation()
4348 || ar.get_army().get_navy_from_army_transport()
4349 || ar.get_army().get_black_flag()
4350 || ar.get_army().get_arrival_time()
4351 || (activity != army_activity::on_guard && activity != army_activity::attacking && activity != army_activity::attack_gathered && activity != army_activity::attack_transport)
4357 auto location = ar.get_army().get_location_from_army_location();
4362 if(sdist > state.defines.alice_ai_gather_radius)
4366 if(!jpath.empty()) {
4368 auto existing_path = ar.get_army().get_path();
4369 auto new_size =
uint32_t(jpath.size());
4370 existing_path.resize(new_size * 2);
4372 for(
uint32_t k = 0; k < new_size; ++k) {
4374 existing_path[new_size + k] = jpath[k];
4376 for(
uint32_t k = 1; k < new_size; ++k) {
4378 existing_path[new_size - k] = jpath[k];
4381 existing_path[0] = location;
4383 ar.get_army().set_dig_in(0);
4390 auto regs = state.world.army_get_army_membership(a);
4391 if(regs.begin() == regs.end())
4395 float total_str = 0.f;
4396 float str_art = 0.f;
4397 float str_inf = 0.f;
4398 float str_cav = 0.f;
4399 for(
const auto reg : regs) {
4400 float str = reg.get_regiment().get_strength() * reg.get_regiment().get_org();
4401 if(
auto utid = reg.get_regiment().get_type(); utid) {
4402 switch(state.military_definitions.unit_base_definitions[utid].type) {
4419 if(total_str == 0.f)
4423 float min_cav = std::min(str_cav, str_inf * (1.f / 4.f));
4424 float scale = 1.f -
math::sin(std::abs(std::min(str_art / total_str, str_inf / total_str) - (4.f * min_cav / total_str)));
4425 return total_str * scale;
4429 float scale = state.world.army_get_controller_from_army_control(a) ? 1.f : 0.5f;
4431 if(
auto gen = state.world.army_get_general_from_army_leadership(a); gen) {
4432 auto n = state.world.army_get_controller_from_army_control(a);
4434 n = state.world.national_identity_get_nation_from_identity_holder(state.national_definitions.rebel_id);
4435 auto back = state.world.leader_get_background(gen);
4436 auto pers = state.world.leader_get_personality(gen);
4437 float morale = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::org_regain)
4438 + state.world.leader_trait_get_morale(back)
4439 + state.world.leader_trait_get_morale(pers) + 1.0f;
4440 float org = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::land_organisation)
4441 + state.world.leader_trait_get_organisation(back)
4442 + state.world.leader_trait_get_organisation(pers) + 1.0f;
4443 float def = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::land_defense_modifier)
4444 + state.world.leader_trait_get_defense(back)
4445 + state.world.leader_trait_get_defense(pers) + 1.0f;
4446 scale += def * morale * org;
4447 scale += state.world.nation_get_has_gas_defense(n) ? 10.f : 0.f;
4450 float terrain_bonus = state.world.province_get_modifier_values(state.world.army_get_location_from_army_location(a), sys::provincial_mod_offsets::defense);
4451 scale += terrain_bonus;
4453 scale += defender_fort;
4456 return std::max(0.1f, strength * scale);
4460 float scale = state.world.army_get_controller_from_army_control(a) ? 1.f : 0.5f;
4462 if(
auto gen = state.world.army_get_general_from_army_leadership(a); gen) {
4463 auto n = state.world.army_get_controller_from_army_control(a);
4465 n = state.world.national_identity_get_nation_from_identity_holder(state.national_definitions.rebel_id);
4466 auto back = state.world.leader_get_background(gen);
4467 auto pers = state.world.leader_get_personality(gen);
4468 float morale = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::org_regain)
4469 + state.world.leader_trait_get_morale(back)
4470 + state.world.leader_trait_get_morale(pers) + 1.0f;
4471 float org = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::land_organisation)
4472 + state.world.leader_trait_get_organisation(back)
4473 + state.world.leader_trait_get_organisation(pers) + 1.0f;
4474 float atk = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::land_attack_modifier)
4475 + state.world.leader_trait_get_attack(back)
4476 + state.world.leader_trait_get_attack(pers) + 1.0f;
4477 scale += atk * morale * org;
4478 scale += state.world.nation_get_has_gas_attack(n) ? 10.f : 0.f;
4482 return std::max(0.1f, strength * scale);
4486 float strength_total = 0.f;
4487 if(state.world.nation_get_is_at_war(by)) {
4488 for(
auto ar : state.world.in_army) {
4489 if(ar.get_is_retreating()
4490 || ar.get_battle_from_army_battle_participation()
4491 || ar.get_controller_from_army_control() == by)
4493 auto loc = ar.get_location_from_army_location();
4495 if(sdist < state.defines.alice_ai_threat_radius) {
4496 auto other_nation = ar.get_controller_from_army_control();
4503 for(
auto ar : state.world.province_get_army_location(target)) {
4504 auto other_nation = ar.get_army().get_controller_from_army_control();
4510 return state.defines.alice_ai_offensive_strength_overestimate * strength_total;
4515 dcon::province_id p;
4518 std::vector<a_str> ready_armies;
4519 ready_armies.reserve(state.world.province_size());
4521 int32_t ready_count = 0;
4522 for(
auto ar : state.world.nation_get_army_control(n)) {
4524 if(ar.get_army().get_battle_from_army_battle_participation()
4525 || ar.get_army().get_navy_from_army_transport()
4526 || ar.get_army().get_black_flag()
4527 || ar.get_army().get_arrival_time()
4528 || activity != army_activity::on_guard
4535 auto loc = ar.get_army().get_location_from_army_location().id;
4536 if(std::find_if(ready_armies.begin(), ready_armies.end(), [loc](a_str
const& v) { return loc == v.p; }) == ready_armies.end()) {
4537 ready_armies.push_back(a_str{ loc, 0.0f });
4541 if(ready_armies.empty())
4544 struct army_target {
4545 float minimal_distance;
4546 dcon::province_id location;
4547 float strength_estimate = 0.0f;
4551 std::vector<army_target> potential_targets;
4552 potential_targets.reserve(state.world.province_size());
4553 for(
auto o : state.world.nation_get_province_ownership(n)) {
4554 if(!o.get_province().get_nation_from_province_control()
4557 potential_targets.push_back(
4563 std::vector<dcon::nation_id> at_war_with;
4564 at_war_with.reserve(state.world.nation_size());
4565 for(
auto w : state.world.nation_get_war_participant(n)) {
4566 auto attacker = w.get_is_attacker();
4567 for(
auto p : w.get_war().get_war_participant()) {
4568 if(p.get_is_attacker() != attacker) {
4569 if(std::find(at_war_with.begin(), at_war_with.end(), p.get_nation().id) == at_war_with.end()) {
4570 at_war_with.push_back(p.get_nation().id);
4575 for(
auto w : at_war_with) {
4576 for(
auto o : state.world.nation_get_province_control(w)) {
4577 potential_targets.push_back(
4581 for(
auto o : state.world.nation_get_province_ownership(w)) {
4582 if(!o.get_province().get_nation_from_province_control()) {
4583 potential_targets.push_back(
4590 for(
const auto ovr : state.world.nation_get_overlord_as_ruler(n)) {
4591 auto w = ovr.get_subject();
4592 for(
auto o : state.world.nation_get_province_ownership(w)) {
4593 if(!o.get_province().get_nation_from_province_control()
4596 potential_targets.push_back(
4603 for(
auto& pt : potential_targets) {
4606 if(sdist < pt.minimal_distance) {
4607 pt.minimal_distance = sdist;
4611 std::sort(potential_targets.begin(), potential_targets.end(), [&](army_target& a, army_target& b) {
4612 if(a.minimal_distance != b.minimal_distance)
4613 return a.minimal_distance < b.minimal_distance;
4615 return a.location.index() < b.location.index();
4619 bool is_at_war = state.world.nation_get_is_at_war(n);
4620 int32_t min_ready_count = std::min(ready_count, 3);
4621 int32_t max_attacks_to_make = is_at_war ? std::max(min_ready_count, (ready_count + 1) / 3) : ready_count;
4622 auto const psize = potential_targets.size();
4624 for(
uint32_t i = 0; i < psize && max_attacks_to_make > 0; ++i) {
4625 if(!potential_targets[i].location)
4627 if(potential_targets[i].strength_estimate == 0.0f)
4630 auto target_attack_force = potential_targets[i].strength_estimate;
4631 std::sort(ready_armies.begin(), ready_armies.end(), [&](a_str
const& a, a_str
const& b) {
4632 auto adist = province::sorting_distance(state, a.p, potential_targets[i].location);
4633 auto bdist = province::sorting_distance(state, b.p, potential_targets[i].location);
4635 return adist > bdist;
4637 return a.p.index() < b.p.index();
4641 float a_force_str = 0.f;
4642 int32_t k = int32_t(ready_armies.size());
4643 for(; k-- > 0 && a_force_str <= target_attack_force;) {
4644 if(ready_armies[k].str == 0.0f) {
4645 for(
auto ar : state.world.province_get_army_location(ready_armies[k].p)) {
4646 if(ar.get_army().get_battle_from_army_battle_participation()
4647 || n != ar.get_army().get_controller_from_army_control()
4648 || ar.get_army().get_navy_from_army_transport()
4649 || ar.get_army().get_black_flag()
4650 || ar.get_army().get_arrival_time()
4651 ||
army_activity(ar.get_army().get_ai_activity()) != army_activity::on_guard
4659 ready_armies[k].str += 0.00001f;
4661 a_force_str += ready_armies[k].str;
4664 if(a_force_str < target_attack_force) {
4669 dcon::province_id central_province;
4671 glm::vec3 accumulated{ 0.0f, 0.0f, 0.0f };
4672 float minimal_distance = 2.0f;
4674 for(int32_t m = int32_t(ready_armies.size()); m-- > k + 1; ) {
4675 accumulated += state.world.province_get_mid_point_b(ready_armies[m].p);
4677 auto magnitude =
math::sqrt((accumulated.x * accumulated.x + accumulated.y * accumulated.y) + accumulated.z * accumulated.z);
4678 if(magnitude > 0.00001f)
4679 accumulated /= magnitude;
4684 auto pmid = state.world.province_get_mid_point_b(p);
4685 if(
auto dist = -((accumulated.x * pmid.x + accumulated.y * pmid.y) + accumulated.z * pmid.z); dist < minimal_distance) {
4686 minimal_distance = dist;
4687 central_province = p;
4690 if(!central_province)
4694 for(int32_t m = int32_t(ready_armies.size()); m-- > k + 1; ) {
4695 assert(m >= 0 && m < int32_t(ready_armies.size()));
4696 for(
auto ar : state.world.province_get_army_location(ready_armies[m].p)) {
4697 if(ar.get_army().get_battle_from_army_battle_participation()
4698 || n != ar.get_army().get_controller_from_army_control()
4699 || ar.get_army().get_navy_from_army_transport()
4700 || ar.get_army().get_black_flag()
4701 || ar.get_army().get_arrival_time()
4702 ||
army_activity(ar.get_army().get_ai_activity()) != army_activity::on_guard
4708 if(ready_armies[m].p == central_province) {
4709 ar.get_army().set_ai_province(potential_targets[i].location);
4710 ar.get_army().set_ai_activity(
uint8_t(army_activity::attacking));
4712 auto existing_path = ar.get_army().get_path();
4713 auto new_size =
uint32_t(path.size());
4714 existing_path.resize(new_size);
4716 for(
uint32_t q = 0; q < new_size; ++q) {
4718 existing_path[q] = path[q];
4721 ar.get_army().set_dig_in(0);
4722 ar.get_army().set_ai_province(potential_targets[i].location);
4723 ar.get_army().set_ai_activity(
uint8_t(army_activity::attacking));
4728 ready_armies.resize(k + 1);
4729 --max_attacks_to_make;
4733 for(
uint32_t j = i + 1; j < psize; ++j) {
4734 if(
province::sorting_distance(state, potential_targets[j].location, potential_targets[i].location) < state.defines.alice_ai_attack_target_radius)
4735 potential_targets[j].location = dcon::province_id{};
4742 concurrency::parallel_for(
uint32_t(0), state.world.nation_size(), [&](
uint32_t i) {
4743 dcon::nation_id n{ dcon::nation_id::value_base_t(i) };
4744 if(state.world.nation_is_valid(n)) {
4745 assign_targets(state, n);
4751 concurrency::parallel_for(
uint32_t(0), state.world.nation_size(), [&](
uint32_t i) {
4752 dcon::nation_id n{ dcon::nation_id::value_base_t(i) };
4753 if(state.world.nation_is_valid(n)) {
4754 distribute_guards(state, n);
4760 static std::vector<dcon::army_id> require_transport;
4761 require_transport.clear();
4763 for(
auto ar : state.world.in_army) {
4764 if(ar.get_ai_activity() ==
uint8_t(army_activity::attack_transport)) {
4765 if(!ar.get_arrival_time()
4766 && !ar.get_battle_from_army_battle_participation()
4767 && !ar.get_navy_from_army_transport()
4768 && std::find(require_transport.begin(), require_transport.end(), ar.id) == require_transport.end()) {
4772 require_transport.push_back(ar.id);
4774 ar.set_ai_activity(
uint8_t(army_activity::on_guard));
4775 ar.set_ai_province(dcon::province_id{});
4778 }
else if(ar.get_ai_activity() ==
uint8_t(army_activity::attack_gathered)) {
4779 if(!ar.get_arrival_time()
4780 && !ar.get_battle_from_army_battle_participation()
4781 && !ar.get_navy_from_army_transport()) {
4783 if(ar.get_location_from_army_location() == ar.get_ai_province()) {
4784 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())) {
4786 ar.set_ai_activity(
uint8_t(army_activity::on_guard));
4787 ar.set_ai_province(dcon::province_id{});
4791 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) {
4793 auto existing_path = ar.get_path();
4794 auto new_size =
uint32_t(path.size());
4795 existing_path.resize(new_size);
4797 for(
uint32_t i = 0; i < new_size; ++i) {
4799 existing_path[i] = path[i];
4804 ar.set_ai_activity(
uint8_t(army_activity::on_guard));
4805 ar.set_ai_province(dcon::province_id{});
4808 ar.set_ai_activity(
uint8_t(army_activity::on_guard));
4809 ar.set_ai_province(dcon::province_id{});
4813 }
else if(ar.get_ai_activity() ==
uint8_t(army_activity::attacking)
4814 && ar.get_ai_province() != ar.get_location_from_army_location()
4815 && !ar.get_arrival_time()
4816 && !ar.get_battle_from_army_battle_participation()
4817 && !ar.get_navy_from_army_transport()) {
4819 bool all_gathered =
true;
4820 for(
auto o : ar.get_controller_from_army_control().get_army_control()) {
4821 if(o.get_army().get_ai_province() == ar.get_ai_province()) {
4822 if(ar.get_location_from_army_location() != o.get_army().get_location_from_army_location()) {
4824 if(o.get_army().get_path().size() > 0 && o.get_army().get_path()[0] == ar.get_location_from_army_location()) {
4825 all_gathered =
false;
4830 if(o.get_army().get_battle_from_army_battle_participation()) {
4831 all_gathered =
false;
4840 if(ar.get_ai_province() == ar.get_location_from_army_location()) {
4841 for(
auto o : ar.get_location_from_army_location().get_army_location()) {
4842 if(o.get_army().get_ai_province() == ar.get_ai_province()
4843 && o.get_army().get_path().size() == 0) {
4845 o.get_army().set_ai_activity(
uint8_t(army_activity::attack_gathered));
4848 }
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) {
4850 for(
auto o : ar.get_location_from_army_location().get_army_location()) {
4851 if(o.get_army().get_ai_province() == ar.get_ai_province()
4852 && o.get_army().get_path().size() == 0) {
4854 auto existing_path = o.get_army().get_path();
4855 auto new_size =
uint32_t(path.size());
4856 existing_path.resize(new_size);
4858 for(
uint32_t i = 0; i < new_size; ++i) {
4860 existing_path[i] = path[i];
4863 o.get_army().set_dig_in(0);
4864 o.get_army().set_ai_activity(
uint8_t(army_activity::attack_gathered));
4868 for(
auto o : ar.get_location_from_army_location().get_army_location()) {
4869 if(o.get_army().get_ai_province() == ar.get_ai_province()
4870 && o.get_army().get_path().size() == 0) {
4872 require_transport.push_back(o.get_army().id);
4873 ar.set_ai_activity(
uint8_t(army_activity::attack_transport));
4878 ar.set_ai_activity(
uint8_t(army_activity::on_guard));
4879 ar.set_ai_province(dcon::province_id{});
4885 for(
uint32_t i = 0; i < require_transport.size(); ++i) {
4886 auto coastal_target_prov = state.world.army_get_location_from_army_location(require_transport[i]);
4887 auto controller = state.world.army_get_controller_from_army_control(require_transport[i]);
4891 auto regs = state.world.army_get_army_membership(require_transport[i]);
4894 tcap -= int32_t(regs.end() - regs.begin());
4896 if(tcap < 0 || (state.world.nation_get_is_at_war(controller) && !
naval_advantage(state, controller))) {
4898 if(state.world.army_get_controller_from_army_control(require_transport[j]) == controller) {
4899 state.world.army_set_ai_activity(require_transport[j],
uint8_t(army_activity::on_guard));
4900 state.world.army_set_ai_province(require_transport[j], dcon::province_id{});
4901 require_transport[j] = require_transport.back();
4902 require_transport.pop_back();
4905 state.world.army_set_ai_activity(require_transport[i],
uint8_t(army_activity::on_guard));
4906 state.world.army_set_ai_province(require_transport[i], dcon::province_id{});
4910 if(!state.world.province_get_is_coast(coastal_target_prov)) {
4913 state.world.army_set_ai_activity(require_transport[i],
uint8_t(army_activity::on_guard));
4914 state.world.army_set_ai_province(require_transport[i], dcon::province_id{});
4917 coastal_target_prov = path.front();
4919 auto existing_path = state.world.army_get_path(require_transport[i]);
4920 auto new_size =
uint32_t(path.size());
4921 existing_path.resize(new_size);
4923 for(
uint32_t k = 0; k < new_size; ++k) {
4925 existing_path[k] = path[k];
4927 state.world.army_set_arrival_time(require_transport[i],
military::arrival_time_to(state, require_transport[i], path.back()));
4928 state.world.army_set_dig_in(require_transport[i], 0);
4934 if(fleet_destination == state.world.navy_get_location_from_navy_location(transport_fleet)) {
4935 state.world.navy_get_path(transport_fleet).clear();
4936 state.world.navy_set_arrival_time(transport_fleet,
sys::date{});
4937 state.world.navy_set_ai_activity(transport_fleet,
uint8_t(fleet_activity::boarding));
4938 }
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()) {
4941 auto existing_path = state.world.navy_get_path(transport_fleet);
4942 auto new_size =
uint32_t(fleet_path.size());
4943 existing_path.resize(new_size);
4945 for(
uint32_t k = 0; k < new_size; ++k) {
4947 existing_path[k] = fleet_path[k];
4949 state.world.navy_set_arrival_time(transport_fleet,
military::arrival_time_to(state, transport_fleet, fleet_path.back()));
4950 state.world.navy_set_ai_activity(transport_fleet,
uint8_t(fleet_activity::boarding));
4954 state.world.army_set_ai_activity(require_transport[i],
uint8_t(army_activity::transport_attack));
4956 auto destination_region = state.world.province_get_connected_region_id(state.world.army_get_ai_province(require_transport[i]));
4960 if(state.world.army_get_controller_from_army_control(require_transport[j]) == controller) {
4961 auto jregs = state.world.army_get_army_membership(require_transport[j]);
4962 if(tcap >= (jregs.end() - jregs.begin())) {
4963 if(state.world.province_get_connected_region_id(state.world.army_get_ai_province(require_transport[j])) != destination_region)
4966 if(state.world.army_get_location_from_army_location(require_transport[j]) == coastal_target_prov) {
4967 state.world.army_set_ai_activity(require_transport[i],
uint8_t(army_activity::transport_attack));
4968 tcap -= int32_t(jregs.end() - jregs.begin());
4970 auto jpath = state.world.army_get_black_flag(require_transport[j])
4971 ?
province::make_land_path(state, state.world.army_get_location_from_army_location(require_transport[j]), coastal_target_prov, controller, require_transport[j])
4973 if(!jpath.empty()) {
4974 auto existing_path = state.world.army_get_path(require_transport[j]);
4975 auto new_size =
uint32_t(jpath.size());
4976 existing_path.resize(new_size);
4978 for(
uint32_t k = 0; k < new_size; ++k) {
4980 existing_path[k] = jpath[k];
4982 state.world.army_set_arrival_time(require_transport[j],
military::arrival_time_to(state, require_transport[j], jpath.back()));
4983 state.world.army_set_dig_in(require_transport[j], 0);
4984 state.world.army_set_ai_activity(require_transport[i],
uint8_t(army_activity::transport_attack));
4985 tcap -= int32_t(jregs.end() - jregs.begin());
4990 require_transport[j] = require_transport.back();
4991 require_transport.pop_back();
4998 for(
auto n : state.world.in_nation) {
4999 if(n.get_is_player_controlled() || n.get_owned_province_count() == 0)
5001 auto disarm = n.get_disarmed_until();
5002 if(disarm && state.current_date < disarm)
5005 static std::vector<dcon::province_land_construction_id> hopeless_construction;
5006 hopeless_construction.clear();
5008 state.world.nation_for_each_province_land_construction(n, [&](dcon::province_land_construction_id plcid) {
5010 auto prov = fat_plc.get_pop().get_province_from_pop_location();
5011 if(prov.get_nation_from_province_control() != n)
5012 hopeless_construction.push_back(plcid);
5015 for(
auto item : hopeless_construction) {
5016 state.world.delete_province_land_construction(item);
5019 auto constructions = state.world.nation_get_province_land_construction(n);
5020 if(constructions.begin() != constructions.end())
5023 int32_t num_frontline = 0;
5024 int32_t num_support = 0;
5026 bool can_make_inf = state.world.nation_get_active_unit(n, state.military_definitions.infantry) || state.military_definitions.unit_base_definitions[state.military_definitions.infantry].active;
5027 bool can_make_art = state.world.nation_get_active_unit(n, state.military_definitions.artillery) || state.military_definitions.unit_base_definitions[state.military_definitions.artillery].active;
5028 bool art_req_pc = state.military_definitions.unit_base_definitions[state.military_definitions.artillery].primary_culture;
5030 for(
auto ar : state.world.nation_get_army_control(n)) {
5031 for(
auto r : ar.get_army().get_army_membership()) {
5032 auto type = r.get_regiment().get_type();
5033 auto etype = state.military_definitions.unit_base_definitions[type].type;
5039 if(can_make_inf && type == state.military_definitions.irregular) {
5040 r.get_regiment().set_type(state.military_definitions.infantry);
5045 const auto decide_type = [&](
bool pc) {
5046 if(can_make_art && (!art_req_pc || (art_req_pc && pc))) {
5047 if(num_frontline > num_support) {
5049 return state.military_definitions.artillery;
5052 return can_make_inf ? state.military_definitions.infantry : state.military_definitions.irregular;
5055 return can_make_inf ? state.military_definitions.infantry : state.military_definitions.irregular;
5059 for(
auto p : state.world.nation_get_province_ownership(n)) {
5060 if(p.get_province().get_nation_from_province_control() != n)
5063 if(p.get_province().get_is_colonial()) {
5064 float divisor = state.defines.pop_size_per_regiment * state.defines.pop_min_size_for_regiment_colony_multiplier;
5065 float minimum = state.defines.pop_min_size_for_regiment;
5067 for(
auto pop : p.get_province().get_pop_location()) {
5068 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
5069 if(pop.get_pop().get_size() >= minimum) {
5070 auto amount = int32_t((pop.get_pop().get_size() / divisor) + 1);
5071 auto regs = pop.get_pop().get_regiment_source();
5072 auto building = pop.get_pop().get_province_land_construction();
5073 auto num_to_make = amount - ((regs.end() - regs.begin()) + (building.end() - building.begin()));
5074 while(num_to_make > 0) {
5075 auto t = decide_type(pop.get_pop().get_is_primary_or_accepted_culture());
5077 auto c = fatten(state.world, state.world.try_create_province_land_construction(pop.get_pop().id, n));
5084 }
else if(!p.get_province().get_is_owner_core()) {
5085 float divisor = state.defines.pop_size_per_regiment * state.defines.pop_min_size_for_regiment_noncore_multiplier;
5086 float minimum = state.defines.pop_min_size_for_regiment;
5088 dcon::pop_id non_preferred;
5089 for(
auto pop : p.get_province().get_pop_location()) {
5090 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
5091 if(pop.get_pop().get_size() >= minimum) {
5092 auto amount = int32_t((pop.get_pop().get_size() / divisor) + 1);
5093 auto regs = pop.get_pop().get_regiment_source();
5094 auto building = pop.get_pop().get_province_land_construction();
5095 auto num_to_make = amount - ((regs.end() - regs.begin()) + (building.end() - building.begin()));
5096 while(num_to_make > 0) {
5097 auto t = decide_type(pop.get_pop().get_is_primary_or_accepted_culture());
5099 auto c = fatten(state.world, state.world.try_create_province_land_construction(pop.get_pop().id, n));
5107 float divisor = state.defines.pop_size_per_regiment;
5108 float minimum = state.defines.pop_min_size_for_regiment;
5110 dcon::pop_id non_preferred;
5111 for(
auto pop : p.get_province().get_pop_location()) {
5112 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
5113 if(pop.get_pop().get_size() >= minimum) {
5114 auto amount = int32_t((pop.get_pop().get_size() / divisor) + 1);
5115 auto regs = pop.get_pop().get_regiment_source();
5116 auto building = pop.get_pop().get_province_land_construction();
5117 auto num_to_make = amount - ((regs.end() - regs.begin()) + (building.end() - building.begin()));
5118 while(num_to_make > 0) {
5119 auto t = decide_type(pop.get_pop().get_is_primary_or_accepted_culture());
5121 auto c = fatten(state.world, state.world.try_create_province_land_construction(pop.get_pop().id, n));
5134 for(
auto ar : state.world.in_army) {
5135 auto controller = ar.get_controller_from_army_control();
5138 && !ar.get_battle_from_army_battle_participation()
5139 && !ar.get_navy_from_army_transport()
5140 && !ar.get_arrival_time()) {
5142 auto location = ar.get_location_from_army_location();
5144 if(ar.get_black_flag() ||
army_activity(ar.get_ai_activity()) == army_activity::unspecified) {
5145 auto regs = ar.get_army_membership();
5146 if(regs.begin() == regs.end()) {
5148 }
else if(regs.end() - regs.begin() > 1) {
5150 ar.set_ai_activity(
uint8_t(army_activity::on_guard));
5152 bool is_art = state.military_definitions.artillery == (*regs.begin()).get_regiment().get_type();
5153 dcon::province_id target_location;
5154 float nearest_distance = 1.0f;
5157 for(
auto o : controller.get_army_control()) {
5158 auto other_location = o.get_army().get_location_from_army_location();
5160 if(
army_activity(o.get_army().get_ai_activity()) == army_activity::on_guard
5161 && other_location.get_connected_region_id() == location.get_connected_region_id()
5162 && (!target_location || sdist < nearest_distance)) {
5164 int32_t num_support = 0;
5165 int32_t num_frontline = 0;
5166 for(
auto r : o.get_army().get_army_membership()) {
5167 auto type = r.get_regiment().get_type();
5168 auto etype = state.military_definitions.unit_base_definitions[type].type;
5176 if((is_art && num_support < 5) || (!is_art && num_frontline < 5)) {
5177 target_location = other_location;
5178 nearest_distance = sdist;
5183 if(target_location) {
5184 if(target_location == location) {
5185 ar.set_ai_province(target_location);
5186 ar.set_ai_activity(
uint8_t(army_activity::merging));
5187 }
else if(
auto path =
province::make_land_path(state, location, target_location, controller, ar); path.size() > 0) {
5188 auto existing_path = ar.get_path();
5189 auto new_size =
uint32_t(path.size());
5190 existing_path.resize(new_size);
5192 for(
uint32_t i = 0; i < new_size; ++i) {
5194 existing_path[i] = path[i];
5198 ar.set_ai_province(target_location);
5199 ar.set_ai_activity(
uint8_t(army_activity::merging));
5201 ar.set_ai_activity(
uint8_t(army_activity::on_guard));
5204 ar.set_ai_activity(
uint8_t(army_activity::on_guard));
5207 }
else if(
army_activity(ar.get_ai_activity()) == army_activity::merging) {
5208 auto regs = ar.get_army_membership();
5209 if(regs.begin() == regs.end()) {
5213 bool is_art = state.military_definitions.artillery == (*regs.begin()).get_regiment().get_type();
5214 for(
auto o : location.get_army_location()) {
5215 if(o.get_army().get_ai_activity() ==
uint8_t(army_activity::on_guard)
5216 && o.get_army().get_controller_from_army_control() == controller) {
5218 int32_t num_support = 0;
5219 int32_t num_frontline = 0;
5220 for(
auto r : o.get_army().get_army_membership()) {
5221 auto type = r.get_regiment().get_type();
5222 auto etype = state.military_definitions.unit_base_definitions[type].type;
5230 if((is_art && num_support < 5) || (!is_art && num_frontline < 5)) {
5231 (*regs.begin()).get_regiment().set_army_from_army_membership(o.get_army());
5236 ar.set_ai_activity(
uint8_t(army_activity::unspecified));
5244 auto v = state.current_date.value;
5276 for(
auto ar : state.world.province_get_army_location(p))
5277 if(ar.get_army().get_controller_from_army_rebel_control())
#define assert(condition)
void update_crisis_leaders(sys::state &state)
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 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)
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)
float estimate_enemy_defensive_force(sys::state &state, dcon::province_id target, dcon::nation_id by)
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)
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)
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)
bool will_join_crisis_with_offer(sys::state &state, dcon::nation_id n, sys::crisis_join_offer const &offer)
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_land_constructions(sys::state &state)
bool will_be_crisis_primary_defender(sys::state &state, dcon::nation_id n)
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)
void sort_avilable_cbs(std::vector< possible_cb > &result, sys::state &state, dcon::nation_id n, dcon::war_id w)
bool army_ready_for_battle(sys::state &state, dcon::nation_id n, dcon::army_id a)
void take_ai_decisions(sys::state &state)
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)
void get_desired_factory_types(sys::state &state, dcon::nation_id nid, std::vector< dcon::factory_type_id > &desired_types)
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 sort_avilable_declaration_cbs(std::vector< possible_cb > &result, sys::state &state, dcon::nation_id n, dcon::nation_id target)
dcon::cb_type_id pick_fabrication_type(sys::state &state, dcon::nation_id from, dcon::nation_id target)
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)
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)
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)
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 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)
int32_t state_factory_count(sys::state &state, dcon::state_instance_id sid, dcon::nation_id n)
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_construction_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)
constexpr dcon::commodity_id money(0)
float estimate_naval_spending(sys::state &state, dcon::nation_id n)
void bound_budget_settings(sys::state &state, dcon::nation_id n)
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)
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)
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)
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)
float cb_infamy(sys::state const &state, dcon::cb_type_id t)
bool cb_requires_selection_of_a_valid_nation(sys::state const &state, dcon::cb_type_id t)
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)
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)
@ 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)
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)
dcon::state_definition_id state_def
dcon::national_identity_id associated_tag
dcon::nation_id secondary_nation
static constexpr uint32_t set_size
dcon::cb_type_id wargoal_type
static constexpr uint32_t modifier_definition_size