diff --git a/src/economy/advanced_province_buildings.cpp b/src/economy/advanced_province_buildings.cpp index fbc89a170..21b07e6bc 100644 --- a/src/economy/advanced_province_buildings.cpp +++ b/src/economy/advanced_province_buildings.cpp @@ -342,7 +342,7 @@ void update_national_size(sys::state& state) { auto tmod = state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::education_efficiency) + 1.0f; auto nmod = state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::education_efficiency_modifier) + 1.0f; - auto cost_of_input = state.world.province_get_labor_price(pids, def.throughput_labour_type); + auto cost_of_input = state.world.province_get_labor_price(pids, def.throughput_labour_type) + 0.001f; auto cost_of_output = state.world.province_get_service_price(pids, def.output) * tmod * nmod * def.output_amount; auto spending_scale = state.world.nation_get_spending_level(owner); @@ -354,6 +354,36 @@ void update_national_size(sys::state& state) { auto weight = ve::select(total_population == 0.f, 0.f, local_population / total_population); auto local_education_budget = weight * education_budget; state.world.province_set_advanced_province_building_national_size(pids, bid, ve::max(0.f, local_education_budget / cost_of_input)); + +#ifndef NDEBUG + ve::apply([&](float s) { + assert(!std::isnan(s)); + }, cost_of_input); + ve::apply([&](float s) { + assert(!std::isnan(s)); + }, cost_of_output); + ve::apply([&](float s) { + assert(!std::isnan(s)); + }, spending_scale); + ve::apply([&](float s) { + assert(!std::isnan(s)); + }, national_budget); + ve::apply([&](float s) { + assert(!std::isnan(s)); + }, education_priority); + ve::apply([&](float s) { + assert(!std::isnan(s)); + }, total_population); + ve::apply([&](float s) { + assert(!std::isnan(s)); + }, local_population); + ve::apply([&](float s) { + assert(!std::isnan(s)); + }, local_education_budget); + ve::apply([&](float s) { + assert(!std::isnan(s)); + }, cost_of_input); +#endif }); } } @@ -377,9 +407,34 @@ void update_production(sys::state& state) { state.world.province_set_service_supply_private(pids, def.output, current_private_supply + current_private_size * output); state.world.province_set_advanced_province_building_private_output(pids, bid, current_private_size * output); +#ifndef NDEBUG + ve::apply([&](float s) { + assert(!std::isnan(s)); + }, current_private_supply); + ve::apply([&](float s) { + assert(!std::isnan(s)); + }, current_private_size); + ve::apply([&](float s) { + assert(!std::isnan(s)); + }, output); +#endif + auto current_public_size = state.world.province_get_advanced_province_building_national_size(pids, bid); auto current_public_supply = state.world.province_get_service_supply_public(pids, def.output); state.world.province_set_service_supply_public(pids, def.output, current_public_supply + current_public_size * output); + state.world.province_set_advanced_province_building_private_output(pids, bid, current_public_size * output); + +#ifndef NDEBUG + ve::apply([&](float s) { + assert(!std::isnan(s)); + }, current_public_supply); + ve::apply([&](float s) { + assert(!std::isnan(s)); + }, current_public_size); + ve::apply([&](float s) { + assert(!std::isnan(s)); + }, output); +#endif }); // TODO: @@ -403,8 +458,19 @@ void update_production(sys::state& state) { //assume that low trade volume doesn't require any additional infrastructure or workers auto output = 100.f + current_private_size * input_satisfaction * def.output_amount * efficiency; auto current_private_supply = state.world.province_get_service_supply_private(pids, def.output); - state.world.province_set_service_supply_private(pids, def.output, current_private_supply + output); - state.world.province_set_advanced_province_building_private_output(pids, bid, output); + state.world.province_set_service_supply_private(pids, def.output, current_private_supply + current_private_size * output); + +#ifndef NDEBUG + ve::apply([&](float s) { + assert(!std::isnan(s)); + }, current_private_supply); + ve::apply([&](float s) { + assert(!std::isnan(s)); + }, current_private_size); + ve::apply([&](float s) { + assert(!std::isnan(s)); + }, output); +#endif }); } } diff --git a/src/economy/economy_trade_routes.cpp b/src/economy/economy_trade_routes.cpp index 1b70e6bf1..83ea6fc2a 100644 --- a/src/economy/economy_trade_routes.cpp +++ b/src/economy/economy_trade_routes.cpp @@ -22,7 +22,6 @@ namespace economy { // 1 means that trade profit due to price difference is pocketed by importers constexpr inline float import_profit_priority = 0.5f; - template auto trade_route_effect_of_scale(sys::state& state, TRADE_ROUTE trade_route) { using MARKET = convert_value_type; @@ -47,7 +46,8 @@ auto trade_route_effect_of_scale(sys::state& state, TRADE_ROUTE trade_route) { } -// US3AC2 Labour demand for a single trade route +// US3AC2 +// Labour demand for a single trade route float trade_route_labour_demand(sys::state& state, dcon::trade_route_id trade_route, dcon::province_id A_capital, dcon::province_id B_capital) { auto cargo = 0.f; state.world.for_each_commodity([&](auto cid) { @@ -64,7 +64,8 @@ float trade_route_labour_demand(sys::state& state, dcon::trade_route_id trade_ro return total_demanded_labor; } -// US3AC2 Calculate labour demand for trade routes between markets +// US3AC2 Markets have associated labour costs for trade routes management +// Calculate labour demand for trade routes between markets float transportation_between_markets_labor_demand(sys::state& state, dcon::market_id market) { auto total_demanded_labour = 0.f; @@ -83,7 +84,8 @@ float transportation_between_markets_labor_demand(sys::state& state, dcon::marke } -// US3AC3 Calculate labour demand for trade inside the market +// US3AC3 Markets have associated labour costs for trade inside the state +// Calculate labour demand for trade inside the market float transportation_inside_market_labor_demand(sys::state& state, dcon::market_id market, dcon::province_id capital) { auto base_cargo_transport_demand = 0.f; @@ -360,11 +362,12 @@ trade_route_volume_change_reasons predict_trade_route_volume_change( auto is_land_route = state.world.trade_route_get_is_land_route(route); auto same_nation = controller_capital_A == controller_capital_B; - // US3AC7. Ban international sea routes or international land routes based on the corresponding modifiers + // Ban international sea routes or international land routes based on the corresponding modifiers + // US3AC7 If disallow_naval_trade national modifier is non-zero then its states can't trade by sea auto A_bans_sea_trade = state.world.nation_get_modifier_values(controller_capital_A, sys::national_mod_offsets::disallow_naval_trade) > 0.f; auto B_bans_sea_trade = state.world.nation_get_modifier_values(controller_capital_B, sys::national_mod_offsets::disallow_naval_trade) > 0.f; auto sea_trade_banned = A_bans_sea_trade || B_bans_sea_trade; - // US3AC8. Ban international sea routes or international land routes based on the corresponding modifiers + // US3AC8 If disallow_land_trade national modifier is non-zero then its states can't trade by land auto A_bans_land_trade = state.world.nation_get_modifier_values(controller_capital_A, sys::national_mod_offsets::disallow_land_trade) > 0.f; auto B_bans_land_trade = state.world.nation_get_modifier_values(controller_capital_B, sys::national_mod_offsets::disallow_land_trade) > 0.f; auto land_trade_banned = A_bans_land_trade || B_bans_land_trade; @@ -372,7 +375,7 @@ trade_route_volume_change_reasons predict_trade_route_volume_change( is_sea_route = is_sea_route && !is_A_blockaded && !is_B_blockaded; - // US3AC9. Wartime embargoes + // US3AC9 auto A_joins_sphere_wide_embargo = ve::apply([&](auto n_a, auto n_b) { return military::are_at_war(state, n_a, n_b); }, market_leader_A, market_leader_B); @@ -381,9 +384,9 @@ trade_route_volume_change_reasons predict_trade_route_volume_change( return military::are_at_war(state, n_a, n_b); }, market_leader_B, market_leader_A); - // US3AC10. diplomatic embargos - // US3AC11. sphere joins embargo - // US3AC12 subject joins embargo + // US3AC10 + // US3AC11 + // US3AC12 auto A_has_embargo = non_war_embargo_status(state, controller_capital_A, controller_capital_B, market_leader_A, market_leader_B); A_joins_sphere_wide_embargo = A_has_embargo || A_joins_sphere_wide_embargo; @@ -411,7 +414,8 @@ trade_route_volume_change_reasons predict_trade_route_volume_change( auto trade_good_loss_mult = std::max(0.f, 1.f - trade_loss_per_distance_unit * distance); - // US3AC2 we assume that 2 uneducated persons (1 from each market) can transport 1 unit of goods along path of 1 effective day length + // US3AC2 + // We assume that 2 uneducated persons (1 from each market) can transport 1 unit of goods along path of 1 effective day length // we do it this way to avoid another assymetry in calculations auto transport_cost = distance / trade_distance_covered_by_pair_of_workers_per_unit_of_good @@ -551,7 +555,8 @@ void update_trade_routes_volume( auto is_sea_route = state.world.trade_route_get_is_sea_route(trade_route) && !is_A_blockaded && !is_B_blockaded; auto is_land_route = state.world.trade_route_get_is_land_route(trade_route); auto same_nation = controller_A == controller_B; - // US3AC7 US3AC8 Ban international sea routes or international land routes based on the corresponding modifiers + // US3AC7 + // US3AC8 auto A_bans_sea_trade = state.world.nation_get_modifier_values(controller_A, sys::national_mod_offsets::disallow_naval_trade) > 0.f; auto B_bans_sea_trade = state.world.nation_get_modifier_values(controller_B, sys::national_mod_offsets::disallow_naval_trade) > 0.f; auto sea_trade_banned = A_bans_sea_trade || B_bans_sea_trade; @@ -583,7 +588,8 @@ void update_trade_routes_volume( // US3AC18 auto trade_good_loss_mult = ve::max(0.f, 1.f - trade_loss_per_distance_unit * distance); - // US3AC2. we assume that 2 uneducated persons (1 from each market) can transport 1 unit of goods along path of 1 effective day length + // US3AC2 + // We assume that 2 uneducated persons (1 from each market) can transport 1 unit of goods along path of 1 effective day length // we do it this way to avoid another assymetry in calculations auto transport_availability_A = ve::select(is_land_route, ve::fp_vector{ state.world.province_get_labor_demand_satisfaction(capital_A, labor::no_education) }, ve::fp_vector{ 0.f }); @@ -718,7 +724,8 @@ void update_trade_routes_consumption(sys::state& state) { }); }); - // US3AC2 register trade demand on transportation labor: + // US3AC2 + // Register trade demand on transportation labor: // money are paid during calculation of trade route profits and actual movement of goods auto port_services_buffer = state.world.market_make_vectorizable_float_buffer(); @@ -760,7 +767,8 @@ void update_trade_routes_consumption(sys::state& state) { state.world.province_set_service_demand_forbidden_public_supply(pid, services::list::port_capacity, local_demand + market_demand * local_weight / total_weight); }); - // US3AC3 register demand on local transportation/accounting due to trade + // US3AC3 + // register demand on local transportation/accounting due to trade // all trade generates uneducated labor demand for goods transport locally // labor demand satisfaction does not set limits on transportation: it would be way too jumpy // we assume that 1 human could move 100 units of goods daily locally diff --git a/src/gamestate/system_state.cpp b/src/gamestate/system_state.cpp index 51094d5a9..15f8b1911 100644 --- a/src/gamestate/system_state.cpp +++ b/src/gamestate/system_state.cpp @@ -2631,7 +2631,9 @@ void state::load_scenario_data(parsers::error_handler& err, sys::year_month_day for(const auto ft : world.in_factory_type) { if(!bool(world.factory_type_get_output(ft))) { + err.fatal = true; err.accumulated_errors += "No output defined for factory " + std::string(text::produce_simple_string(*this, world.factory_type_get_name(ft))) + " (" + err.file_name + ")\n"; + assert(world.factory_type_get_output(ft)); } } if(!new_context.found_worker_types) { diff --git a/src/nations/nations.cpp b/src/nations/nations.cpp index b82722797..5c15381de 100644 --- a/src/nations/nations.cpp +++ b/src/nations/nations.cpp @@ -459,7 +459,10 @@ void generate_sea_trade_routes(sys::state& state) { auto continent_origin = state.world.province_get_continent(state_owner_capital); float mult = 1.f; - mult += std::min(naval_base_origin, naval_base_target) * naval_base_level_to_market_attractiveness; + // US3AC5 Naval bases increase appeal of a state for trade routes by 25% + mult += std::min(naval_base_origin, naval_base_target) * naval_base_level_to_market_attractiveness + + // US3AC22 Trade Route attraction modifier + std::min(state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::trade_routes_attraction), state.world.nation_get_modifier_values(target_owner, sys::national_mod_offsets::trade_routes_attraction)); bool must_connect = same_owner && different_region && capital_and_connected_region; auto distance_approximation = province::direct_distance(state, coast_0, coast_1) / base_speed;