pnwkit 3.0 - v4.3.0
    Preparing search index...

    Class Utilities

    Collection of utility functions for Politics & War calculations and data transformations.

    Provides helper functions for:

    • Converting project bits to boolean values
    • Calculating city costs based on city count
    • Other game-related calculations
    const utils = new Utilities();

    // Check if nation has a specific project
    const hasProject = utils.convertBitsToProject(projectBits, projectNumber);

    // Calculate cost for next city
    const cost = utils.cityCost(cityCount, top20Average);
    Index
    ageBonus: (cityAge: number) => number = ageBonus

    Type Declaration

      • (cityAge: number): number
      • Calculates the age bonus modifier for a city based on its age.

        Parameters

        • cityAge: number

          The age of the city in turns (must be non-negative)

        Returns number

        The age bonus modifier

        Error if cityAge is negative

    airstrikeSim: (
        attackingAircraft: number,
        defendingAircraft: number,
        attacks: number,
        attackType: AirstrikeType,
        defendingSoldiers?: number,
        defendingTanks?: number,
        defendingShips?: number,
        defendingCityInfrastructure?: number,
        attackerWarPolicy?: WarPolicy,
        defenderWarPolicy?: WarPolicy,
        warType?: WarType,
    ) => AirstrikeSimResult = airstrikeSim

    Type Declaration

      • (
            attackingAircraft: number,
            defendingAircraft: number,
            attacks: number,
            attackType: AirstrikeType,
            defendingSoldiers?: number,
            defendingTanks?: number,
            defendingShips?: number,
            defendingCityInfrastructure?: number,
            attackerWarPolicy?: WarPolicy,
            defenderWarPolicy?: WarPolicy,
            warType?: WarType,
        ): AirstrikeSimResult
      • Simulates one or more airstrikes and returns the average losses for both sides, the average infrastructure destroyed, and the probability of each victory type.

        Each airstrike resolves as 3 rolls. Every roll each side generates a value between 40% and 100% of its airforce value (Aircraft * 3); the side with the higher value wins the roll. The number of rolls won determines the victory type:

        3 wins → Immense Triumph, 2 → Moderate Victory, 1 → Pyrrhic Victory, 0 → Utter Failure.

        Aircraft casualties accrue each roll from the opponent's roll value:

        • Dogfight (target Aircraft): attacker loses roll * 0.01, defender loses roll * 0.018337
        • Any other target: attacker loses roll * 0.015385, defender loses roll * 0.009091

        Targeted units killed (soldiers/tanks/ships) use the base formula: Killed = ROUND(MAX(MIN(Enemy Units, Enemy Units * capRate + capFlat, (Att Aircraft - Def Aircraft * 0.5) * coeff * RAND(0.85, 1.05)), 0)) scaled by the victory type: Immense Triumph 100%, Moderate 70%, Pyrrhic 40%, Utter Failure 0% (no targeted units are killed on a failure).

        Infrastructure destroyed uses: Infra = MAX(MIN((Att Aircraft - Def Aircraft * 0.5) * 0.35353535 * RAND(0.85, 1.05) * (wins / 3), City Infrastructure * 0.5 + 100), 0) (note the wins / 3 scaling differs from the unit-kill scaling), reduced to 1/3 for any airstrike that is not explicitly targeting infrastructure, then multiplied by the war-type factor (see warTypeInfraMultiplier) and the combined war-policy factor (see airstrikeInfraPolicyMultiplier).

        Parameters

        • attackingAircraft: number

          The attacker's aircraft count

        • defendingAircraft: number

          The defender's aircraft count

        • attacks: number

          Number of airstrikes to simulate (results are averaged over these)

        • attackType: AirstrikeType

          The airstrike target (see AirstrikeType)

        • defendingSoldiers: number = 0

          The defender's soldiers (only used when targeting soldiers)

        • defendingTanks: number = 0

          The defender's tanks (only used when targeting tanks)

        • defendingShips: number = 0

          The defender's ships (only used when targeting ships)

        • defendingCityInfrastructure: number = 0

          The targeted city's infrastructure (drives the infra-damage cap)

        • OptionalattackerWarPolicy: WarPolicy

          The attacker's war policy (offensive infra modifier)

        • OptionaldefenderWarPolicy: WarPolicy

          The defender's war policy (defensive infra modifier)

        • warType: WarType = WarType.ORDINARY

          The war type (offensive infra modifier; defaults to Ordinary)

        Returns AirstrikeSimResult

        The averaged AirstrikeSimResult across all simulated airstrikes

        Error if aircraft counts are negative, attacks is less than 1, or the attack type is invalid

        const result = airstrikeSim(1000, 200, 10000, AirstrikeType.SOLDIERS, 15000, 0, 0, 2000, WarPolicy.ATTRITION, WarPolicy.TURTLE);
        console.log(result.averageUnitsKilled, result.averageInfrastructureDestroyed);
    basePopulation: (infrastructure: number) => number = basePopulation

    Type Declaration

      • (infrastructure: number): number
      • Calculates the base population for a city based on its infrastructure value.

        Parameters

        • infrastructure: number

          The infrastructure value of the city (must be non-negative)

        Returns number

        The base population (100 per infrastructure point)

        Error if infrastructure is negative

    buildingBonus: (currentbuildings: number, maxbuildings: number) => number = buildingBonus

    Type Declaration

      • (currentbuildings: number, maxbuildings: number): number
      • Calculates the building bonus multiplier for food production or other city stats.

        Parameters

        • currentbuildings: number

          The number of relevant buildings currently present in the city.

        • maxbuildings: number

          The maximum number of buildings possible for the city.

        Returns number

        The building bonus multiplier (between 1 and 1.5).

        Formula: bonus = 1 + (0.5 / (maxbuildings - 1)) * (currentbuildings - 1) This scales the bonus linearly from 1 (at 1 building) up to 1.5 (at max buildings).

    cityCost: (
        cityToBuy: number,
        top20Average: number,
        manifestDestiny?: boolean,
        governmentSupportAgency?: boolean,
        bureauOfDomesticAffairs?: boolean,
    ) => number = cityCost

    Type Declaration

      • (
            cityToBuy: number,
            top20Average: number,
            manifestDestiny?: boolean,
            governmentSupportAgency?: boolean,
            bureauOfDomesticAffairs?: boolean,
        ): number
      • Calculate the cost of a new city based on the new formula (effective late February 2025).

        The city cost projects (MP, UP, AUP) were removed and replaced with a dynamic formula that considers the top 20% average city count.

        Parameters

        • cityToBuy: number

          The city number being purchased (e.g., if you have 10 cities, this is 11)

        • top20Average: number

          The average city count of the top 20% of active nations (updated monthly)

        • manifestDestiny: boolean = false
        • governmentSupportAgency: boolean = false
        • bureauOfDomesticAffairs: boolean = false

        Returns number

        The cost in dollars for the next city

        Error if parameters are invalid (not finite, out of range, or produce unsafe results)

        const cost = cityCost(41, 43.2035);
        console.log(cost); // Cost for city 41 with current top20Average
    commerce: (
        superMarkets: number,
        banks: number,
        shoppingMalls: number,
        stadiums: number,
        subway: number,
        internationalTradeCenter?: boolean,
        telecommunicationsSatellite?: boolean,
    ) => number = commerce

    Type Declaration

      • (
            superMarkets: number,
            banks: number,
            shoppingMalls: number,
            stadiums: number,
            subway: number,
            internationalTradeCenter?: boolean,
            telecommunicationsSatellite?: boolean,
        ): number
      • Calculates the commerce value for a city based on the number of various buildings and special infrastructure.

        Building limits:

        • superMarkets: max 4
        • banks: max 6
        • shoppingMalls: max 5
        • stadiums: max 3
        • subway: max 1

        Special infrastructure:

        • internationalTradeCenter: increases max commerce to 115 and adds 1 to commerce
        • telecommunicationsSatellite: increases max commerce to 125 and adds 3 to commerce

        Commerce calculation: (superMarkets * 15) + (banks * 20) + (shoppingMalls * 25) + (stadiums * 10) + (subway * 15)

        • bonus from special infrastructure Final value is capped at maxCommerce.

        Parameters

        • superMarkets: number

          Number of supermarkets (max 4)

        • banks: number

          Number of banks (max 6)

        • shoppingMalls: number

          Number of shopping malls (max 5)

        • stadiums: number

          Number of stadiums (max 3)

        • subway: number

          Number of subways (max 1)

        • internationalTradeCenter: boolean = false

          Whether the city has an International Trade Center (default: false)

        • telecommunicationsSatellite: boolean = false

          Whether the city has a Telecommunications Satellite (default: false)

        Returns number

        The calculated commerce value for the city

        Error if any building value exceeds its limit

        Error if any building value is negative

        const com = commerce(4, 6, 5, 3, 1, true, true);
        console.log(com); // Commerce in a city with maximum buildings and both special infrastructures
    convertBitsToProject: (projectBits: string, projectPosition: number) => boolean = ConvertBitsToProject

    Type Declaration

      • (projectBits: string, projectPosition: number): boolean
      • Check if a nation has a specific project built.

        The Politics & War API stores project data as a bit field where each bit represents whether a project is built. Bits are indexed right-to-left using standard bit shift operations, where position 0 is the rightmost/least significant bit.

        Parameters

        • projectBits: string

          The project_bits string from the API (e.g., "1679868772347")

        • projectPosition: number

          The bit position (0-40) using standard right-to-left indexing

        Returns boolean

        true if the nation has the project, false otherwise

        Error if parameters are invalid

        const hasIronDome = ConvertBitsToProject(data[0].project_bits, 0); // IRON_DOME
        const hasVDS = ConvertBitsToProject(data[0].project_bits, 1); // VITAL_DEFENSE_SYSTEM
        console.log(hasIronDome); // true or false
    crimeDeaths: (crimeRate: number, infrastructure: number) => number = crimeDeaths

    Type Declaration

      • (crimeRate: number, infrastructure: number): number
      • Calculates the number of crime-related deaths in a city.

        Parameters

        • crimeRate: number

          The calculated crime rate

        • infrastructure: number

          The infrastructure value of the city

        Returns number

        The number of crime-related deaths

        Error if any input value is negative

        const deaths = crimeDeaths(5, 50);
        console.log(deaths); // Crime-related deaths for a city with crime rate 5 and infrastructure 50
    crimeRate: (
        commerce: number,
        infrastructure: number,
        policeModifier: number,
    ) => number = crimeRate

    Type Declaration

      • (commerce: number, infrastructure: number, policeModifier: number): number
      • Calculates the crime percentage for a city using the following formula:

        Crime (%) = ((103 - commerce)^2 + (infrastructure * 100)) / 111111 - policeModifier

        Parameters

        • commerce: number

          The commerce value of the city

        • infrastructure: number

          The infrastructure value of the city

        • policeModifier: number

          The police modifier value

        Returns number

        The calculated crime rate

        Error if any input value is negative

        const crime = crimeRate(80, 50, 5);
        console.log(crime); // Crime rate for a city with commerce 80, infrastructure 50, and police modifier 5
    diseaseDeaths: (diseaseRate: number, basePopulation: number) => number = diseaseDeaths

    Type Declaration

      • (diseaseRate: number, basePopulation: number): number
      • Calculates the number of disease deaths in a city.

        Parameters

        • diseaseRate: number

          The calculated disease rate

        • basePopulation: number

          The base population of the city

        Returns number

        The number of disease deaths

        Error if any input value is negative

        const deaths = diseaseDeaths(0.05, 50000);
        console.log(deaths); // Disease-related deaths for a city with disease rate 0.05 and base population 50000
    diseaseRate: (
        populationDensity: number,
        basePopulation: number,
        pollutionModifier: number,
        hospitalModifier: number,
    ) => number = diseaseRate

    Type Declaration

      • (
            populationDensity: number,
            basePopulation: number,
            pollutionModifier: number,
            hospitalModifier: number,
        ): number
      • Calculates the disease rate for a city using the following formula:

        Disease Rate = ((((populationDensity^2) * 0.01) - 25) / 100) + (basePopulation / 100000) + pollutionModifier - hospitalModifier

        Parameters

        • populationDensity: number

          The population density of the city

        • basePopulation: number

          The base population of the city

        • pollutionModifier: number

          The pollution modifier value

        • hospitalModifier: number

          The hospital modifier value

        Returns number

        The calculated disease rate

        Error if any input value is negative

        const disease = diseaseRate(1000, 50000, 5, 3);
        console.log(disease); // Disease rate for a city with population density 1000, base population 50000, pollution modifier 5, and hospital modifier 3
    espionageOdds: (
        safetyLevel: number,
        yourSpies: number,
        enemySpies: number,
        type: SabotageType,
    ) => number = espionageOdds

    Type Declaration

      • (
            safetyLevel: number,
            yourSpies: number,
            enemySpies: number,
            type: SabotageType,
        ): number
      • Estimates the success odds (%) of an espionage operation.

        Initial Odds = (safetyLevel * 25) + ((yourSpies * 100) / ((enemySpies * 3) + 1)), then divided by the operation's SabotageType difficulty factor.

        Parameters

        • safetyLevel: number

          The attacker's espionage safety level (0-3)

        • yourSpies: number

          The attacker's number of spies

        • enemySpies: number

          The defender's number of spies

        • type: SabotageType

          The espionage operation type (see SabotageType)

        Returns number

        The estimated success odds

        const odds = espionageOdds(3, 50, 30, SabotageType.TANKS);
        console.log(odds); // Estimated success odds for sabotaging tanks
    espionageRange: (score: number) => { max: number; min: number } = espionageRange

    Type Declaration

      • (score: number): { max: number; min: number }
      • Calculates the espionage range for a nation — the span of nation scores it can run espionage operations against (40% to 250% of its own score).

        Parameters

        • score: number

          The nation's score

        Returns { max: number; min: number }

        The minimum and maximum targetable enemy score

        const range = espionageRange(1000);
        console.log(range); // { min: 400, max: 2500 }
    foodProduction: (
        farms: number,
        land: number,
        radiationModifier: number,
        massIrrigation?: boolean,
        season: Season,
        isInAntarctica?: boolean,
    ) => number = foodProduction

    Type Declaration

      • (
            farms: number,
            land: number,
            radiationModifier: number,
            massIrrigation?: boolean,
            season: Season,
            isInAntarctica?: boolean,
        ): number
      • Calculates the food production for a city based on farms, land, radiation index, irrigation, and season.

        Parameters

        • farms: number

          Number of farms in the city

        • land: number

          Amount of land in the city

        • radiationModifier: number

          Radiation index modifier

        • massIrrigation: boolean = false

          Whether mass irrigation is enabled (default: false)

        • season: Season

          The current season ('spring', 'summer', 'fall', 'winter')

        • isInAntarctica: boolean = false

        Returns number

        The calculated food production value

        Error if any input value is negative

        const food = foodProduction(10, 5000, 0.05, true, 'summer');
        console.log(food); // Food production for a city with 10 farms, 5000 land, radiation modifier 0.05, mass irrigation enabled, and summer season
    groundAttackSim: (
        attackingSoldiers: number,
        attackingTanks: number,
        defendingSoldiers: number,
        defendingTanks: number,
        attacks: number,
        attackerMunitions?: boolean,
        defenderMunitions?: boolean,
        defendingPopulation?: number,
        defendingCityInfrastructure?: number,
        attackerWarPolicy?: WarPolicy,
        defenderWarPolicy?: WarPolicy,
        warType?: WarType,
        defendersMoney?: number,
    ) => GroundSimResult = groundAttackSim

    Type Declaration

      • (
            attackingSoldiers: number,
            attackingTanks: number,
            defendingSoldiers: number,
            defendingTanks: number,
            attacks: number,
            attackerMunitions?: boolean,
            defenderMunitions?: boolean,
            defendingPopulation?: number,
            defendingCityInfrastructure?: number,
            attackerWarPolicy?: WarPolicy,
            defenderWarPolicy?: WarPolicy,
            warType?: WarType,
            defendersMoney?: number,
        ): GroundSimResult
      • Simulates one or more ground battles and returns the average soldier and tank losses for both sides, the average infrastructure destroyed, and the probability of each victory type.

        Each side's forces are converted to army values: soldier value = soldiers * (using munitions ? 1.75 : 1) tank value = tanks * 40 The defender additionally gains population / 400 resisting army strength on its soldier value.

        Each battle resolves as 3 rolls. Every roll, each side rolls its soldier value and its tank value independently between 40% and 100%; the attacker's total roll (AR = soldier + tank) is compared to the defender's (DR). The number of rolls the attacker wins (AR > DR) determines the victory type:

        3 wins → Immense Triumph, 2 → Moderate Victory, 1 → Pyrrhic Victory, 0 → Utter Failure.

        Casualties accrue each roll from the opponent's rolls: soldier losses = opponent soldier roll * 0.0084 + opponent tank roll * 0.0092 tank losses = opponent soldier roll * s + opponent tank roll * t, where the winning side uses (0.0004060606, 0.00066666666) and the losing side uses (0.00043225806, 0.00070967741).

        Infrastructure destroyed uses: Infra = MAX(MIN(((Att Soldiers - Def Soldiers * 0.5) * 0.000606061 + (Att Tanks - Def Tanks * 0.5) * 0.01) * RAND(0.85, 1.05) * (wins / 3), City Infrastructure * 0.2 + 25), 0) multiplied by the war-type factor (see warTypeInfraMultiplier) and the combined war-policy factor (see infraPolicyMultiplier).

        Parameters

        • attackingSoldiers: number

          The attacker's soldier count (must be at least 50)

        • attackingTanks: number

          The attacker's tank count

        • defendingSoldiers: number

          The defender's soldier count

        • defendingTanks: number

          The defender's tank count

        • attacks: number

          Number of ground battles to simulate (results are averaged over these)

        • attackerMunitions: boolean = true

          Whether the attacker's soldiers fight with munitions (1.75x vs 1x value)

        • defenderMunitions: boolean = true

          Whether the defender's soldiers fight with munitions (1.75x vs 1x value)

        • defendingPopulation: number = 0

          The defender's population (adds population / 400 resisting strength)

        • defendingCityInfrastructure: number = 0

          The targeted city's infrastructure (drives the infra-damage cap)

        • OptionalattackerWarPolicy: WarPolicy

          The attacker's war policy (infra and loot modifier)

        • OptionaldefenderWarPolicy: WarPolicy

          The defender's war policy (infra and loot modifier)

        • warType: WarType = WarType.ORDINARY

          The war type (infra and loot modifier; defaults to Ordinary)

        • defendersMoney: number = 0

          The defender's on-hand money (drives the loot amount and its caps)

        Returns GroundSimResult

        The averaged GroundSimResult across all simulated battles

        Error if any count is negative, attacks is outside the 1-1000 range, or fewer than 50 attacking soldiers

        const result = groundAttackSim(10000, 500, 8000, 400, 1000, true, true, 100000, 2000, WarPolicy.ATTRITION, WarPolicy.TURTLE, WarType.ATTRITION, 50_000_000);
        console.log(result.averageDefenderSoldiersLost, result.averageInfrastructureDestroyed, result.averageLoot);
    hospitalModifier: (
        hospitals: number,
        clinicalResearchCenter?: boolean,
    ) => number = hospitalModifier

    Type Declaration

      • (hospitals: number, clinicalResearchCenter?: boolean): number
      • Calculates the hospital modifier for disease rate reduction. Each hospital reduces disease rate by 2.5, or 3.5 if a Clinical Research Center is present.

        Parameters

        • hospitals: number

          Number of hospitals in the city

        • clinicalResearchCenter: boolean = false

          Whether a Clinical Research Center is present (default: false)

        Returns number

        The hospital modifier value

        Error if the number of hospitals is negative

        const modifier = hospitalModifier(4, true);
        console.log(modifier); // Hospital modifier for 4 hospitals with a Clinical Research Center
    infraCost: (
        startingAmount: number,
        endingAmount: number,
        centerOfCivilEngineering?: boolean,
        advancedEngineeringCorps?: boolean,
        urbanization?: boolean,
        governmentSupportAgency?: boolean,
        bureauOfDomesticAffairs?: boolean,
    ) => number = infraCost

    Type Declaration

      • (
            startingAmount: number,
            endingAmount: number,
            centerOfCivilEngineering?: boolean,
            advancedEngineeringCorps?: boolean,
            urbanization?: boolean,
            governmentSupportAgency?: boolean,
            bureauOfDomesticAffairs?: boolean,
        ): number
      • Calculates the total infrastructure cost between two amounts, applying discounts for various projects.

        Parameters

        • startingAmount: number

          Starting infrastructure amount

        • endingAmount: number

          Ending infrastructure amount

        • centerOfCivilEngineering: boolean = false

          If true, applies 5% or 10% discount with advancedEngineeringCorps

        • advancedEngineeringCorps: boolean = false

          If true, applies additional discount with centerOfCivilEngineering

        • urbanization: boolean = false

          If true, applies discount based on governmentSupportAgency or bureauOfDomesticAffairs

        • governmentSupportAgency: boolean = false

          If true, increases urbanization discount

        • bureauOfDomesticAffairs: boolean = false

          If true, increases urbanization discount further

        Returns number

        Total infrastructure cost after discounts

        // Basic usage
        const cost = infraCost(100, 200);
        // With all discounts
        const discounted = infraCost(100, 200, true, true, true, true, true);
    infraPolicyMultiplier: (attacker?: WarPolicy, defender?: WarPolicy) => number = infraPolicyMultiplier

    Type Declaration

      • (attacker?: WarPolicy, defender?: WarPolicy): number
      • Returns the combined infrastructure-damage multiplier applied to an airstrike from the attacker's and the defender's war policies.

        Attacker (offensive) modifiers:

        • Attrition: +10% infrastructure damage.
        • Blitzkrieg: +10% infrastructure damage (only within the first 12 turns of switching to this policy — pass the policy only while that window is active).

        Defender (damage-taken) modifiers:

        • Turtle: -10% infrastructure damage taken.
        • Moneybags/Covert/Arcane: +5% infrastructure damage taken.

        All other policies have no effect on airstrike infrastructure damage.

        Parameters

        • Optionalattacker: WarPolicy

          The attacker's war policy

        • Optionaldefender: WarPolicy

          The defender's war policy

        Returns number

        The multiplier to apply to the base infrastructure damage

    inverseEspionageRange: (score: number) => { max: number; min: number } = inverseEspionageRange

    Type Declaration

      • (score: number): { max: number; min: number }
      • Calculates the inverse espionage range — given a nation's score, the span of attacker scores that can run espionage against it (the inverse of espionageRange).

        Parameters

        • score: number

          The nation's score

        Returns { max: number; min: number }

        The minimum and maximum attacker score that has this nation in range

        const range = inverseEspionageRange(1000);
        console.log(range); // { min: 2500, max: 400 }
    inverseWarRange: (score: number) => { max: number; min: number } = inverseWarRange

    Type Declaration

      • (score: number): { max: number; min: number }
      • Calculates the inverse war range — given a nation's score, the span of attacker scores that can declare war on it (the inverse of warRange).

        Parameters

        • score: number

          The nation's score

        Returns { max: number; min: number }

        The minimum and maximum attacker score that has this nation in range

        const range = inverseWarRange(1000);
        console.log(range); // { min: 1333.33, max: 400 }
    landCost: (
        startingAmount: number,
        endingAmount: number,
        arableLandAgency?: boolean,
        advancedEngineeringCorps?: boolean,
        rapidExpansion?: boolean,
        governmentSupportAgency?: boolean,
        bureauOfDomesticAffairs?: boolean,
    ) => number = landCost

    Type Declaration

      • (
            startingAmount: number,
            endingAmount: number,
            arableLandAgency?: boolean,
            advancedEngineeringCorps?: boolean,
            rapidExpansion?: boolean,
            governmentSupportAgency?: boolean,
            bureauOfDomesticAffairs?: boolean,
        ): number
      • Calculates the total land cost between two amounts, applying discounts for various projects.

        Parameters

        • startingAmount: number

          Starting land amount

        • endingAmount: number

          Ending land amount

        • arableLandAgency: boolean = false

          If true, applies 5% or 10% discount with advancedEngineeringCorps

        • advancedEngineeringCorps: boolean = false

          If true, applies additional discount with arableLandAgency

        • rapidExpansion: boolean = false

          If true, applies discount based on governmentSupportAgency or bureauOfDomesticAffairs

        • governmentSupportAgency: boolean = false

          If true, increases rapidExpansion discount

        • bureauOfDomesticAffairs: boolean = false

          If true, increases rapidExpansion discount further

        Returns number

        Total land cost after discounts

        // Basic usage
        const cost = landCost(20, 500);
        // With all discounts
        const discounted = landCost(20, 500, true, true, true, true, true);

        Error if the difference between startingAmount and endingAmount exceeds 10,000

        Error if an unexpected error occurs during calculation

        const cost = landCost(20, 500);
        console.log(cost); // Total land cost for the increase from 20 to 500
    lootPolicyMultiplier: (attacker?: WarPolicy, defender?: WarPolicy) => number = lootPolicyMultiplier

    Type Declaration

      • (attacker?: WarPolicy, defender?: WarPolicy): number
      • Returns the combined war-policy loot multiplier from the attacker's and defender's war policies:

        • Defender Moneybags: x0.6 loot.
        • Attacker Pirate: x1.4 loot.
        • Both applicable: they cancel out to x1.0.

        All other policies have no effect on loot.

        Parameters

        • Optionalattacker: WarPolicy

          The attacker's war policy

        • Optionaldefender: WarPolicy

          The defender's war policy

        Returns number

        The multiplier to apply to the base loot

    lootSim: (
        attackingSoldiers: number,
        attackingTanks: number,
        victory: VictoryType,
        defendersMoney: number,
        warType?: WarType,
        attackerWarPolicy?: WarPolicy,
        defenderWarPolicy?: WarPolicy,
    ) => number = lootSim

    Type Declaration

      • (
            attackingSoldiers: number,
            attackingTanks: number,
            victory: VictoryType,
            defendersMoney: number,
            warType?: WarType,
            attackerWarPolicy?: WarPolicy,
            defenderWarPolicy?: WarPolicy,
        ): number
      • Simulates the money looted from a successful ground attack.

        Loot = (Attacking Soldiers * 1.1 + Attacking Tanks * 25.15) * VictoryFactor * RAND(0.8, 1.1) * WarTypeFactor * WarPolicyFactor

        where VictoryFactor is the victory tier (0 for Utter Failure up to 3 for Immense Triumph), the war-type factor comes from warTypeLootMultiplier, and the war-policy factor from lootPolicyMultiplier. The result is capped at 75% of the defender's cash on hand, cannot take their last $1,000,000, and is floored at zero.

        Parameters

        • attackingSoldiers: number

          Number of the attacker's surviving soldiers

        • attackingTanks: number

          Number of the attacker's surviving tanks

        • victory: VictoryType

          The victory tier (see VictoryType)

        • defendersMoney: number

          The defender's on-hand money

        • warType: WarType = WarType.ORDINARY

          The war type (loot modifier; defaults to Ordinary)

        • OptionalattackerWarPolicy: WarPolicy

          The attacker's war policy (loot modifier)

        • OptionaldefenderWarPolicy: WarPolicy

          The defender's war policy (loot modifier)

        Returns number

        The amount of money looted

        const loot = lootSim(5000, 250, VictoryType.IMMENSE_TRIUMPH, 10_000_000, WarType.RAID, WarPolicy.PIRATE);
        console.log(loot); // Money looted on an immense triumph
    missileDamage: (cityInfrastructure: number, populationDensity: number) => number = missileDamage

    Type Declaration

      • (cityInfrastructure: number, populationDensity: number): number
      • Simulates the infrastructure destroyed by a missile strike on a city.

        Infra Destroyed = min( randBetween(300, max(350, populationDensity * 3)), (cityInfrastructure * 0.3) + 100, // city infra limit cityInfrastructure // can't destroy more than the city has )

        Parameters

        • cityInfrastructure: number

          The city's current infrastructure

        • populationDensity: number

          The city's population density

        Returns number

        The amount of infrastructure destroyed

        Error if any input value is negative

        const destroyed = missileDamage(2000, 500);
        console.log(destroyed); // Infrastructure destroyed by a missile
    navalSim: (
        attackingShips: number,
        defendingShips: number,
        attacks: number,
        defendingCityInfrastructure?: number,
        attackerWarPolicy?: WarPolicy,
        defenderWarPolicy?: WarPolicy,
        warType?: WarType,
    ) => NavalSimResult = navalSim

    Type Declaration

      • (
            attackingShips: number,
            defendingShips: number,
            attacks: number,
            defendingCityInfrastructure?: number,
            attackerWarPolicy?: WarPolicy,
            defenderWarPolicy?: WarPolicy,
            warType?: WarType,
        ): NavalSimResult
      • Simulates one or more naval battles and returns the average ship losses for both sides, the average infrastructure destroyed, and the probability of each victory type.

        Each battle resolves as 3 rolls. Every roll each side generates a value between 40% and 100% of its naval value (Ships * 4); the side with the higher value wins the roll. The number of rolls won determines the victory type:

        3 wins → Immense Triumph, 2 → Moderate Victory, 1 → Pyrrhic Victory, 0 → Utter Failure.

        Ship casualties accrue each roll from the opponent's roll value: each side loses (opponent's roll) * 0.01375 ships per roll.

        Infrastructure destroyed uses: Infra = MAX(MIN((Att Ships - Def Ships * 0.5) * 2.625 * RAND(0.85, 1.05) * (wins / 3), City Infrastructure * 0.5 + 25), 0) multiplied by the war-type factor (see warTypeInfraMultiplier) and the combined war-policy factor (see airstrikeInfraPolicyMultiplier — the Attrition/Turtle/Moneybags/Covert/Arcane modifiers apply to naval battles too).

        Parameters

        • attackingShips: number

          The attacker's ship count

        • defendingShips: number

          The defender's ship count

        • attacks: number

          Number of naval battles to simulate (results are averaged over these)

        • defendingCityInfrastructure: number = 0

          The targeted city's infrastructure (drives the infra-damage cap)

        • OptionalattackerWarPolicy: WarPolicy

          The attacker's war policy (offensive infra modifier)

        • OptionaldefenderWarPolicy: WarPolicy

          The defender's war policy (defensive infra modifier)

        • warType: WarType = WarType.ORDINARY

          The war type (offensive infra modifier; defaults to Ordinary)

        Returns NavalSimResult

        The averaged NavalSimResult across all simulated battles

        Error if ship counts are negative or attacks is outside the 1-1000 range

        const result = navalSim(50, 30, 1000, 2000, WarPolicy.ATTRITION, WarPolicy.TURTLE, WarType.ATTRITION);
        console.log(result.averageDefenderShipsLost, result.averageInfrastructureDestroyed);
    nukeDamage: (cityInfrastructure: number, populationDensity: number) => number = nukeDamage

    Type Declaration

      • (cityInfrastructure: number, populationDensity: number): number
      • Simulates the infrastructure destroyed by a nuclear strike on a city.

        Infra Destroyed = min( randBetween(1700, max(2000, populationDensity * 13.5)), (cityInfrastructure * 0.8) + 150, // city infra limit cityInfrastructure // can't destroy more than the city has )

        Parameters

        • cityInfrastructure: number

          The city's current infrastructure

        • populationDensity: number

          The city's population density

        Returns number

        The amount of infrastructure destroyed

        Error if any input value is negative

        const destroyed = nukeDamage(2000, 500);
        console.log(destroyed); // Infrastructure destroyed by a nuclear strike
    policeModifier: (
        policeStations: number,
        specializedPoliceTrainingProgram?: boolean,
    ) => number = policeModifier

    Type Declaration

      • (policeStations: number, specializedPoliceTrainingProgram?: boolean): number
      • Calculates the police modifier for crime rate reduction. Each police station reduces crime rate by 2.5, or 3.5 if a Specialized Police Training Program is present.

        Parameters

        • policeStations: number

          Number of police stations in the city

        • specializedPoliceTrainingProgram: boolean = false

          Whether a Specialized Police Training Program is present (default: false)

        Returns number

        The police modifier value

        Error if the number of police stations is negative

        const modifier = policeModifier(3, true);
        console.log(modifier); // Police modifier for 3 police stations with a Specialized Police Training Program
    pollution: (
        improvements: PollutingImprovements,
        greenTechnologies?: boolean,
        recyclingInitiative?: boolean,
    ) => number = pollution

    Type Declaration

      • (
            improvements: PollutingImprovements,
            greenTechnologies?: boolean,
            recyclingInitiative?: boolean,
        ): number
      • Calculates a city's total pollution index from its improvement counts, summing ImprovementPollution across every improvement and applying national project modifiers. The result is floored at zero.

        National project modifiers:

        • Green Technologies: manufacturing pollution -25%, farm pollution -50%, and subways reduce pollution 25 points more (-45 -> -70).
        • Recycling Initiative: recycling centers reduce 75 instead of 70.

        Parameters

        • improvements: PollutingImprovements

          Improvement counts keyed by lowercase name (e.g. steel_mill)

        • greenTechnologies: boolean = false

          Whether the nation has the Green Technologies project (default: false)

        • recyclingInitiative: boolean = false

          Whether the nation has the Recycling Initiative project (default: false)

        Returns number

        The total pollution index (never negative)

        Error if any improvement count is negative

        const index = pollution({ coal_mine: 10, steel_mill: 5, recycling_center: 4, subway: 1 }, true, true);
        console.log(index); // Total pollution index with both projects applied
    pollutionModifier: (pollutionLIndex: number) => number = pollutionModifier

    Type Declaration

      • (pollutionLIndex: number): number
      • Calculates the pollution modifier for disease rate.

        Parameters

        • pollutionLIndex: number

          The pollution index value

        Returns number

        The pollution modifier value

        Error if the pollution index is negative

        const modifier = pollutionModifier(10);
        console.log(modifier); // Pollution modifier for a pollution index of 10
    population: (
        basePopulation: number,
        diseaseDeaths: number,
        crimeDeaths: number,
        ageBonus: number,
    ) => number = population

    Type Declaration

      • (
            basePopulation: number,
            diseaseDeaths: number,
            crimeDeaths: number,
            ageBonus: number,
        ): number
      • Calculates the actual (displayed) population for a city.

        Population = (Base Population - Disease Deaths - Crime Deaths) * Age Bonus

        Parameters

        • basePopulation: number

          The base population (infrastructure * 100)

        • diseaseDeaths: number

          Population lost to disease (see diseaseDeaths)

        • crimeDeaths: number

          Population lost to crime (see crimeDeaths)

        • ageBonus: number

          The city age bonus modifier (see ageBonus)

        Returns number

        The actual population, floored at zero

        Error if any input value is negative

        const basePop = basePopulation(50); // 5000
        const ageBonusValue = ageBonus(20); // Age bonus for a 20-turn-old city
        const diseaseDeaths = 120;
        const crimeDeaths = 80;
        const pop = population(basePop, diseaseDeaths, crimeDeaths, ageBonusValue);
        console.log(pop); // Actual population after deaths and age bonus
    populationDensity: (population: number, land: number) => number = populationDensity

    Type Declaration

      • (population: number, land: number): number
      • Calculates the population density for a city.

        Parameters

        • population: number

          The total population of the city (must be non-negative)

        • land: number

          The land area of the city (must be greater than zero)

        Returns number

        The population density (population divided by land)

        Error if land is zero or negative, or population is negative

    radiationModifier: (
        continentRadiation: number,
        globalRadiation: number,
        falloutShelter?: boolean,
    ) => number = radiationModifier

    Type Declaration

      • (
            continentRadiation: number,
            globalRadiation: number,
            falloutShelter?: boolean,
        ): number
      • Calculates the radiation index modifier for a city based on continent and global radiation values.

        Parameters

        • continentRadiation: number

          Radiation value for the continent

        • globalRadiation: number

          Global radiation value

        • falloutShelter: boolean = false

        Returns number

        The calculated radiation index modifier

        Error if any input value is negative

        const modifier = radiationModifier(50, 100);
        console.log(modifier); // Radiation index modifier for a continent radiation of 50 and global radiation of 100
    warRange: (score: number) => { max: number; min: number } = warRange

    Type Declaration

      • (score: number): { max: number; min: number }
      • Calculates the war declaration range for a nation — the span of nation scores it can declare war on (75% to 250% of its own score).

        Parameters

        • score: number

          The nation's score

        Returns { max: number; min: number }

        The minimum and maximum declarable enemy score

        const range = warRange(1000);
        console.log(range); // { min: 750, max: 2500 }
    warTypeInfraMultiplier: (warType: WarType) => number = warTypeInfraMultiplier

    Type Declaration

      • (warType: WarType): number
      • Returns the fraction of potential infrastructure damage an attacker deals based on the war type:

        • Ordinary: 50% of potential infrastructure damage.
        • Attrition: 100% of potential infrastructure damage.
        • Raid: 25% of potential infrastructure damage.

        Parameters

        • warType: WarType

          The war type

        Returns number

        The infrastructure-damage multiplier for the attacker

    warTypeLootMultiplier: (warType: WarType) => number = warTypeLootMultiplier

    Type Declaration

      • (warType: WarType): number
      • Returns the war-type loot multiplier — the fraction of potential loot an attacker takes based on the war type:

        • Ordinary: 50% of potential loot.
        • Attrition: 25% of potential loot.
        • Raid: 100% of potential loot.

        (Note this differs from the infrastructure war-type factor, where Attrition is the strongest and Raid the weakest.)

        Parameters

        • warType: WarType

          The war type

        Returns number

        The loot multiplier for the attacker