Skip to main content

tiger_lib/vic3/tables/
iterators.rs

1use std::sync::LazyLock;
2
3use crate::everything::Everything;
4use crate::helpers::TigerHashMap;
5use crate::item::Item;
6use crate::lowercase::Lowercase;
7use crate::report::{ErrorKey, err};
8use crate::scopes::Scopes;
9use crate::token::Token;
10
11const GEOGRAPHIC_REGION_ITERATORS: &[(Scopes, &str, Scopes)] = &[
12    (Scopes::None, "country_in_", Scopes::Country),
13    (Scopes::None, "province_in_", Scopes::Province),
14    (Scopes::None, "state_in_", Scopes::State),
15    (Scopes::None, "state_region_in_", Scopes::StateRegion),
16    (Scopes::None, "strategic_region_in_", Scopes::StrategicRegion),
17];
18
19#[inline]
20pub fn iterator(name_lc: &Lowercase, name: &Token, data: &Everything) -> Option<(Scopes, Scopes)> {
21    for (inscope, pfx, outscope) in GEOGRAPHIC_REGION_ITERATORS.iter().copied() {
22        if let Some(part) = name_lc.strip_prefix_unchecked(pfx) {
23            if !data.item_exists(Item::GeographicRegionShortKey, part.as_str()) {
24                let msg = format!("could not find geographic region short key {part}");
25                let info = format!("so the iterator {name} does not exist");
26                err(ErrorKey::MissingItem).strong().msg(msg).info(info).loc(name).push();
27            }
28            return Some((inscope, outscope));
29        }
30    }
31
32    ITERATOR_MAP.get(name_lc.as_str()).copied()
33}
34
35static ITERATOR_MAP: LazyLock<TigerHashMap<&'static str, (Scopes, Scopes)>> = LazyLock::new(|| {
36    let mut hash = TigerHashMap::default();
37    for (from, s, to) in ITERATOR.iter().copied() {
38        hash.insert(s, (from, to));
39    }
40    hash
41});
42
43/// LAST UPDATED VIC3 VERSION 1.12.0
44/// See `effects.log` from the game data dumps
45/// These are the list iterators. Every entry represents
46/// a every_, ordered_, random_, and any_ version.
47const ITERATOR: &[(Scopes, &str, Scopes)] = &[
48    (Scopes::Country, "active_law", Scopes::Law),
49    (Scopes::Country, "active_party", Scopes::Party),
50    (Scopes::None, "character", Scopes::Character),
51    (Scopes::None, "character_in_exile_pool", Scopes::Character),
52    (Scopes::None, "character_in_void", Scopes::Character),
53    (Scopes::Character, "character_role", Scopes::CharacterRole),
54    (Scopes::Country, "civil_war", Scopes::CivilWar),
55    (Scopes::Country, "cobelligerent_in_diplo_play", Scopes::Country),
56    (Scopes::Country, "cobelligerent_in_war", Scopes::Country),
57    (
58        Scopes::Battle
59            .union(Scopes::Building)
60            .union(Scopes::Front)
61            .union(Scopes::Hq)
62            .union(Scopes::MilitaryFormation),
63        "combat_unit",
64        Scopes::NewCombatUnit,
65    ),
66    (Scopes::Country, "company", Scopes::Company),
67    (Scopes::None, "country", Scopes::Country),
68    (Scopes::Country, "country_strategic_region", Scopes::StrategicRegion),
69    (Scopes::None, "decentralized_country", Scopes::Country),
70    (Scopes::Country, "diplomatic_catalyst", Scopes::DiplomaticCatalyst),
71    (Scopes::None, "diplomatic_play", Scopes::DiplomaticPlay),
72    (Scopes::Country, "diplomatically_relevant_country", Scopes::Country),
73    (Scopes::Country, "direct_subject", Scopes::Country),
74    (Scopes::Country, "enemy_in_diplo_play", Scopes::Country),
75    (Scopes::Country, "enemy_in_war", Scopes::Country),
76    (
77        Scopes::Country
78            .union(Scopes::State)
79            .union(Scopes::StateRegion)
80            .union(Scopes::StrategicRegion),
81        "harvest_condition",
82        Scopes::HarvestConditionType,
83    ),
84    (Scopes::None, "in_global_list", Scopes::all_but_none()),
85    (Scopes::Country, "in_hierarchy", Scopes::Country),
86    (Scopes::None, "in_list", Scopes::all_but_none()),
87    (Scopes::None, "in_local_list", Scopes::all_but_none()),
88    (Scopes::PoliticalMovement, "influenced_interest_group", Scopes::InterestGroup),
89    (Scopes::Country, "interest_group", Scopes::InterestGroup),
90    (Scopes::None, "key_in_global_variable_map", Scopes::all_but_none()),
91    (Scopes::None, "key_in_local_variable_map", Scopes::all_but_none()),
92    (Scopes::None, "key_in_variable_map", Scopes::all_but_none()),
93    (Scopes::Country, "law", Scopes::Law),
94    (Scopes::PoliticalLobby, "lobby_member", Scopes::InterestGroup),
95    (Scopes::None, "market", Scopes::Market),
96    (Scopes::Market, "market_goods", Scopes::MarketGoods),
97    (Scopes::Party, "member", Scopes::InterestGroup),
98    (
99        Scopes::Country.union(Scopes::Front).union(Scopes::Hq),
100        "military_formation",
101        Scopes::MilitaryFormation,
102    ),
103    (
104        Scopes::Country
105            .union(Scopes::State)
106            .union(Scopes::StateRegion)
107            .union(Scopes::StrategicRegion),
108        "neighbouring_state",
109        Scopes::State,
110    ),
111    (Scopes::Country, "overlord_or_above", Scopes::Country),
112    (Scopes::Company, "owned_country", Scopes::Country),
113    (Scopes::DiplomaticPact, "participant", Scopes::Country),
114    (Scopes::Country.union(Scopes::InterestGroup), "political_lobby", Scopes::PoliticalLobby),
115    (Scopes::Country, "political_movement", Scopes::PoliticalMovement),
116    (Scopes::Law, "possible_amendment_type", Scopes::AmendmentType),
117    (Scopes::Country, "potential_party", Scopes::Party),
118    (Scopes::None, "power_bloc", Scopes::PowerBloc),
119    (Scopes::PowerBloc, "power_bloc_member", Scopes::Country),
120    (Scopes::InterestGroup, "preferred_law", Scopes::Law),
121    (Scopes::Country.union(Scopes::CountryDefinition), "primary_culture", Scopes::Culture),
122    // TODO: verify. The docs have State and Province reversed.
123    (Scopes::State, "province", Scopes::Province),
124    (Scopes::Country, "rival_country", Scopes::Country),
125    (Scopes::Country, "rivaling_country", Scopes::Country),
126    // TODO: Scopes::Front is in the docs but doesn't make sense for admirals
127    (
128        Scopes::Country
129            .union(Scopes::Front)
130            .union(Scopes::InterestGroup)
131            .union(Scopes::MilitaryFormation),
132        "scope_admiral",
133        Scopes::Character,
134    ),
135    (Scopes::Country, "scope_ally", Scopes::Country),
136    (Scopes::Law, "scope_amendment", Scopes::Amendment),
137    (
138        Scopes::Country.union(Scopes::Front).union(Scopes::Hq),
139        "scope_army",
140        Scopes::MilitaryFormation,
141    ),
142    (Scopes::Treaty, "scope_article", Scopes::TreatyArticle),
143    (
144        Scopes::TreatyOptions.union(Scopes::Treaty),
145        "scope_article_option",
146        Scopes::TreatyArticleOptions,
147    ),
148    (Scopes::Country.union(Scopes::State), "scope_building", Scopes::Building),
149    (
150        Scopes::Country
151            .union(Scopes::Front)
152            .union(Scopes::InterestGroup)
153            .union(Scopes::MilitaryFormation),
154        "scope_character",
155        Scopes::Character,
156    ),
157    (
158        Scopes::Market.union(Scopes::StateRegion).union(Scopes::StrategicRegion),
159        "scope_country",
160        Scopes::Country,
161    ),
162    (Scopes::Country.union(Scopes::State), "scope_culture", Scopes::Culture),
163    (Scopes::Country, "scope_diplomatic_pact", Scopes::DiplomaticPact),
164    (Scopes::Country.union(Scopes::Hq), "scope_fleet", Scopes::MilitaryFormation),
165    (Scopes::War, "scope_front", Scopes::Front),
166    (
167        Scopes::Country
168            .union(Scopes::Front)
169            .union(Scopes::InterestGroup)
170            .union(Scopes::MilitaryFormation),
171        "scope_general",
172        Scopes::Character,
173    ),
174    (Scopes::Country, "scope_held_interest_marker", Scopes::InterestMarker),
175    (Scopes::Country.union(Scopes::Culture), "scope_homeland_state", Scopes::State),
176    (Scopes::DiplomaticPlay, "scope_initiator_ally", Scopes::Country),
177    (
178        Scopes::Country.union(Scopes::StateRegion).union(Scopes::StrategicRegion),
179        "scope_interest_marker",
180        Scopes::InterestMarker,
181    ),
182    (Scopes::JournalEntry, "scope_je_involved", Scopes::Country),
183    (Scopes::DiplomaticPlay, "scope_play_involved", Scopes::Country),
184    (
185        Scopes::Country
186            .union(Scopes::Front)
187            .union(Scopes::InterestGroup)
188            .union(Scopes::MilitaryFormation),
189        "scope_politician",
190        Scopes::Character,
191    ),
192    (
193        Scopes::Country.union(Scopes::Culture).union(Scopes::InterestGroup).union(Scopes::State),
194        "scope_pop",
195        Scopes::Pop,
196    ),
197    (Scopes::Company, "scope_regional_hqs", Scopes::Building),
198    (Scopes::Country.union(Scopes::MilitaryFormation), "scope_ship", Scopes::Ship),
199    (
200        Scopes::Country
201            .union(Scopes::Front)
202            .union(Scopes::StateRegion)
203            .union(Scopes::StrategicRegion)
204            .union(Scopes::Theater),
205        "scope_state",
206        Scopes::State,
207    ),
208    (Scopes::Country.union(Scopes::State), "scope_strait", Scopes::Strait),
209    (Scopes::DiplomaticPlay, "scope_target_ally", Scopes::Country),
210    (Scopes::Country, "scope_theater", Scopes::Theater),
211    (Scopes::Country, "scope_treaty", Scopes::Treaty),
212    (Scopes::Country, "scope_violate_sovereignty_interested_parties", Scopes::Country),
213    (Scopes::Country, "scope_violate_sovereignty_wars", Scopes::War),
214    (Scopes::Country, "scope_war", Scopes::War),
215    // TODO: check if the scoped state is a sea node
216    (Scopes::State, "sea_node_adjacent_state", Scopes::State),
217    (Scopes::None, "state", Scopes::State),
218    (Scopes::None, "state_region", Scopes::StateRegion),
219    (Scopes::Country, "strategic_objective", Scopes::State),
220    (Scopes::None, "strategic_region", Scopes::StrategicRegion),
221    (Scopes::Country, "subject_of_subject", Scopes::Country),
222    (Scopes::Country, "subject_or_below", Scopes::Country),
223    (Scopes::PoliticalMovement, "supporting_character", Scopes::Character),
224    (Scopes::None, "treaty", Scopes::Treaty),
225    (Scopes::Country, "valid_mass_migration_culture", Scopes::Culture),
226    (Scopes::War, "war_participant", Scopes::Country),
227];
228
229pub fn iterator_removed(name: &str) -> Option<(&'static str, &'static str)> {
230    for (removed_name, version, explanation) in ITERATOR_REMOVED.iter().copied() {
231        if name == removed_name {
232            return Some((version, explanation));
233        }
234    }
235    None
236}
237
238const ITERATOR_REMOVED: &[(&str, &str, &str)] = &[
239    (
240        "scope_cobelligerent",
241        "1.4.0",
242        "replaced with _cobelligerent_in_diplo_play, _cobelligerent_in_war",
243    ),
244    ("supporting_interest_group", "1.8", "replaced with `_influenced_interest_group`"),
245    ("trade_route", "1.9", "replaced by world market system"),
246];