![]() |
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 fractional 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)
Speed Limit:
Max_speed = 9 ...if ship has Hardened Engines 15 - Trunc(Damage/10) ...if ship owner is Lizards 10 - Trunc(Damage/10) ...otherwise
Fuel usage:
Fuel_usage = Trunc((ERnd(Total_ship_mass/10) * Distance * Engine_fuel_usage) / (10000 * Max_dist)) ...if UseAccurateFuelModel is off Total_ship_mass * (1.0 - Exp(-(Engine_fuel_usage * Distance) / (Max_dist * 100000))) ...if UseAccurateFuelModel is on ...where Max_dist = Warp^2 ...for normal engines Warp^2 * 2 ...for gravitonic engines
Note that the UseAccurateFuelModel formula can yield fractional values. In case ship movement occurs in multiple phases (because the ship hits a mine), these fractional values are added up, and arithmetically rounded at the end. In contrast, non-accurate movement rounds after every step.
Damage from mine hit:
Damage_taken = 100 * MineHitDamageFor100KT / Hull_mass ...for normal mines 100 * WebHitDamageFor100KT / Hull_mass ...for web mines
Ground combat happens when a hostile ship drops colonists on a foreign planet, using the ship-to-planet cargo transporters.
During ground combat, attacking colonists and defenders annihilate each other, subject to their attack and defense ratios, until one party remains.
Ground_attack_result = "attacker wins with Trunc(Result/Attacker_rate) clans remaining" ...if Result >= 0 "defender wins with Trunc(-Result/Defender_rate) clans remaining" ...if Result < 0 ...with Attacker_rate = GroundKillFactor[Ship_owner] Defender_rate = GroundDefenseFactor[Planet_owner] + Planet_defense / 20 Result = (Attacking_clans * Attacker_rate) - (Defending_clans * Defender_rate)
Note that if the result yields 0 clans remaining (maybe due to rounding), the planet gets unowned.
Mine sweeping comes in two flavours: normal sweeping and scooping. Scooping is selected using the msc friendly code or the Scoop Torpedoes extended mission. Mine sweeping scans all minefields in range, and destroys hostile minefields if possible. Mine scooping, in addition, gathers up torpedoes from a minefield owned by the same player as the ship, and turns it back into torpedoes.
Units_swept = Beam_contribution + Fighter_contribution Beam_contribution = Beam_count * Beam_type^2 * Sweep_rate ...with Sweep_rate is WebMineSweepRate or MineSweepRate ...if ship has beams, is within range, and field not hidden by ion storm 0 ...otherwise Fighter_contribution = Fighter_count * FighterSweepRate ...if ship has bays, and is within FighterSweepRange, and minefield is a normal minefield or ship is owned by colonies and AllowColoniesSweepWebs is enabled 0 ...otherwise Torps_scooped = Max(Trunc(Mine_units / Conversion_rate), Free_cargo_room) ...where Conversion_rate = Trunc(Torp_type^2 * UnitsPerTorpRate[Ship_owner] / 100) Units_scooped = Torps_scooped * Conversion_rate
If the Scoop Torpedoes mission is used, the parameter specifies the maximum number of torpedoes to scoop from each applicable minefield, not the total amount.
Torpedo ships can lay mines. The same formulas apply to web laying.
Torps_laid = Min(Torps_available, Trunc((Max_units - Existing_units) / Conversion_rate)) ...0 if Conversion_rate is zero or Existing_units >= Max_units ...where Conversion_rate = Trunc(Torp_type^2 * Min(UnitsPerTorpRate[Ship_owner], UnitsPerTorpRate[Minefield_owner]) / 100) Max_units = MaximumMinefieldRadius[Minefield_owner] ...if it is a normal mine field MaximumWebMinefieldRadius[Minefield_owner] ...if it is a web field Units_laid = Torps_laid * Conversion_rate
Existing_units is the number of mine units in the field we're adding to, 0 if it is a new field. Torps_available is the number of Torps allowed for laying using mdX or an extended mission like Lay Minefield. Note that Ship_owner and Minefield_owner can differ if miX or an extended mission is used.
For more details about towing, see Tow Conflict Resolution.
Tow_strength = Engine_contribution + Movement_contribution Engine_contribution = Engine_tech^2 * Eff_engines * Warp_factor * TowStrengthEngineScale Movement_contribution = Movement_distance * TowStrengthDistanceScale
For intercept, PHost attempts to sort ships into an order such that all intercept targets move before their respective interceptors. In case of circular intercept, this cannot be done, so it is treated specially:
Waypoint_X = (Sum(Position_X) + Adjust_X) / Num_ships_in_loop Waypoint_Y = (Sum(Position_Y) + Adjust_Y) / Num_ships_in_loop Adjust_X = 0 ...if AllowWraparoundMap is off i * Map_dimension_X ...where 0 <= i < Num_ships_in_loop such that Sum((Position_X - Waypoint_X)^2) is minimal Adjust_Y = 0 ...if AllowWraparoundMap is off j * Map_dimension_Y ...where 0 <= j < Num_ships_in_loop such that Sum((Position_Y - Waypoint_Y)^2) is minimal
The Adjust_X and Adjust_Y parameters are used only in wraparound-map games, and attempt to make sure that ships move the minimum possible distance. They are found by iterating all possible i and j values and picking the best fit. In PHost below 4.0k/3.4m, they are always zero.
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
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
Ships that cloak need to burn fuel.
Fuel_burned_by_cloak = 0 ...if ship has Advanced Cloaking Trunc(CloakFuelBurn * Min(Hull_mass, 100) / 100) ...otherwise Fuel_needed_before_movement = 1 + Fuel_burned_by_cloak Fuel_needed_after_movement = 1
Ships need to decloak if their fuel drops below the Fuel_needed value. After the normal cloak fuel was burnt, one kt must remain; fuelless ships cannot cloak.
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 imposes 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
Note that PHost up to version 4.0j/3.4l truncates the
Travel_failure_odds value to an integral number. Later
versions use the exact value.
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 Fed
The 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 has Full Weaponry Min(Ship_beams, Max_beams - Trunc(Max_beams * Damage / Divisor) ...otherwise Tube_count = Ship_tubes ...if ship has Full Weaponry Min(Ship_tubes, Max_tubes - Trunc(Max_tubes * Damage / Divisor) ...otherwise Bay_count = Basis_bays + Bonus_bays ...with Basis_bays = Ship_bays ...if ship has Full Weaponry Max_bays - Trunc(Max_bays * Ship_damage / Divisor) ...otherwise Bonus_bays = ExtraFighterBays + EModExtraFighterBays ...if Basis_bays > 0 0 ...otherwise 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 / 100) Torp_recharge_rate = Eff_TubeRechargeRate + Trunc((Torp_Kill_Power + Torp_Expl_Power) * Eff_TubeRechargeBonus / 100) 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 are 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).
Ion storm classes are described in the Rules section.
Speed = 8 ...if Voltage > 250 6 ...if Radius < 200 2 + Random(3) ...otherwise, i.e. random between 2 and 4 Heading = Old_heading - 10 + Random(21) ...i.e. change by +/- 10 degrees
Voltage_change = 2 * Random(6) ...i.e. 0 to 10 in steps of two Radius_change = Random(4) ...i.e. 0 to 3 New_voltage = Old_voltage + Voltage_change + Additional_gain New_radius = Old_radius - Radius_change ...if Old_radius > Radius_change 1 - (Old_radius - Radius_change) ...otherwise
The Additional_gain consists of four bonuses that are given to each storm. Note that, because growing storms always have odd voltages, adding one will turn the storm into a weakening one. All four conditions are checked, so the bonus may be anything between zero and four.
Additional_gain = +1 ...if second rule was used for New_radius +1 ...with a 1% chance +1 ...with a 2.5% chance if New_voltage > 320 +1 ...with a 10% chance if New_voltage > 500
Voltage_change = 4 + 2 * Random(6) ...i.e. 4 to 14 in steps of two Radius_change = Random(11) ...i.e. 0 to 10 New_voltage = Old_voltage - Voltage_change ...Storm disappears if this is zero or less New_radius = Old_radius + Radius_change
Pancaking Effect: The pancaking effect has a probability of 1:33 to occur, and happens after normal radius and voltage changes. This may change the storm into a growing one.
Voltage_after_pancaking = Round(Sqrt(New_voltage)) Radius_after_pancaking = 2 * New_radius
Storms Id_1 and Id_2 merge if they partially overlap: Distance_of_centers^2 <= Radius_1^2 + Radius_2^2.
New_X = Trunc((X_1 * Voltage_1 + X_2 * Voltage_2) / (Voltage_1 + Voltage_2)) New_Y = Trunc((Y_1 * Voltage_1 + Y_2 * Voltage_2) / (Voltage_1 + Voltage_2)) ...i.e. weighed average; closer to center of stronger storm New_Radius = Trunc(Sqrt(Radius_1^2 + Radius_2^2)) ...i.e. the storm is larger than each of the original ones New_voltage = Trunc((Voltage_1 * Radius_1^2 + Voltage_2 * Radius_2^2) / (Radius_1^2 + Radius_2^2)) ...i.e. weighed average
The Id of the new storm is the same as the Id of the stronger storm; if they are equally strong, it is the higher of the two. The new heading and speed are taken from that storm.
Whether the new storm is growing or weakening depends upon whether the computed New_voltage is odd or even.
Ships: All storms de-cloak ships that don't have advanced cloaking. Storms stronger than 150 MeV affect all ships that do not cloak or were thus uncloaked, and which do not have an Ion Shield.
Ship_dragged_distance = 0.75 * Storm_warp^2 Ship_dragged_heading = Storm_heading Ship_damage_taken = (Random(200) + Storm_voltage - Ship_mass - 20 * Ship_engine) * Exp_modificator ...with Exp_modificator = 1 ...if NumExperienceLevels = 0 1 - (Ship_experience_level / NumExperienceLevels) ...otherwise ...plus 50 if ship does not have fuel ...at least zero, of course Ship_damage = Ship_damage + Ship_damage_taken Ship_crew = Trunc(Ship_crew * (100 - Ship_damage_taken) / 100) Ship_experience_gain = Trunc(EPShipIonStorm100MEV * (Storm_voltage - 100) / 100)
Last updated 03 September 2006.