![]() |
Formulas
|
This document describes all formulas and processes used in PHost. It is intended for players who do not leave anything to chance. If you believe that some aspect of PHost operation should be documented in this file but is not, send mail to the PHost group and bring this to our attention.
The sequence of events is documented on the Host Sequence page.
This document is organized by initiator of an action. For example, Pillage is a ship mission, so it is documented in the ships section. Combat is an exception because it applies to ships as well as planets.
Variable names (Hull_mass, Native_race, ...) should be self-explanatory. We use common arithmetic notation. In particular, / is a floating-point division.
Configuration options are specified verbatim, with links to their description. Eff_ConfigOption denotes the value of the ConfigOption modified by experience modifiers EModConfigOption.
Internally, PHost often uses people counts for populations, which were also used in the older documentation. For this document, numbers have been converted to the the more familiar clans. Since VGA Planets does not support fractional clans, PHost truncated after each step anyway.
When a series of "if..." sentences is given, take the first applicable one.
Trunc(X) | Truncate X to integer (remove fractional part) |
Round(X) | Round X to integer (round towards nearest integer; round up if ends in .5 exactly) |
ERnd(X) | Round X to integer (round towards nearest integer; round towards nearest even number if ends in .5 exactly) |
Ceil(X) | Next-largest integer (round up if there is any fractional part) |
Sqrt(X) | Square-root of X |
Exp(X) | Exponential of X (2.7182^X) |
Ln(X) | Natural logarithm of X |
Random(X) | Random number, between 0 (inclusive) up to X (not inclusive). For example, Random(3) yields one of 0, 1, 2. |
PI | The number PI = 3.14159265358979323846 |
Ships burn fuel after movement. If the ship has less fuel, nothing bad will happen, but the ship will end up without fuel afterwards.
Fuel_burned_per_turn = Ceil(Ship_hull_mass * FuelUsagePerTurnFor100KT / 100)
Ships burn fuel after each fight. If the ship has less fuel, nothing bad will happen, but the ship will end up without fuel afterwards.
Fuel_burned_per_fight = Ceil(Ship_hull_mass * FuelUsagePerFightFor100KT / 100)
Klingon Pillage: Ships that do Pillage will plunder planetary households to get cash and supplies. They will then kill people which makes the population unhappy.
Supplies_made = Trunc((Colonist_clans + Native_clans) / 100) Money_made = Trunc((Colonist_clans + Native_clans) / 100) Colonist_clans_survived = Trunc(Colonist_clans * 0.8 - 20) Native_clans_survived = Trunc(Native_clans * 0.8 - 120) Colonist_happy_change = -10 Native_happy_change = -10
RGA: Ships that do Rebel Ground Attack will destroy planetary resources. They will then kill colonists, which makes them unhappy. Sarcastic natives will laugh at unhappy colonists.
Money_remaining = Trunc(Money * 0.7) Supplies_remaining = Trunc(Supplies * 0.6) Defense_remaining = Trunc(Defense_posts * 0.8) Mines_remaining = Trunc(Mines * 0.4) Factories_remaining = Trunc(Factories * 0.7) Colonist_clans_survived = Trunc(Colonist_clans * 0.8) Colonist_happy_change = -60 Native_happy_change = +40
Large meteors kill people and make them unhappy. Meteor showers have no effect on the population.
Colonists_survived = Colonists * (Random(91)+10) / 100 Colonist_happiness_change = -(Random(31) + 50) Natives_survived = Natives * (Random(100)+1) / 100 Native_happiness_change = -(Random(31) + 50)
In simple words, up to 90% of the colonists and up to 99% of the natives die, and they lose 50 to 80 happiness points. The mineral amounts added to the planet's core (not surface!) are configurable (LargeMeteorOreRanges, MeteorShowerOreRanges).
Maximum: The maximum number of structures you can build on a planet depends on the population of the planet.
Maximum_mines = Colonist_clans ...if Colonist_clans < 200 Round(200 + Sqrt(Colonist_clans - 200)) ...if Colonist_clans >= 200 Maximum_factories = Colonist_clans ...if Colonist_clans < 100 Round(100 + Sqrt(Colonist_clans - 100)) ...if Colonist_clans >= 100 Maximum_defense_posts = Colonist_clans ...if Colonist_clans < 50 Round(50 + Sqrt(Colonist_clans - 50)) ...if Colonist_clans >= 50
Note that you need not permanently fulfill these conditions. You can build factories and beam off clans to a ship. Excess buildings will decay at a rate of StructureDecayPerTurn.
Buildings affect your visibility to Sensor Sweep.
Industry_detection_chance = 0% ...if Mines < MinesForDetectable and Factories < FactoriesForDetectable 0% ...if Defense >= DefenseForUndetectable 100% - (Defense / DefenseForUndetectable * 100%) ...in all other cases Industry_level_reported = "minimal" ...if (Mines + Factories) < 30 "light" ...if (Mines + Factories) < 60 "moderate" ...if (Mines + Factories) < 90 "substantial" ...if (Mines + Factories) < 120 "heavy" ...if (Mines + Factories) >= 120 Bioscan_detection_chance = 0% ...if Defense >= 20 0% ...if ship does not have bioscanner (of course :-) 100% ...if ship has full bioscanner 20% ...otherwise
Supplies: Supplies are produced by factories, or by Bovinoid natives.
Supplies_made = Trunc((Factory_contribution + Bovinoid_contribution) * ProductionRate) / 100) ...where Factory_contribution = Factories Bovinoid_contribution = Min(Trunc(Native_clans / 100), Colonist_clans) ...if natives are Bovinoid 0 ...otherwise
Taxation: Taxes are collected from colonists and natives.
Taxes_collected = Taxes_from_colonists + Taxes_from_natives ...at most MaxPlanetaryIncome Taxes_from_colonists = Round(Round(Colonist_clans * Colonist_tax / 1000) * ColonistTaxRate / 100) ...if Colonist_happiness >= 30 0 ...if Colonist_happiness < 30 Taxes_from_natives = 0 ...if Native_happiness < 30 0 ...if natives are Amorphous Round(Max(Colonist_clans, Natives_due) * IF * NativeTaxRate / 100) ...where Natives_due = Round(Native_clans * Native_gov_number * Native_tax / 5000) ...where IF = 2 if natives are insectoid, IF = 1 otherwise
The Native_gov_number is tabulated in the Planet Rules section (e.g. 6 for Monarchy).
Happiness: Taxation changes happiness. Note that happiness changes occur before taxation. If the happiness before this stage is below 30, taxes are set to zero (and new happiness is computed according to this rate).
Colonist_happiness_change = Trunc(10 - Sqrt(Colonist_clans / 10000) - Abs(Temperature - Target_temperature) / Temp_divisor - (Mines + Factories) / 300 - Colonist_tax * 0.8) ...where Target_temperature = 100 and Temp_divisor = 66 if owner is Crystal and CrystalsPreferDeserts is on ...where Target_temperature = 50 and Temp_divisor = 33 otherwise Native_happiness_change = Trunc(5 + Native_gov_factor / 2 - Sqrt(Native_clans / 10000) - (Mines + Factories) / 200 - Native_tax * 0.85) ...plus 10 if natives are Avian
Again, the Native_gov_number is tabulated in the Planet Rules section (e.g. 6 for Monarchy, yielding a value of 6/2 = 3 for the first term).
Happiness is summarized as follows:
Happiness_level = "happy" ...if Happiness >= 90 "calm" ...if Happiness >= 70 "unhappy" ...if Happiness >= 50 "very angry" ...if Happiness >= 40 "rioting" ...if Happiness >= 20 "fighting" ...if Happiness < 20 Happiness_change_level = "hate you" ...if Happiness_change < -5 "angry about you" ...if Happiness_change < 0 "undecided" ...if Happiness_change = 0 "like your leadership" ...if Happiness_change <= 4 "love you" ...if Happiness_change >= 5
Mining: The maximum amount of minerals extracted from a planet's core depends on the mineral density.
Max_minerals_mined = Trunc(Mining_rate * Mine_count / 100) ...where Mining_rate = Trunc(RaceMiningRate * Mineral_density / 100) * RF ...with RF = 2 for Reptilian natives, 1 otherwise Minerals_mined = Min(Max_minerals_mined, Minerals_in_core)
Trans-Uranium Decay: New minerals appear in the planet's core. Note that this happens after mining, so you cannot extract the new minerals the same turn.
New_minerals_in_core = Trunc((TransuraniumDecayRate * Mineral_density + 50) / 100)
Cyborg Assimilation: Cyborgs assimilate natives, and turn them into colonists. One assimilated native clan yields one new cyborg colonist clan.
Native_clans_assimilated =
Trunc(Colonist_clans * BorgAssimilationRate / 100)
...at most Native_clans
Maximum Population: The maximum population for a planet is a fixed number which depends on the planet's climate. With ClimateLimitsPopulation enabled, the maximum population on an ideally-tempered world is 100000 clans (10 million colonists). If configured, supplies help you support more colonists on a planet.
Eff_max_colonist_clans = Max_colonist_clans + Supply_bonus ...if ClimateLimitsPopulation is enabled 250000 ...otherwise (25 million colonists) Max_colonist_clans = Max(Trunc(100000 * Sin(Temperature * PI / 200)), 1) ...if colonists are Crystalline and CrystalsPreferDeserts is enabled and CrystalSinTempBehavior is enabled and Temperature >= 15 3 + Trunc(MaxColTempSlope * Temperature / 100) ...if colonists are Crystalline and CrystalsPreferDeserts is enabled and CrystalSinTempBehavior is enabled and Temperature < 15 Max(1000 * Temperature, 1) ...if colonists are Crystalline and CrystalsPreferDeserts is enabled and CrystalSinTempBehavior is disabled 90000 ...if colonists are Rebel and Temperature < 20 (9 million colonists) 3 + Trunc(MaxColTempSlope * Temperature / 100) ...if Temperature < 15 1 + Trunc((100-Temperature) * MaxColTempSlope / 100) ...if Temperature > 84 ...at least 60 if colonists are Klingon, Robot, Rebel or Colony Trunc(100000 * Sin(Temperature * PI / 100)) ...in all remaining cases Supply_bonus = Trunc(Supplies / 40) ...if AllowEatingSupplies is enabled 0 ...otherwise
Native populations have simpler formulas. The absolute maximum is 15.6 million natives (156000 clans). Supplies do not help you to increase the limit.
Max_native_clans = 156000 ...if ClimateLimitsPopulation is disabled 100000 * Temperature ...if natives are Siliconoid and CrystalsPreferDeserts is enabled and PHost is version 3.3c or newer Trunc(Sin(Temperature * PI / 100) * 156000) ...in all remaining cases
It might be considered a bug that Siliconoids cannot reach the 15.6 million mark with CrystalsPreferDeserts enabled, but changing the formula would again complicate matters even more.
Growth: Growth depends on taxation and climate. Populations will never grow over the limit. The maximum growth rate is 5% per turn.
Colonist_growth_in_clans = Trunc(Round(Colonist_growth_rate * Colonist_clans / 10000) * RaceGrowthRate / 100) ...at most Eff_max_colonist_clans - Colonist_clans Colonist_growth_rate = 0 ...if Colonist_clans >= Eff_max_colonist_clans 0 ...if Colonist_happiness < 70 0 ...if colonists are Crystalline and CrystalsPreferDeserts is enabled and CrystalSinTempBehavior is enabled and Temperature < 15 5 * Sin(Temperature * PI / 200) / (1 + Colonist_tax / 5) ...if colonists are Crystalline and CrystalsPreferDeserts is enabled and CrystalSinTempBehavior is enabled and Temperature >= 15 5 * (Temperature / 100 ) / (1 + Colonist_tax / 5) ...if colonists are Crystalline and CrystalsPreferDeserts is enabled and CrystalSinTempBehavior is disabled 0 ...if Temperature < 15 0 ...if Temperature > 84 5 * Sin(Temperature * PI / 100) / (1 + Colonist_tax / 5) ...in all other cases
Native growth is similar, but here the maximum growth rate is 4%. Natives do not grow on unowned planets(!).
Native_growth_in_clans = Trunc(Round(Native_growth_rate * Native_clans) / 100) ...at most Max_native_clans - Native_clans Native_growth_rate = 0 ...if Native_clans >= Max_native_clans 0 ...if Native_happiness < 70 4 * (Temperature / 100) / (1 + Native_tax / 5) ...if natives are Siliconoids and CrystalsPreferDeserts is enabled and PHost is version 3.3c or newer 4 * Sin(Temperature * PI / 100) / (1 + Native_tax / 5) ...in all other cases
Overpopulation eats supplies: If enabled, colonist overpopulation will eat supplies to survive.
Supply_loss = 0 ...if AllowEatingSupplies is off 0 ...if ClimateLimitsPopulation is off 0 ...if Colonist_clans <= Max_colonist_clans Trunc((Colonist_clans - Max_colonist_clans) / 40 + 1) ...otherwise
If there are fewer supplies than needed, they'll all be used up with no negative consequences.
Climate Deaths: If enabled, colonists and natives over the population limit will die.
Colonist_clans_dying = 0 ...if ClimateLimitsPopulation is off 0 ...if Colonist_clans <= Eff_max_colonist_clans Min(Trunc(Colonist_clans * ClimateDeathRate / 100), Eff_max_colonist_clans - Colonist_clans) ...otherwise Native_clans_dying = 0 ...if ClimateLimitsPopulation is off 0 ...if planet is unowned 0 ...if Native_clans <= Max_native_clans Min(Trunc(Native_clans * NativeClimateDeathRate / 100), Max_native_clans - Native_clans) ...otherwise
If the population exceeds the absolute maximum of 250000
clans (25 million people), the excess clans will die and be
reported as climate deaths, even if
ClimateLimitsPopulation is off.
Eff_max_colonist_clans is computed
after overpopulation-eats-supplies, so it uses the new
(lower) supply amount.
This table shows all actions involving planets. The left column shows the PControl stages, in chronological order. The middle column contains all actions affecting happiness or population (like "taxation happens before growth"), the right-most column contains all actions affecting minerals and buildings (like "beam-up-multiple happens before lfm" (hint, hint)).
Stage | Happiness/Population | Minerals/Industry |
---|---|---|
LargeMeteors, MeteorShowers | Meteors might bring down happiness. | Meteors and meteor showers add minerals to planet core. |
CargoDump | Ground combat | |
Training | Ships gather supplies for training | |
GatherMission | Ships gather stuff | |
SpecialMissions_1 | Lizards Hiss | |
BuildFighters, BuildTorpedoes | Ships gather stuff | |
ShipBuilding_1 | Cloning might consume minerals. | |
DumpOldBaseParts | Starbases recycle old starship parts | |
BaseMissions_1 | Starbases first recycle ships, then maximize defense or load torps onto ships | |
FreeFighters | Starbases build "free" fighters | |
GloryDevices | Glory devices kill people and toast Amorphous natives | Glory devices damage planet |
ColonizeMission | Colonize ships bring clans | Colonize ships bring minerals |
BaseMissions_2 | Starbases refuel ships or unload them | |
Combat | Population might be killed in combat. | Defense might be destroyed. |
TerraForming | Terraforming makes environment more pleasant for inhabitants. | |
SensorSweep | Sensor Sweep might discover planets according to their industry. | |
SpecialMissions_2 | Pillage / RGA might make people unhappy | Pillage / RGA will destroy stuff, Dark Sense reports amounts afterwards |
PlanetaryProduction | Mining, supply production, then trans-uranium decay | |
PlanetaryHappiness | if happiness is 29 or lower, taxes are set to 0. Then, happiness changes. | |
PlanetaryTaxation | Tax collection | |
PlanetaryGrowth | Growth | |
PlanetaryLosses | Climate deaths, then losses through riots | Overpopulation eat supplies, then structure decay, then losses through riots, then Amorphs eating colonists |
ShipBuilding_2 | Cloning might consume minerals. | |
Assimilation | Cyborgs assimilate natives |
The size of the wormhole entry point depends on its mass.
Wormhole_radius = (Wormhole_mass ^ (WrmEntryPowerX100 / 100)) / 2
Note that PHost uses the exact fractional value internally. Ufos will report Trunc(Wormhole_radius) (versions up to 3.3d always report 5).
Endpoint Movement: Wormhole endpoints move each turn. They move towards their waypoint up to WrmDisplacement lightyears in X/Y direction, and add some random jitter of WrmRandDisplacement.
Endpoint_displacement = Waypoint_displacement + Random_displacement ...where Random_displacement = Random(1 + 2*WrmRandDisplacement) - WrmRandDisplacement Waypoint_displacement = Waypoint_position - Endpoint_position ...at most WrmDisplacement ...at least -WrmDisplacement
Size changes: Wormholes change their mass and instability each turn.
Mass_change = WrmMassAdd + Random(1 + 2*WrmRandMass) - WrmRandMass Instability_change = -WrmStabilityAddX10 / 10 + Random(1 + 2*WrmRandStability) - WrmRandStability
The mass is an integer in the range 1..32767, the instability is a possibly fractional value in range 0..100. Note that if the mass drops to zero by this process, the wormhole dies, and PHost will set the start and end coordinates to (0,0).
Let Ship_dist be the distance between the scanning ship and the center of the wormhole entry point (the X,Y from wormhole.txt).
Deterministic Scanning: A ship sees all wormholes for which Ship_dist <= WrmScanRange. A ship with the ScansAllWormholes function sees all wormholes for which Ship_dist <= 2 * WrmScanRange. These rules are only applied if WrmScanRange is not 0.
Probabilistic Scanning: The chance to see a wormhole depends on its mass.
Detection_radius = 10 * Wormhole_mass ^ (1/3) Detection_chance = 100% ...if Ship_dist <= Detection_radius (4 - (Ship_dist/Detection_radius)^2) * 33.3% ...if Detection_radius < Ship_dist <= 2*Detection_radius 0% ...if Ship_dist > 2*Detection_radius
For every wormhole, a dice is rolled.
Ships must be within Wormhole_radius lightyears from the endpoint's center to enter a wormhole.
Wormhole travel emposes some stress on the wormhole. The higher the stress, the higher the chance of a travel failure.
Wormhole_stress = 0 ...if Ship_mass < Wormhole_mass (Ship_mass / Wormhole_mass - 1)^2 ...otherwise Travel_failure_odds = Wormhole_stress + Wormhole_instability + (Wormhole_stress*Wormhole_instability / 10) Travel_failure_figure = Random(100) Travel_fuel_usage = Fuel_usage(Equiv_distance, WrmTravelWarpSpeed) ...where Equiv_distance = Wormhole_distance / WrmTravelDistDivisor
Possible outcomes of wormhole travel:
Travel_fuel_usage > Fuel Travel fails: New_ship_X = 1000 + Random(2001) New_ship_Y = 1000 + Random(2001) Damage_taken = 25 + Random(75) Travel_fuel_usage <= Fuel and Travel_failure_figure >= Travel_failure_odds Safe travel: New_ship_X = Endpoint_X - 10 + Random(21) New_ship_Y = Endpoint_Y - 10 + Random(21) Damage_taken = 0 Travel_fuel_usage <= Fuel and Travel_failure_figure < Travel_failure_odds Successful travel with damage taken: New_ship_X = Endpoint_X - 10 + Random(21) New_ship_Y = Endpoint_Y - 10 + Random(21) Damage_taken = (Travel_failure_odds - Travel_failure_figure) ^ 2
The wormhole instability provides a rating for the safety of this wormhole. It is summarized and reported to players using the following levels:
Wormhole_stability_rating = "very stable" ...if Wormhole_instability <= 5 "stable" ...if Wormhole_instability <= 15 "mostly stable" ...if Wormhole_instability <= 30 "unstable" ...if Wormhole_instability <= 50 "very unstable" ...if Wormhole_instability <= 80 "completely unstable" ...otherwise
Trunc(100 - 2*Damage/3) if ship is Lizard Trunc(100 - Damage) otherwise
Hull_mass + Trunc(ESB_Rate * Engine_cost / 100) ...plus 50 if ship is FedThe Engine_cost is the monetary cost of one engine of the ship. The ESB_Rate is the sum of the following components:
Beam_count = Ship_beams if ship is Fed Min(Ship_beams, Max_beams - Trunc(Max_beams * Damage / Divisor) Tube_count = Ship_tubes if ship is Fed Min(Ship_tubes, Max_tubes - Trunc(Max_tubes * Damage / Divisor) Bay_count = Ship_bays if ship is Fed Max_bays - Trunc(Max_bays * Ship_damage / Divisor) Divisor = 150 if ship is Lizard 100 otherwiseMax_beams, Max_tubes and Max_bays are the maximum amounts allowed by the ship's hull.
A planet's defense is reduced if the planet gets damaged.
Eff_Planet_Defense = Trunc(Planet_Defense * (100 - Damage) / 100) Eff_Base_Defense = Trunc(Base_Defense * (100 - Damage) / 100) Eff_Total_Defense = Trunc((Base_Defense + Planet_Defense) * (100 - Damage) / 100)
A base's tech level is reduced if the base gets damaged. Here's the formula for beam tech, it applies to the other areas as well.
Eff_Beam_Tech = Beam_Tech ...at most Trunc((100 - Base_damage) / 10) ...at least 1
Planet's equipment in combat:
Combat_mass = 100 + Eff_Planet_Defense ...plus Eff_Base_Defense if base exists Beam_type = Round(Sqrt(Eff_Planet_Defense / 2)) if no base Max(above, Eff_Beam_Tech) if base present Beam_count = Round(Sqrt(Eff_Total_Defense / 3)) ...at most 10 if AllowAlternativeCombat is off ...at most 20 if AllowAlternativeCombat is on Torp_type = Round(Sqrt(Eff_Planet_Defense / 2)) if no base Max(above, Eff_Torp_Tech) if base present Tube_count = Round(Sqrt(Eff_Total_Defense / 4)) ...at most 20 Torp_count = Tube_count * PlanetaryTorpsPerTube ...plus Trunc(Base_torp_cost / Torp_money_cost(Torp_type)) if base present ...at most 255 Base_torp_cost = Torp_money_cost(1) * Torps_in_storage(1) + Torp_money_cost(2) * Torps_in_storage(2) ... + Torp_money_cost(10) * Torps_in_storage(10)
Beam_hit_odds = Eff_BeamHitOdds + Trunc((Beam_Kill_Power + Beam_Expl_Power) * Eff_BeamHitBonus / 100) Beam_recharge_rate = BeamRechargeRate + Trunc((Beam_Kill_Power + Beam_Expl_Power) * Eff_BeamRechargeBonus / 100) Beam_recharge_per_tick = Random(Beam_recharge_rate) Torp_hit_odds = Eff_TorpHitOdds + Trunc((Torp_Kill_Power + Torp_Expl_Power) * Eff_TorpHitBonus Torp_recharge_rate = Eff_TubeRechargeRate + Trunc((Torp_Kill_Power + Torp_Expl_Power) * Eff_TubeRechargeBonus Torp_recharge_per_tick = Random(Torp_recharge_rate) Bay_recharge_rate = Eff_BayRechargeRate + Eff_BayRechargeBonus * Num_Bays Bay_recharge_per_tick = Random(Bay_recharge_rate)
Eff_XXX means the effective value of a configuration option, which consists of the actual configuration value plus the experience modifier of the unit using the weapon.
Every weapon hit is defined by three values:
Beams: The Expl_Power and Kill_Power are taken from the weapon definition. A beam emits death rays if its Expl_Power is zero. If the owner of the weapon is Privateer, the Kill_Power is tripled. The beam's charge affects its power; a beam fired at charge 600 has only 60% of its normal power.
Torpedoes: The Expl_Power and Kill_Power are taken from the weapon definition. If AllowAlternativeCombat is off, the values are doubled (note that some clients already display the doubled values). A torpedo emits death rays if its Expl_Power is zero.
Fighters: The Expl_Power and Kill_Power is defined by FighterBeamExplosive and FighterBeamKill, respectively. Fighters never fire death rays.
Shield_damage = (Expl_Power * Eff_ShieldDamageScaling + Kill_Power * Eff_ShieldKillScaling) / (Mass + 1) if AllowAlternativeCombat is on = Trunc(above + 1.5) if AllowAlternativeCombat is off Hull_damage = (Expl_Power * Eff_HullDamageScaling) / (Mass + 1) if AllowAlternativeCombat is on = Trunc(1.5 + (Shield_damage * Eff_HullDamageScaling / (Mass + 1)) if AllowAlternativeCombat is off Crew_killed = (Kill_Power * Eff_CrewKillScaling) / (Mass + 1) if AllowAlternativeCombat is on = Trunc(above + 0.5) if AllowAlternativeCombat is off ...at least 1 if AllowAlternativeCombat is off and the weapon emits Death Rays.
Eff_XXX means the effective value of a configuration option, which consists of the actual configuration value plus any experience modifier of the unit being hit (these are the defensive bonuses).
Last updated 20 March 2004.