aboutsummaryrefslogtreecommitdiff
path: root/docs/simulation/calculations.yaml
blob: 91664b6c258ea18da8926dae13e52568df93d0ab (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
Diplomacy:
  Monthly diplomatic points gain: defines.country.BASE_MONTHLY_DIPLOPOINTS * (1 + sum of diplomatic_points + sum of diplomatic_points_modifier)
  Influence:
    Total base daily influence gain:  defines.country.BASE_GREATPOWER_DAILY_INFLUENCE * (1 + sum of influence) * (1 + sum of influence_modifier)
    Base daily influence gain per country:
      if total priority bars > 0: Total base influence gain * priority bars / total priority bars
      else: Total base influence gain / number of countries (excluding banned)
    Country influence gain modifier:
      note: 'our' and 'we' refers to the influencer. 'target' is the country being influenced.
      formula: 1 + score mod + relations mod + population mod + investment mod + puppet mod + neighbour mod + continent mod + discredit mod
      score mod: 1 - target score / our score
      relations mod: relations / defines.diplomacy.RELATION_INFLUENCE_MODIFIER
      population mod:
        if target population > LARGE_POPULATION_LIMIT:
          formula: floor((target population - LARGE_POPULATION_LIMIT) / LARGE_POPULATION_INFLUENCE_PENALTY_CHUNK) * LARGE_POPULATION_INFLUENCE_PENALTY
          target population: total of pop sizes
          LARGE_POPULATION_LIMIT: defines.pops.LARGE_POPULATION_LIMIT
          LARGE_POPULATION_INFLUENCE_PENALTY_CHUNK: defines.pops.LARGE_POPULATION_INFLUENCE_PENALTY_CHUNK
          LARGE_POPULATION_INFLUENCE_PENALTY: defines.diplomacy.LARGE_POPULATION_INFLUENCE_PENALTY
        else: 0
      investment mod:
        if value of total investments in target > 0: (1 - value of our investment / value of total investments in target) * - defines.diplomacy.INVESTMENT_INFLUENCE_DEFENSE
        else: 0
      puppet mod:
        if is our puppet: defines.diplomacy.PUPPET_BONUS_INFLUENCE_PERCENT
        else: 0
      neighbour mod:
        if target is direct neighbour: defines.diplomacy.NEIGHBOUR_BONUS_INFLUENCE_PERCENT
        else if target has a sphereling as neighbour: defines.diplomacy.SPHERE_NEIGHBOUR_BONUS_INFLUENCE_PERCENT
        else: 0
      continent mod:
        if target is on a different continent: defines.diplomacy.OTHER_CONTINENT_BONUS_INFLUENCE_PERCENT
        else: 0
      discredit mod:
        if we are discredited: defines.diplomacy.DISCREDIT_INFLUENCE_GAIN_FACTOR
        else: 0
    Daily influence gain per country: Base daily influence gain per country * Country influence gain modifier
  Colonisable life rating: defines.country.COLONIAL_LIFERATING + sum of colonial_life_rating
Economy:
  Budget:
    Loan interest per day:
      formula: (NBD + FBD * (1 + FIM)) * max(0.01, LBI+BIM)/30
      NBD: National bank debt = debt owed to your national bank.
      FBD: Foreign bank debt = debt owed to foreign national banks and private investors.
      1+FIM: Foreign interest modifier = sum of loan_interest modifiers from non-tech
      max(0.01: Hardcoded value. Reasoning unknown.
      LBI: defines.economy.LOAN_BASE_INTEREST
      BIM: Base interest modifier = sum of loan_interest modifiers from technology.
      /30: Hardcoded value to represent days in a month.
    Gold income daily:
      formula: MGQ * GOLD_TO_CASH_RATE
      MGQ: Money good quanity = total production of goods with money = yes
      GOLD_TO_CASH_RATE: defines.country.GOLD_TO_CASH_RATE
    Overseas maintenance:
      See: https://github.com/schombert/Project-Alice/blob/main/docs/rules.md#overseas-penalty
  Production:
    Resource gathering operation:
      base workforce: defined in common/production_types.txt as workforce
      rgo size:
        formula: floor(1.5*ceil(n_workers_in_state / (base workforce * (1 + terrain rgo size modifier)))
        n_workers_in_state: Total size of POPs in state where POP type is in employees (common/production_types.txt).
        note: Calculated when starting a new game.
      Output:
        formula: base output * rgo size * (1 + overseas penalty) * throughput from workers * (1 + throughput modifier) * (1 + output from workers) * (1 + output modifier)
        base output: defined in common/production_types.txt
        overseas penalty:
          if province is 'overseas': overseas penalty (see economy > budget > overseas maintenance)
          else: 0
        workforce:
          formula: base workforce * rgo size * (1 + rgo size modifier)
          base workforce: Defined in common/production_types.txt as workforce.
          rgo size modifier: sum of rgo size modifiers + sum of farm size modifiers (if farm=yes) + sum of mine size modifiers (if mine=yes)
        job portion of workforce:
          formula: employees with job / workforce
          employees with job: Number of POPs employed with the job. Job being an entry in employees in common/production_types.txt.
        effect from job:
          formula:
            if effect_multiplier == 1: effect_multiplier * employees with job / workforce
            else: effect_multiplier * min(employees with job / workforce, amount)
          effect_multiplier: defined in common/production_types.txt (default 1)
          amount: defined in common/production_types.txt (default 1)
        throughput from workers: sum of effect from job for each job with `effect = throughput`
        output from workers: sum of effect from job for each job with `effect = output`
        throughput modifier: sum of throughput modifiers (including from owner)
        output modifier: sum of throughput modifiers (including from owner)
        modifier from owner:
          formula: effect_multiplier * n_owners_in_state / n_pops_in_state
          effect_multiplier: see throughput from workers
          n_owners_in_state: total size of owner POPs in state
          n_pops_in_state: total size of all POPs in state
          note: included in throughput or output modifier
    Human resource management:
      Vacancies: max employees - employees count
      Maximum employees hired per day:
        formula: max(employees available, relative maximum)
        employees available: unemployed employee pops in state
        relative maximum:
            if employees count = 0 & max employees >= 6667: 0.2775 * Vacancies
            else: ceil(0.15 * Vacancies) - 1
          0.15: Hardcoded value.
          0.2775: 1 - (1 - 0.15)^2
          note: Rounding is unknown for the 0.2775 case. See https://discord.com/channels/1063392556160909312/1063416834650554398/1204520366643347476
      Minimum employees hired per day:
        formula: max(absolute minimum, relative minimum)
        absolute minimum: 50 (hardcoded value)
        relative minimum: floor(defines.economy.EMPLOYMENT_HIRE_LOWEST * employees count)
Military:
  Maximum regiments per soldier POP:
    if POP size < defines.military.POP_MIN_SIZE_FOR_REGIMENT: 0
    else:
      formula: 1 + trunc(POP size / (POP_SIZE_PER_REGIMENT * location factor))
      POP_SIZE_PER_REGIMENT: defines.military.POP_SIZE_PER_REGIMENT
      location factor:
        if is protectorate: defines.military.POP_MIN_SIZE_FOR_REGIMENT_PROTECTORATE_MULTIPLIER
        else if is colony: defines.military.POP_MIN_SIZE_FOR_REGIMENT_COLONY_MULTIPLIER
        else if location is core: 1
        else: defines.military.POP_MIN_SIZE_FOR_REGIMENT_NONCORE_MULTIPLIER
  Reinforcing:
    Regiment reinforcements fraction * 1000:
      formula:
        if regiment is full strength: 0
        else: min(trunc(regiment reinforce rate * supply factor * reinforcements multiplier * 1000), 1000)
      unit type strength: as defined in /units/<unit>.txt
      1000: strength is defined in thousands of soldiers. Reinforcements per army uses the number of soldiers.
      regiment reinforce rate:
          if regiment is mobilised: 0.5
          else if pop is too small for a single regiment: 0.5
          else if pop supports too many regiments: Maximum regiments per soldier POP / number of supported regiments
          else: 1
      reinforcements multiplier:
        formula: REINFORCE_SPEED * local reinforce rate * (1 + reinforce_rate) * (1 + reinforce_speed)
        REINFORCE_SPEED: defines.military.REINFORCE_SPEED
        local reinforce rate:
          if location owner == army owner: 2
          else if army is exiled: 0
          else if location is uncolonised: 0
          else if location controller is hostile:
            if location neighbours a province controlled by an ally in this war: 0.5
            else if location is coastal & not blockaded: 0.25
            else: 0.1
          else: 1
        reinforce_rate: sum of reinforce_rate modifiers from tech
        reinforce_speed: sum of reinforce_speed modifiers on country
      supply factor:
        if army received all its supplies: 1
        else:
          formula: x^(1+i)
          x: received supply
          i: 0 based index of regiment in the army
      trunc(... * 1000): Truncated to 1/1000th.
      min(..., 1000): Capped at max strength.
    Regiment reinforcements:
      formula: trunc(unit type strength * Regiment reinforcements fraction * 1000)
      unit type strength: as defined in /units/<unit>.txt
      trunc(unit type strength * ...): Truncated to integers in the case unit type strength isn't an integer already.
    Reinforcements per army (tooltip): sum of Regiment reinforcements
    Regiment experience after reinforcing:
      formula: xp before reinforcing / (1 + trunc(Regiment reinforcements fraction * 1000 / 3) / 1000)
      trunc(... / 3): Hardcoded.
      / 1000: to counter * 1000.
  Regiment experience gain per day of combat:
    formula: d6 * defines.military.EXP_GAIN_DIV * (1 + sum of experience gain modifiers) + unexplained
    d6: random integer (inclusive) 1-6
    unexplained: see https://discord.com/channels/1062018115275325480/1062021872545447936/1278664121323356190 or https://media.discordapp.net/attachments/1062021872545447936/1278666211848228906/image.png?ex=66d1a235&is=66d050b5&hm=47bafd0f86451a25aebd7b728e96dda264bc0704a4e398ca59931390a902b968&=&format=webp&quality=lossless
Politics:
  Westernisation:
    Upper house reform support:
      formula: sum of (Ideology support factor * Ideology upper house share)
      Ideology support factor: common/ideologies.txt add_economic_reform or add_military_reform
    Economic reform cost modifier: defines.country.ECONOMIC_REFORM_UH_FACTOR * Upper house reform support + self_unciv_economic_modifier
    Military reform cost modifier: defines.country.MILITARY_REFORM_UH_FACTOR * Upper house reform support + self_unciv_military_modifier
POPs:
  Monthly pop growth:
    formula: BASE_POPGROWTH + (min(40, LR * (1 + LRM)) - MIN_LIFE_RATING_FOR_GROWTH) * LIFE_RATING_GROWTH_BONUS + population_growth + pop_growth + global_population_growth/10
    BASE_POPGROWTH: defines.pops.BASE_POPGROWTH
    min(40,: Hardcoded limit to life rating.Reasoning unknown.
    LR: Province life rating
    1+LRM: Life rating modifier = sum of life_rating modifiers
    MIN_LIFE_RATING_FOR_GROWTH: defines.pops.MIN_LIFE_RATING_FOR_GROWTH
    LIFE_RATING_GROWTH_BONUS: defines.pops.LIFE_RATING_GROWTH_BONUS
    population_growth: Sum of population_growth modifiers
    pop_growth: Sum of pop_growth modifiers
    global_population_growth/10: Sum of global_population_growth modifiers
  Attitudes:
    Consciousness from literacy: defines.pops.CON_LITERACY * Plurality * POP literacy * (1 + literacy_con_impact)
    Monthly literacy change:
      formula: defines.pops.LITERACY_CHANGE_SPEED * local clergy factor * (1 + education_efficiency) * (1 + education_efficiency_modifier) * educational spending slider
      local clergy factor: ((clergy POPs in province / total POPs in province) - defines.pops.BASE_CLERGY_FOR_LITERACY) / (defines.pops.MAX_CLERGY_FOR_LITERACY - defines.pops.BASE_CLERGY_FOR_LITERACY)
      note: clergy POPs are all pop types with can_reduce_consciousness = yes
  Needs:
    Base needs scalar: (1 + Plurality) * (1 + 2 * Consciousness / defines.pops.PDEF_BASE_CON) * (1 + sum of goods_demand) * defines.pop.BASE_GOODS_DEMAND * POP size / 200000
    Life needs scalar: Base needs scalar * (1 + <strata>_life_needs modifier)
    Invention needs scalar: 1 + number of inventions * defines.pops.INVENTION_IMPACT_ON_DEMAND
    Everyday needs scalar: Base needs scalar * Invention needs scalar * (1 + <strata>_everyday_needs modifier)
    Luxury needs scalar: Base needs scalar * Invention needs scalar * (1 + <strata>_luxury_needs modifier)
  POP income:
    Base life needs costs: Base needs scalar * sum of (life need quantity * good price)
    Pensions: 2 * pension_level * administrative efficiency * social spending slider * Base life needs costs * (1 - effective tax) * POP size / 200000
    Unemployment subsidies: 2 * unemployment_benefit * administrative efficiency * social spending slider * Base life needs costs * (1 - effective tax) * POP size / 200000
    Wages:
      Minimum (worker) wage: 2 * minimum_wage * administrative efficiency * Base life needs costs * (1 - effective tax) * POP size / 200000
      RGO wages:
        Owners:
          if minimum worker wages > normal worker wage:
            formula: (RGO income - total worker income) * owner POP size / n_owners_in_state * (1 - effective tax) 
          else:
            formula: RGO income * min(0.5, 2 * n_owners_in_state / n_workers) * owner POP size / n_owners_in_state * (1 - effective tax) 
            n_owners_in_state: total size of owner POPs in state
            n_workers: number of employed workers in RGO
            min(0.5: Hardcoded maximum of half the RGO income.
            2 *: Hardcoded value.
        Workers:
          if is_slave: 0
          else:
            if minimum wage > normal wage:
              formula: min(minimum wage, RGO income * employed workers in POP / total non-slave employed workers) * (1 - effective tax) 
            else:
              formula: RGO income * max(0.5, 1 - 2 * n_owners_in_state / n_workers) * employed workers in POP / total non-slave employed workers * (1 - effective tax) 
              n_owners_in_state: total size of owner POPs in state
              n_workers: number of employed workers in RGO
              max(0.5: Hardcoded minimum of half the RGO income.
              2 *: Hardcoded value.
Scores:
  Industrial power:
    formula: sum of investment scores + sum of state factory scores
    investment score: money_invested * defines.country.INVESTMENT_SCORE_FACTOR / 100
    state factory score:
      if n_workers > 0:
        formula: sum_factory_levels_in_state * max(0.2, min(4, floor(n_workers_in_state / 100) * 400 / total_factory_jobs_in_state))
        sum_factory_levels_in_state: sum of factory levels in the state
        max(0.2: Hardcoded minimum score per factory level.
        min(4: Hardcoded maximum score per factory level.
        floor(n_workers_in_state / 100): Hardcoded number step.
        400: Hardcoded value.
        n_workers_in_state: Total size of POPs in state (employed or not) where POP type has `can_work_factory = yes`.
        total_factory_jobs_in_state: Sum of (factory level * workforce), defined in /common/production_types.txt.
      else: 0
  Military power:
    formula: soldier & army score + capital ship score + leader score
    soldier & army score:
      formula: disarmed penalty * regular army size * supply consumption * sum unit stats / (7 * (1 + n_unit_types))
      disarmed penalty:
        if is_disarmed: defines.diplomacy.DISARMAMENT_ARMY_HIT
        else: 1
      regular army size: min(4 * number of deployed non-mobilised regiments, possible regiment count)
      supply consumption: From army tab, not unit types.
      sum unit stats: Sum of ((attack + defence + land_attack_modifier + land_defense_modifier) * discipline) for each land unit type (including locked).
      n_unit_types: Number of land unit types (including locked).
      7*: Hardcoded value.
    capital ship score:
      formula: sum ship stats / 250
      sum ship stats: Sum of ((hull + naval_defense_modifier) * (gun_power + naval_attack_modifier)) for each capital ship instance.
      /250: Hardcoded value.
    leader score: min(number of admirals + number of generals, number of deployed non-mobilised regiments)