©
|
Detailed Operation
The Portable Host
Version 3.2.3.4c
|
INDEX
Introduction
This file contains details regarding the inner workings of PHOST. If
you believe that some aspect of PHOST operation should be documented in
this file but it is not, then please send
e-mail to the PHOST support team
and bring this to our attention.
Back to the index
Mission Ordering
PHOST performs the following events in sequence. The phase numbers (1,
2, and 3) refer to broad stages of host processing. Phase 1 represents
the processing of TRN files, phase 2 represents the bulk of host
processing, phase 3 represents the generation of RST files. AUXHOST
1 programs run between phase 1 and phase 2, while AUXHOST 2 programs run
betweeen phase 2 and phase 3.
Phase 1
- Host Data Checking
- Turn File Processing:
- ships with valid Cloak missions are cloaked
- starbase construction
- cargo dump/transfer between ships/planets belonging to the same player
- base tech levels, primary order, etc. are set
- planetary factories, mines, defenses, friendly codes are set to new
values
- ship name changes, friendly code changes, waypoint settings, warp speed
settings, etc.
- Alliance Status Processing (if DelayAllianceCommands
is disabled)
- Cheat Checking
Phase 2
- Ship/Planet Ownership Transfers (give
command, gsN friendly code)
- Meteors
- Meteor Showers
- Loki Anti-Cloak Tachyon Fields
- Birdman Super Spy Deluxe Missions
- New Natives Appearing
- Privateer Rob Mission
- Gambling Ships
- Cargo Dump (also Imperial Assault and bdm action) from ships
to foreign planets
- Cargo Transfer from ships to foreign ships
- Overloaded ships are trimmed down
- Beam Transfer Friendly Codes (btt, btf, and btm)
- Cargo Gather missions
- Beam Transfer Planetary Credits (bum action)
- Minefield Decay
- Mine Laying and Minefield Explosions
- Minefield Friendly Code Assignment
- Minefield Sweeping
- Minefield Scanning
- Wormhole Scanning
- Web Draining
- Special Missions 1 (Fed Super Refit, Lizard Hiss, Cyborg self repair)
- Fighter Building for Ships (and lfm action)
- Torpedo Building for Ships
- Alchemy Functions (including Aries advanced refinery)
- Populate Build Queue (build orders from starbases, and
cln orders)
- Ship Building/Cloning
- Dump Old Starbase Parts
- Starbase Missions: Fix, Recycle, Load Torps, Max Defense, Force Surrender
- Ship Repair Using Supplies
- Boarding Parties (tow capture)
- Free Fighters for Starbases
- Ship Movement: tow resolution, movement, intercept resolution, intercepts,
wormhole travel, gravity wells
- Glory Devices
- Chunneling
- Loki Anti-Cloak Tachyon Fields (again)
- Ship Colonize Mission
- Ship Repair Using Supplies (again)
- Starbase Missions: Refuel, Unload Freighters, Repair Base
- Combat
- Ship Repair Using Supplies (again)
- Science Ships
- Ship Sensor Sweep Mission
- Special Missions 2 (Klingon Pillage, Rebel Ground Attack, Empire Dark
Sense)
- Planetary Production: mines, supplies, TUDR
- Planetary Happiness Changes
- Planetary Taxation
- Planetary Colonist and Native Growth
- Planetary Losses: climate deaths, overpopulation supply loss, structure
decay, losses due to riots/civil war, losses from Amorphous natives
- Clear Invalid Tow/Intercept Missions (on ships destroyed in combat)
- Ship Building/Cloning (again)
- Cyborg Native Assimilation
- Birdmen Super Spy Mission
- Ship Exploration Mission
- Update player activity levels and build queue priorities
- Build Queue Report
Phase 3
- External Message Processing (MESS.EXT file)
- Ships Scan for Enemy Ships
- Planets Scan for Enemy Ships
- SHIPSCAN.EXT file
is written
- Ship Adjustments: ships with >100% damage deleted, waypoints truncated,
tow missions that target deleted ships cleared, intercept missions on deleted/non-visible
ships cleared, ship speed damage-limited
- Calculate Scores
- Alliance Status Processing (if DelayAllianceCommands
is enabled)
- Generate RST Files
- Generate UTIL.DAT Files
- Append UTIL.EXT files to UTIL.DAT files
- Remove UTIL.EXT files
- Remove TRN Files
Back to the index
Definitions
Planetary Abbreviations
COL |
Colonists on a planet |
CLANS |
Clans on a planet or ship (COL / 100) |
NAT |
Natives on a planet |
NATCLANS |
Native clans on a planet (NAT / 100) |
F |
Factories |
M |
Mines |
DP |
Planetary defense posts |
BDP |
Base defense posts |
PDAMAGE |
Planetary damage during combat |
SUP |
Supplies |
MC |
Megacredits |
FC |
Friendly code |
CTAX |
Colonist tax rate (%) |
NTAX |
Native tax rate (%) |
NATGOV |
Native government (1=Anarchy, 9=Unity) |
CHAPPY |
Colonist happiness (-300 to 100) |
NHAPPY |
Native happiness (-300 to 100) |
TEMP |
Planet temperature |
Mathematical Notation
ABS(X) |
Absolute value of X |
ARCTAN(Y,X) |
Four-quadrant arctangent of Y/X |
COS(X) |
Cosine of argument (argument is in radians) |
DIST(X,Y) |
Distance in LY from X to Y |
ERND(X) |
Round floating point to nearest integer. Values that have a fractional
part of exactly 0.5 are rounded to the nearest even integer (e.g., 8.5
becomes 8, 9.5 becomes 10) |
EXP(X) |
Exponential function of X (i.e., 2.71828^X) |
MAX(A,B) |
Maximum of A and B |
MIN(A,B) |
Minimum of A and B |
RAND(N) |
Random integer in the range 0 to N-1 inclusive |
RND(X) |
Round floating point number to nearest integer |
SGN(X) |
Sign of X (+1 if positive, -1 if negative, else 0) |
SIN(X) |
Sine of argument (argument is in radians) |
SQRT(X) |
Square root of X |
TRUNC(X) |
Truncate floating point by discarding fractional part |
X^N |
X to the Nth power |
Other Conventions
Colonist/native populations are generally expressed as number of
persons, not clans. When a formula yields a number
of colonists/natives which is not evenly divisible by 100, the result
is rounded down. Unless specified otherwise, PHOST truncates results.
Back to the index
Planetary Formulas
COL survived after meteor strike = COL * (RAND(91) + 10) / 100
NAT survived after meteor strike = NAT * (RAND(100) + 1) / 100
CHAPPY after meteor strike = CHAPPY - (RAND(31) + 50)
NHAPPY after meteor strike = NHAPPY - (RAND(31) + 50)
NHAPPY after combat in which planet was lost = NHAPPY - 20
COL after Klingon pillage = TRUNC(0.8*COL - 2000)
CHAPPY after Klingon pillage = CHAPPY - 10
NAT after Klingon pillage = TRUNC(0.8*NAT - 12000)
NHAPPY after Klingon pillage = NHAPPY - 10
SUP generated by Klingon pillage = TRUNC((COL+NAT) / 10000)
MC generated by Klingon pillage = TRUNC((COL+NAT) / 10000)
(COL and NAT are populations present *before* reduction)
CHAPPY after Rebel RGA = CHAPPY - 60
NHAPPY after Rebel RGA = NHAPPY + 40
MC after Rebel RGA = TRUNC(MC*7/10)
SUP after Rebel RGA = TRUNC(SUP*6/10)
DP after Rebel RGA = TRUNC(DP*8/10)
M after Rebel RGA = TRUNC(M*4/10)
F after Rebel RGA = TRUNC(F*7/10)
COL after Rebel RGA = TRUNC(COL*8/10)
Minerals mined = TRUNC(MINING_RATE * M / 100)
MINING_RATE = TRUNC((cfg_RaceMiningRate * MINERAL_DENSITY) / 100)
If at least 100 Reptilian natives are present,
MINING_RATE = MINING_RATE * 2
Colonist supply contribution = F
Bovinoid supply contribution = MIN(NATCLANS / 100, CLANS),
if planet has Bovinoids
= 0, otherwise
Total supplies collected =
= TRUNC((COLONIST_SUPPLIES+BOVINOID_SUPPLIES) * cfg_ProductionRate / 100)
Minerals from TUDR
= TRUNC((cfg_TransuraniumDecayRate * MINERAL_DENSITY + 50) / 100)
Natives assimilated = MIN(COL * cfg_BorgAssimilationRate / 100, NAT)
TargetTemp = 100 if planet is Crystal and cfg_CrystalsPreferDeserts is ON
= 50
TempDivisor = 66 if planet is Crystal and cfg_CrystalsPreferDeserts is ON
= 33
CHAPPY change = TRUNC(10 - SQRT(CLANS/10000.0)
- ABS(TEMP-TargetTemp)/TempDivisor
- (M+F)/300
- CTAX*0.8)
NHAPPY change = TRUNC(5 + NATGOV/2 - SQRT(NATCLANS/10000.0) - (M+F)/200
- NTAX*0.85)
If natives are Avian,
NHAPPY change = NHAPPY change + 10
CHAPPY/NHAPPY change from Hissing
= (Number of Hissing ships)*cfg_HissEffectRate
(Note that hissing happens before taxation; after the hiss effect
increases happiness, taxation will it bring down again)
MC from colonist tax = 0, if CHAPPY < 30
= TRUNC((CLANS * CTAX * 5 + 2500) / 5000)
if CHAPPY >= 30
...then MC = TRUNC((MC * cfg_ColonistTaxRate + 50) / 100)
MC from native tax =
= 0, if NHAPPY < 30 or natives are Amorphous
= MIN(TRUNC((NATCLANS * NATGOV * NTAX + 2500) / 5000), CLANS)
...then MC = MC * 2 if natives are Insectoid
...then MC = TRUNC((MC * cfg_NativeTaxRate + 50) / 100)
Max COL Supply Bonus = 0, if cfg_AllowEatingSupplies is OFF
= TRUNC(100*SUP/40), if cfg_AllowEatingSupplies is ON
Base Max COL on planet
= MAX(10 000 000*sin(TEMP * 3.14159 / 200), 100)
if planet is Crystalline
and cfg_CrystalsPreferDeserts is ON
and cfg_CrystalSinTempBehavior is ON
and TEMP >= 15
= 300 + cfg_MaxColTempSlope*TEMP
if planet is Crystalline
and cfg_CrystalsPreferDeserts is ON
and cfg_CrystalSinTempBehavior is ON
and TEMP < 15
= MAX(100 000*TEMP, 100)
if planet is Crystalline
and cfg_CrystalsPreferDeserts is ON
and cfg_CrystalSinTempBehavior is OFF
= 9000000 if TEMP < 20 and planet is Rebel
= 300 + cfg_MaxColTempSlope*TEMP if TEMP < 15
= at least 6000 if TEMP > 84 and planet is Klingon,
Robotic, Rebel, or Colonial
= 100 + (100 - TEMP)*cfg_MaxColTempSlope if TEMP > 84
= SIN(TEMP * 3.14159 / 100) * 10 000 000
if TEMP >= 15 and TEMP <= 84
Max COL on planet = 25 000 000 if cfg_ClimateLimitsPopulation is OFF
= TRUNC(BASE_MAX_COL) + TRUNC(MAX_COL_SUPPLY_BONUS)
Max NAT on planet = 15 600 000 if cfg_ClimateLimitsPopulation is OFF
= (100 000 * TEMP)
if natives are Siliconoid
and CrystalsPreferDeserts is ON
and PHost 3.3c or later
= sin(TEMP * 3.14159 / 100) * 15 600 000
COL_GROWTH_RATE = 0 if CHAPPY < 70 or COL >= Max COL on Planet
= 0 if planet is Crystalline
and cfg_CrystalsPreferDeserts is ON
and cfg_CrystalSinTempBehavior is ON
and TEMP < 15
= 5*SIN(TEMP * 3.14159 / 200) / (1 + CTAX/5)
if planet is Crystalline
and cfg_CrystalsPreferDeserts is ON
and cfg_CrystalSinTempBehavior is ON
and TEMP >= 15
= 5 * (TEMP / 100) / (1 + CTAX/5)
if planet is Crystalline
and cfg_CrystalsPreferDeserts is ON
and cfg_CrystalSinTempBehavior is OFF
= 0, if TEMP < 15 or or TEMP > 84
= 5*SIN(TEMP * 3.14159 / 100) / (1 + CTAX/5)
COL growth =
= RND(COL_GROWTH_RATE * COL / 10000) * cfg_RaceGrowthRate
IF (COL growth + COL > Max COL on Planet) THEN
COL growth = Max COL on Planet - COL
COL climate deaths = (COL - 25 000 000) if COL > 25 000 000
= 0, if cfg_ClimateLimitsPopulation is OFF
= 0, if COL <= Max COL on planet
= TRUNC(COL * cfg_ClimateDeathRate / 100)
If (COL - COL climate deaths < Max COL on planet):
COL climate deaths = COL - Max COL on planet
If (COL_climate_deaths < 100):
COL climate deaths = 0
Overpopulation supply loss
= 0, if cfg_ClimateLimitsPopulation is OFF
= 0, if COL <= BASE_MAX_COL_ON_PLANET
= MIN(TRUNC((COL-BASE_MAX_COL_ON_PLANET)/4000)+1,SUP)
NAT_GROWTH_RATE = 0 if NHAPPY < 70
= 4*(TEMP/100) / (1 + NTAX/5)
if natives are Siliconoids
and cfg_CrystalsPreferDeserts is ON
and PHost 3.3c or later
= 4*SIN(TEMP * 3.14159 / 100) / (1 + NTAX/5)
NAT growth = 0, if planet is unowned
= (NAT_GROWTH_RATE * NAT + 50) / 100
if (NAT growth + NAT > Max NAT on Planet) THEN
NAT growth = Max NAT on Planet - NAT
NAT climate deaths = (25 000 000 - NAT) if NAT > 25 000 000
= 0, if cfg_ClimateLimitsPopulation is OFF
= 0, if planet is unowned
= 0, if NAT < Max NAT on planet
= TRUNC((NAT * cfg_NativeClimateDeathRate) / 100)
If (NAT - NAT_climate_deaths < Max NAT on planet):
NAT climate deaths = NAT - Max NAT on planet
Max M on planet = CLANS, if CLANS < 200
= RND(200 + SQRT(CLANS - 200))
Max F on planet = CLANS, if CLANS < 100
= RND(100 + SQRT(CLANS - 100))
Max DP on planet = CLANS, if CLANS < 50
= RND(50 + SQRT(CLANS - 50))
COL deaths from Amorphous natives = 500, if NHAPPY >= 70
= 2000, if NHAPPY >= 50
= 4000, if NHAPPY < 50
deaths = MIN(deaths, COL)
COL deaths from fighting = COL * (40 - CHAPPY) / 500,
if CHAPPY < 20
= COL * (40 - NHAPPY) / 2500,
if NHAPPY < 20
NAT deaths from fighting = NAT * (40 - NHAPPY) / 500,
if NHAPPY < 20
= NAT * (40 - CHAPPY) / 2500,
if CHAPPY < 20
% chance that planet is detected on sensor sweep =
= 0, if DP >= cfg_DefenseForUndetectable
= 0, if (M < cfg_MinesForDetectable)
AND (F < cfg_FactoriesForDetectable)
= 100% *
(cfg_DefenseForUndetectable - DP) / cfg_DefenseForUndetectable
Planet industrial activity = "minimal", if (M+F) < 30
= "light", if (M+F) < 60
= "moderate", if (M+F) < 90
= "substantial", if (M+F) < 120
= "heavy", if (M+F) >= 120
Back to the index
Ship Formulas
Fuel needed to remain cloaked = 1 KT after movement phase
= CLOAK_FUEL_BURN+1 KT before movement phase
CLOAK_FUEL_BURN = 0 if ship has advanced cloaking device
= TRUNC(MAX(ShipHullMass, 100) * cfg_CloakFuelBurn / 100)
UnitsPerTorp = TRUNC(TorpType^2
* MIN(cfg_UnitsPerTorpRate[ShipOwner],
cfg_UnitsPerTorpRate[MinefieldOwner])
/ 100)
MAX_TORPS_TO_LAY = 0, if UnitsPerTorp is 0
= TRUNC((cfg_MaximumMinefieldRadius^2 - MinefieldRadius^2)
/ UnitsPerTorp)
Units laid in minefield = UnitsPerTorp*MIN(Torps, MAX_TORPS_TO_LAY)
Torps to scoop = MinefieldRadius^2, if UnitsPerTorp is 0
= TRUNC(MinefieldRadius^2 / UnitsPerTorp)
NOTE: If the number of torps created by scooping (as limited by cargo
room) actually equals TorpsToScoop, then the minefield vanishes (i.e.,
minefield units leading to fractional torps are lost if the minefield
is completely swept).
Mine units swept = TRUNC(BeamType^2 * BeamNumber * cfg_MineSweepRate)
= above + (NumFighters * cfg_FighterSweepRate)
if ship is in range
and (minefield is not a web mine field
or (ship is Colonial
and cfg_AllowColoniesSweepWebs is ON))
Minerals reclaimed from colonizing ship =
= TRUNC((HullMineral
+ NumEngines*EngineMineral
+ NumBeams*BeamMineral
+ NumTubes*TubeMineral) * cfg_RecycleRate / 100)
Colonists on planet after colonize mission =
= 100*(TRUNC(ShipCrew/100) + 1)
Max ship speed (warp) = 15 - TRUNC(ShipDamage / 10) if Lizards
= 10 - TRUNC(ShipDamage / 10)
Fuel consumption rate = EngineFuelConsumption / 200 000
if ship hull is gravitonic
= EngineFuelConsumption / 100 000
Fuel consumption = TRUNC(ERND((FuellessShipMass+ShipFuel)/10)
* 10*FUEL_CONSUMPTION_RATE
* TRUNC(DistanceToTravel))
if cfg_UseAccurateFuelModel is OFF
= RND((FuellessShipMass+ShipFuel)
* (1 - EXP(-FUEL_CONSUMPTION_RATE * DistanceToTravel)))
if cfg_UseAccurateFuelModel is ON
EngineFuelConsumption is derived from value from ENGSPEC.DAT and is
tabulated in Eden Tan's Infolist
. It is reproduced here for convenience
(note that this only applies to the original ship list):
Fuel Usage |
Warp 1 |
Warp 2 |
Warp 3 |
Warp 4 |
Warp 5 |
Warp 6 |
Warp 7 |
Warp 8 |
Warp 9 |
StarDrive 1 |
100.00 |
200.00 |
300.00 |
400.00 |
500.00 |
600.00 |
700.00 |
800.00 |
900.00 |
StarDrive 2 |
100.00 |
107.50 |
300.00 |
400.00 |
500.00 |
600.00 |
700.00 |
800.00 |
900.00 |
StarDrive 3 |
100.00 |
106.25 |
107.78 |
337.50 |
500.00 |
600.00 |
700.00 |
800.00 |
900.00 |
SuperStarDrv 4 |
100.00 |
103.75 |
104.44 |
106.25 |
300.00 |
322.22 |
495.92 |
487.50 |
900.00 |
Nova Drive 5 |
100.00 |
103.75 |
104.44 |
106.25 |
104.00 |
291.67 |
291.84 |
366.41 |
900.00 |
HeavyNova Drv 6 |
100.00 |
103.75 |
104.44 |
106.25 |
104.00 |
103.69 |
251.02 |
335.16 |
900.00 |
Quantam Drive 7 |
100.00 |
103.75 |
104.44 |
106.25 |
104.00 |
103.69 |
108.16 |
303.91 |
529.63 |
Hyper Drive 8 |
100.00 |
100.00 |
100.00 |
100.00 |
100.00 |
100.00 |
102.04 |
109.38 |
529.63 |
Transwarp Drive |
100.00 |
100.00 |
100.00 |
100.00 |
100.00 |
100.00 |
100.00 |
100.00 |
100.00 |
Mine hit damage = TRUNC(100 * cfg_MineHitDamageFor100KT / ShipHullMass)
Web hit damage = TRUNC(100 * cfg_WebHitDamageFor100KT / ShipHullMass)
Ground attack attack factor = cfg_GroundKillFactor
Ground attack defense factor = cfg_GroundDefenseFactor + PlanetDefense/20
Ground attack discriminant = AttackColonists*GROUND_ATTACK_FACTOR
- DefenseColonists*GROUND_DEFENSE_FACTOR
Planet colonists remaining after ground attack =
= GROUND_ATTACK_DISCRIMINANT / GROUND_ATTACK_FACTOR
if GROUND_ATTACK_DISCRIMINANT >= 0 (attackers win)
= -GROUND_ATTACK_DISCRIMINANT / GROUND_DEFENSE_FACTOR
if GROUND_ATTACK_DISCRIMINANT < 0 (defenders win)
Back to the index
Minefield Formulas
Minefield units after decay =
= TRUNC(CurrentUnits * (100 - cfg_MineDecayRate) / 100) for mines
= TRUNC(CurrentUnits * (100 - cfg_WebMineDecayRate) / 100) for webs
Web drain fuel loss = MIN(cfg_WebDrainFuelLoss, ShipFuel)
Web hit fuel loss = MIN(MAX(50, ShipFuel/6), ShipFuel)
Minefields exploding:
D = DIST( Mine1, Mine2 ), the distance between 2 minefield centers
R1 = SQRT( MineUnits1 ), the radii of the minefields
R2 = SQRT( MineUnits2 )
IF (D > (R1+R2)) THEN
Mines exploding = 0
ELSE IF (D is 0) THEN
Mines exploding = MineUnits1 if R1 < R2
= MineUnits2 if R2 <= R1
ELSE
A = (R1*R1 - R2*R2 + D*D) / (2*D)
IF (A < 0) THEN
Mines exploding = MineUnits1
ELSE IF (A > D) THEN
Mines exploding = MineUnits2
ELSE
Mines exploding = R1*R1 - A*A
ENDIF
ENDIF
Back to the index
Planetary Combat Formulas
Base tech maximum after damage (a.k.a. BaseDamageTech(TECH) ) =
= MAX(MIN( (100-BaseDamage)/10, BaseTech(TECH) ), 1)
PLANET_COMBAT_DEFENSE = TRUNC(DP * (100-PDAMAGE) / 100)
BASE_COMBAT_DEFENSE = TRUNC(BDP * (100-PDAMAGE) / 100)
TOTAL_COMBAT_DEFENSE = TRUNC((DP + BDP) * (100-PDAMAGE) / 100)
(damage-scaled planetary/starbase defense post count)
Planet combat mass = 100 + PLANET_COMBAT_DEFENSE
= above + BASE_COMBAT_DEFENSE
if starbase present
Planet beam type = RND(PLANET_COMBAT_DEFENSE / 2) if no base
= MAX(above, BaseDamageTech(BEAMS)) if base present
Planet beam number = MIN(RND(SQRT(TOTAL_COMBAT_DEFENSE / 3)), 20)
if cfg_AllowAlternativeCombat is ON
= MIN(RND(SQRT(TOTAL_COMBAT_DEFENSE / 3)), 10)
if cfg_AllowAlternativeCombat is OFF
Planet torp type = RND(PLANET_COMBAT_DEFENSE / 2) if no base
= MAX(above, BaseDamageTech(TORPS)) if base present
Planet tube number = MIN(RND(SQRT(TOTAL_COMBAT_DEFENSE / 4)), 20)
Planet torp number = PLANET_TUBE_NUMBER * cfg_PlanetaryTorpsPerTube
= above + BASE_TORPS if base is present. BASE_TORPS
is calculated according to the following
algorithm:
EQUIVCOST = 0
FOR Type=1 TO 10
EQUIVCOST = EQUIVCOST +
TorpsInStorage(Type)*TorpMoneyCost(Type)
ENDFOR
BASE_TORPS = EQUIVCOST / TorpMoneyCost(PLANET_TORP_TYPE)
A planet can have at most 255 torpedoes.
Torps removed from base storage after combat are calculated as follows:
COST_OF_TORPS = TorpsFiredInBattle * TorpMoneyCost(PLANET_TORP_TYPE)
WHILE (COST_OF_TORPS > 0)
DONE=1
FOR TYPE=1 to 10
IF ( BaseTorps(TYPE) > 0
AND TorpMoneyCost(TYPE) <= COST_OF_TORPS
)
COST_OF_TORPS = COST_OF_TORPS - TorpMoneyCost(TYPE)
BaseTorps(TYPE) = BaseTorps(TYPE) - 1
DONE=0
ENDIF
ENDFOR
IF (DONE) STOP
ENDWHILE
Planet bay number = MIN(RND(SQRT(PLANET_COMBAT_DEFENSE)), 50) if no base
= MIN(above+5, 50) if base present
Planet fighters = RND(SQRT(PLANET_COMBAT_DEFENSE)) if no base
= above + BaseFighters if base present
NAT after combat in which planet is conquered =
= TRUNC(NAT*cfg_NativeCombatSurvivalRate/100)
Back to the index
Ship Combat Formulas
Ship shields = TRUNC((300 - 2*ShipDamage)/3) if ship is Lizard
= TRUNC(100 - ShipDamage)
Ship mass = ShipHullMass
+ TRUNC(ENGINE_TECH_BONUS*cfg_EngineShieldBonusRate/100)
if cfg_AllowEngineShieldBonus is ON
and (ship is fighting a ship,
or cfg_AllowESBonusAgainstPlanets is ON)
= ShipHullMass otherwise
= above + 50
if ship is Federation and cfg_AllowFedCombatBonus is ON
If cfg_PALIncludesESB is ON (hardwired on PHost 3.3d or earlier), the
ship mass computed here is used for PAL computations. Otherwise,
only the ShipHullMass is used for PALs.
ENGINE_TECH_BONUS = cost (in megacredits) of building 1 engine of the
same type as the ship's engines
DamageScale = 150 if ship is Lizard
= 100 otherwise
Ship beam number =
= ShipBeams if ship is Federation and cfg_AllowFedCombatBonus is ON
= MIN(ShipBeams, MaxHullBeams-TRUNC(MaxHullBeams*ShipDamage/DamageScale))
Ship bay number =
= ShipBays if ship is Federation and cfg_AllowFedCombatBonus is ON
= MIN(ShipBays, MaxShipBays-TRUNC(MaxShipBays*ShipDamage/DamageScale))
Ship tube number
= ShipTubes if ship is Federation and cfg_AllowFedCombatBonus is ON
= MIN(ShipTubes, MaxHullTubes-TRUNC(MaxHullTubes*ShipDamage/DamageScale))
Beam hit odds = cfg_BeamHitOdds
+ TRUNC((BeamKillPower+BeamSmashPower)*cfg_BeamHitBonus/100)
Torp hit odds = cfg_TorpHitOdds
+ TRUNC((TorpKillPower+TorpSmashPower)*cfg_TorpHitBonus/100)
Beam recharge rate = cfg_BeamRechargeRate
+ TRUNC((BeamKillPower + BeamSmashPower)
* cfg_BeamRechargeBonus / 100)
Bay recharge rate = cfg_BayRechargeRate + cfg_BayRechargeBonus*NumBays
Tube recharge rate = cfg_TubeRechargeRate
+ TRUNC((TorpKillPower + TorpSmashPower)
* cfg_TubeRechargeBonus / 100)
Damage to shields = (SmashPower * cfg_ShieldDamageScaling) / (Mass + 1)
if cfg_AllowAlternativeCombat is ON
= TRUNC(above + 1.5)
if cfg_AllowAlternativeCombat is OFF
Damage to hull = (SmashPower * cfg_HullDamageScaling) / (Mass + 1)
if cfg_AllowAlternativeCombat is ON
= TRUNC((DAMAGE_TO_SHIELDS * cfg_HullDamageScaling)
/ (Mass + 1) + 1.5)
if cfg_AllowAlternativeCombat is OFF
Crew killed = (KillPower * cfg_CrewKillScaling) / (Mass + 1)
if cfg_AllowAlternativeCombat is ON
= TRUNC(above + 0.5) if cfg_AllowAlternativeCombat is OFF
Back to the index
Planetary Happiness Flowchart
; "Special Missions 1"
CHAPPY = MIN(CHAPPY + HISS_EFFECT, 100)
NHAPPY = MIN(NHAPPY + HISS_EFFECT, 100)
; ... much later, after movement, combat, terraforming, RGA and Pillage ...
IF CHAPPY < 30 AND CTAX > 0 THEN
CTAX = 0
;Colonists refuse to pay taxes
ENDIF
CHAPPY = CHAPPY + COLONIST_HAPPY_CHANGE
IF CHAPPY < 20 THEN
;Civil war
ELSE IF CHAPPY < 40 THEN
;Riots
ENDIF
IF CLANS == 0 THEN
CTAX = 0
NTAX = 0
ENDIF
IF NHAPPY < 30 AND NTAX > 0 THEN
NTAX = 0
;Natives refuse to pay taxes
ENDIF
NHAPPY = NHAPPY + NATIVE_HAPPY_CHANGE
IF NHAPPY < 20 THEN
;Native civil war
ELSE IF NHAPPY < 40 THEN
;Native riots
ENDIF
Back to the index
Planetary Losses Flowchart
COL = COL - COL_CLIMATE_DEATHS
NAT = NAT - NAT_CLIMATE_DEATHS
SUP = SUP - OVERPOPULATION_SUPPLY_LOSS
M = M - STRUCTURE_DECAY_LOSS
F = F - STRUCTURE_DECAY_LOSS
DP = DP - STRUCTURE_DECAY_LOSS
IF CHAPPY < 40 OR NHAPPY < 40 THEN
M = M - 10
F = F - 10
ENDIF
COL = COL - COL_FIGHTING_DEATHS
NAT = NAT - NAT_FIGHTING_DEATHS
COL = COL - AMORPHOUS_LOSSES
Back to the index
Ship Movement Flowchart
Ship starting co-ordinates = (Xs, Ys)
Ship waypoint co-ordinates = (Xw, Yw)
Start-to-waypoint distance = D = DIST(startpoint,waypoint)
Actual travel distance = T = MIN(D, ShipSpeed*ShipSpeed*GravFactor)
(where GravFactor = 2 for gravitonic ships,
GravFactor = 1 for all other ships)
Ship heading = ARCTAN(Yw-Ys, Xw-Xs)
(HEADING)
IF T == D THEN
New ship location = (Xw, Yw)
ELSE
Ship displacement (floating point) = (T*COS(HEADING), T*SIN(HEADING))
= (Xdf, Ydf)
IF Xw == Xs THEN
Xdf = 0
ENDIF
IF Yw == Ys THEN
Ydf = 0
ENDIF
Ship displacement (integer) = (ROUNDUP(Xdf), ROUNDUP(Ydf))
= (Xsi, Ysi)
New ship location = (Xs+Xsi, Ys+Ysi)
ENDIF
ROUNDUP(Q) rounds number Q towards the next larger integer, preserving
the sign:
ROUNDUP(0) = 0
ROUNDUP(10.3) = 11 ROUNDUP(-10.3) = -11
ROUNDUP(11) = 11 ROUNDUP(-11) = -11
ROUNDUP(11.01) = 12 ROUNDUP(-11.01) = -12
***NOTE: Ship locations are limited to the square (0,0)-(10000,10000).
If an X or Y position of a ship exceeds the value 10000, it is
reduced to 10000. If a position becomes negative, it is mapped
to the value 10000.
Back to the index
Hyperwarp Ship Movement Flowchart
Ship starting co-ordinates = (Xs, Ys)
Ship waypoint co-ordinates = (Xw, Yw)
DX = Xw-Xs
DY = Yw-Ys
DIST_TO_WAYPOINT = SQRT(DX*DX+DY*DY)
IF (DIST_TO_WAYPOINT >= 340 AND DIST_TO_WAYPOINT <= 360) THEN
New Location X = Xw
New Location Y = Yw
ELSE
New Location X = Xs + SGN(DX)*TRUNC(350*ABS(DX)/SQRT(DX^2 + DY^2) + 0.4999999)
New Location Y = Ys + SGN(DY)*TRUNC(350*ABS(DY)/SQRT(DX^2 + DY^2) + 0.4999999)
ENDIF
Back to the index
Wraparound Movement Flowchart
Definitions:
ShipX -- X co-ordinate of ship position before wraparound
ShipY -- Y co-ordinate of ship position before wraparound
NewShipX -- X co-ordinate of ship position after wraparound
NewShipY -- Y co-ordinate of ship position after wraparound
LowerLeftX -- X co-ordinate of lower-left corner of wrap region
LowerLeftY -- Y co-ordinate of lower-left corner of wrap region
UpperRightX -- X co-ordinate of upper-right corner of wrap region
UpperRightY -- Y co-ordinate of upper-right corner of wrap region
(these are the four numbers specified in cfg_WraparoundRectangle)
DimX -- Length of wrap region along the X-axis (UpperRightX-LowerLeftX)
DimY -- Length of wrap region along the Y-axis (UpperRightY-LowerLeftY)
Movement Formulas:
IF (ShipX < LowerLeftX) THEN
NewShipX = ShipX + DimX
ELSE IF (ShipX >= UpperRightX) THEN
NewShipX = ShipX - DimX
ENDIF
IF (ShipY < LowerLeftY) THEN
NewShipY = ShipY + DimY
ELSE IF (ShipY >= UpperRightY) THEN
NewShipY = ShipY - DimY
ENDIF
Note that PHost 3.3b and earlier had ">" in the UpperRightX
and UpperRightY comparisons which caused ugly ambiguities.
Back to the index
Wormhole Formulas
Wormhole detection radius = D = 10 * WormholeMass^(1/3)
Wormhole detection chance = 100% if DIST(ship,wormhole) <= D
= (4 - (DIST(ship,wormhole)/D)^2) * 33.3%
if D < DIST(ship,wormhole) <= 2D
= 0% if DIST(ship,wormhole) > 2D
Wormhole stress factor = (TotalShipMass/WormholeMass - 1)^2
(WRM_STRESS) if TotalShipMass >= WormholeMass
= 0 if TotalShipMass < WormholeMass
Wormhole passage failure chance = WRM_STRESS + WormholeInstability
(WRM_FAILURE) + WRM_STRESS*WormholeInstability/10
(percent)
Wormhole passage failure figure = RAND(100)
(WRM_FAILFIG)
Ship damage from wormhole passage failure = (WRM_FAILFIG - WRM_FAILURE)^2
if WRM_FAILFIG < WRM_FAILURE
= 0 if WRM_FAILFIG >= WRM_FAILURE
Wormhole entry radius = 0.5 * WormholeMass^(cfg_WrmEntryPowerX100/100) LY
Ship exit point X (normal travel) = WRM_EXIT_X + RAND(21) - 10
Ship exit point Y (normal travel) = WRM_EXIT_Y + RAND(21) - 10
Ship exit point X (insufficient fuel) = RAND(2001) + 1000
Ship exit point Y (insufficient fuel) = RAND(2001) + 1000
Back to the index
This document is maintained by The Portable Host Project
(support@phost.de).
Last updated 16 December, 2002