©

Detailed Operation
The Portable Host
Version 3.2.3.2

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

  1. Host Data Checking
  2. Turn File Processing:
  3. Alliance Status Processing (if DelayAllianceCommands is disabled)
  4. Cheat Checking

Phase 2

  1. Ship/Planet Ownership Transfers (give command, gsN friendly code)
  2. Meteors
  3. Meteor Showers
  4. Loki Anti-Cloak Tachyon Fields
  5. Birdman Super Spy Deluxe Missions
  6. New Natives Appearing
  7. Privateer Rob Mission
  8. Gambling Ships
  9. Cargo Dump (also Imperial Assault and bdm action) from ships to foreign planets
  10. Cargo Transfer from ships to foreign ships
  11. Overloaded ships are trimmed down
  12. Beam Transfer Friendly Codes (btt, btf, and btm)
  13. Cargo Gather missions
  14. Beam Transfer Planetary Credits (bum action)
  15. Minefield Decay
  16. Mine Laying and Minefield Explosions
  17. Minefield Friendly Code Assignment
  18. Minefield Sweeping
  19. Minefield Scanning
  20. Wormhole Scanning
  21. Web Draining
  22. Special Missions 1 (Fed Super Refit, Lizard Hiss, Cyborg self repair)
  23. Fighter Building for Ships (and lfm action)
  24. Torpedo Building for Ships
  25. Alchemy Functions (including Aries advanced refinery)
  26. Ship Building (and cln action)
  27. Dump Old Starbase Parts
  28. Starbase Missions: Fix, Recycle, Load Torps, Max Defense, Force Surrender
  29. Ship Repair Using Supplies
  30. Boarding Parties (tow capture)
  31. Free Fighters for Starbases
  32. Ship Movement: tow resolution, movement, intercept resolution, intercepts, wormhole travel, gravity wells
  33. Glory Devices
  34. Chunneling
  35. Loki Anti-Cloak Tachyon Fields (again)
  36. Ship Colonize Mission
  37. Ship Repair Using Supplies (again)
  38. Starbase Missions: Refuel, Unload Freighters, Repair Base
  39. Combat
  40. Ship Repair Using Supplies (again)
  41. Science Ships
  42. Ship Sensor Sweep Mission
  43. Special Missions 2 (Klingon Pillage, Rebel Ground Attack, Empire Dark Sense)
  44. Planetary Production: mines, supplies, TUDR
  45. Planetary Happiness Changes
  46. Planetary Taxation
  47. Planetary Colonist and Native Growth
  48. Planetary Losses: climate deaths, overpopulation supply loss, structure decay, losses due to riots/civil war, losses from Amorphous natives
  49. Clear Invalid Tow/Intercept Missions (on ships destroyed in combat)
  50. Ship Building (and cln action) (again)
  51. Cyborg Native Assimilation
  52. Birdmen Super Spy Mission
  53. Ship Exploration Mission
  54. Update player activity levels and build queue priorities
  55. Build Queue Report

Phase 3

  1. External Message Processing (MESS.EXT file)
  2. Ships Scan for Enemy Ships
  3. Planets Scan for Enemy Ships
  4. SHIPSCAN.EXT file is written
  5. 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
  6. Calculate Scores
  7. Alliance Status Processing (if DelayAllianceCommands is enabled)
  8. Generate RST Files
  9. Generate UTIL.DAT Files
  10. Append UTIL.EXT files to UTIL.DAT files
  11. Remove UTIL.EXT files
  12. 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

cfg_XXXX This notation represent the configuration option XXXX

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 = MINING_RATE * M / 100
     MINING_RATE = (cfg_RACE_MINING_RATE * 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 = (cfg_TUDR * MINERAL_DENSITY + 50) / 100

     Natives assimilated = MIN(COL * cfg_ASSIM_RATE / 100, NAT)

     TargetTemp = 100 if planet is Crystal and cfg_CrystalsLikeDesert is ON
                = 50
     TempDivisor = 66 if planet is Crystal and cfg_CrystalsLikeDesert is ON
                 = 33
     CHAPPY change = 10 - SQRT(CLANS/10000.0)
                        - ABS(TEMP-TargetTemp)/TempDivisor
                        - (M+F)/300
                        - CTAX*0.8
                        + (Number of Hissing ships)*cfg_HissEffectRate

     NHAPPY change = 5 + NATGOV/2 - SQRT(NATCLANS/10000.0) - (M+F)/200
                       - NTAX*0.85
                       + (Number of Hissing ships)*cfg_HissEffectRate)

     If natives are Avian,
        NHAPPY change = NHAPPY change + 10

     MC from colonist tax = 0, if CHAPPY < 30
                          = TRUNC((CLANS * CTAX * 5 + 2500) / 5000)
                                         if CHAPPY >= 30
          ...then  MC = TRUNC((MC * cfg_TAX_RATE + 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_TAX_RATE + 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 CrystalsLikeDesert is ON
                            and CrystalSinTempBehavior is ON
                            and TEMP >= 15
                       = 300 + cfg_MaxColTempSlope*TEMP
                            if planet is Crystalline
                            and CrystalsLikeDesert is ON
                            and CrystalSinTempBehavior is ON
                            and TEMP < 15
                       = MAX(100 000*TEMP, 100)
                            if planet is Crystalline
                            and CrystalsLikeDesert is ON
                            and 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 ClimateLimitsPopulation is OFF
                       = BASE_MAX_COL + MAX_COL_SUPPLY_BONUS


     Max NAT on planet = 15 600 000 if ClimateLimitsPopulation is OFF
                       = 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 CrystalsLikeDesert is ON
                         and CrystalSinTempBehavior is ON
                         and TEMP < 15
                     = 5*SIN(TEMP * 3.14159 / 200) / (1 + CTAX/5)
                         if planet is Crystalline
                         and CrystalsLikeDesert is ON
                         and CrystalSinTempBehavior is ON
                         and TEMP >= 15
                     = 5 * (TEMP / 100) / (1 + CTAX/5)
                         if planet is Crystalline
                         and CrystalsLikeDesert is ON
                         and 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 ClimateLimitsPopulation is OFF
                        = 0, if COL <= Max COL on planet
                        = TRUNC(COL * cfg_CLIMATE_DEATH_RATE / 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*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 ClimateLimitsPopulation is OFF
                        = 0, if planet is unowned
                        = 0, if NAT < Max NAT on planet
                        = TRUNC((NAT * cfg_NATIVE_DEATH_RATE) / 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_DEFENSE_FOR_UNDETECTABLE
                   = 0, if (M < cfg_MINES_FOR_DETECTABLE)
                           AND (F < cfg_FACTORIES_FOR_DETECTABLE)
                   = 100% *
              (cfg_DEFENSE_FOR_UNDETECTABLE - DP) / cfg_DEFENSE_FOR_UNDETECTABLE

     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 = 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_MaxMineRadius^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_SweepRate)
                      = above + (NumFighters * cfg_FighterSweepRate) if
                            ship is Colonial and ship is in range

     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_MineHitDamage / ShipHullMass)
     Web hit damage  = TRUNC(100 * cfg_WebHitDamage / 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_WebDecayRate) / 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 mass = 100 + TRUNC((DP + BDP)*(100-PDAMAGE)/100)

    Planet beam type = RND(SQRT(DP*(100-PDAMAGE)/200)) if no base
                     = MAX(above, BaseDamageTech(BEAMS)) if base present

    Planet beam number = MIN(RND(SQRT((DP+BDP)*(100-PDAMAGE)/300)), 20)
                                    if cfg_AlternativeCombat is ON
                       = MIN(RND(SQRT((DP+BDP)*(100-PDAMAGE)/300)), 10)
                                    if cfg_AlternativeCombat is OFF

    Planet torp type = RND(SQRT(DP*(100-PDAMAGE)/200)) if no base
                     = MAX(above, BaseDamageTech(TORPS)) if base present

    Planet tube number = MIN(RND(SQRT((DP+BDP)*(100-PDAMAGE)/400)), 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 / PLANET_TORP_TYPE

    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(DP*(100-PDAMAGE)/100)), 50) if no base
                      = MIN(above+5, 50) if base present

    Planet fighters = RND(SQRT(DP*(100-PDAMAGE)/100)) 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 if cfg_EngineShieldBonus is OFF
              = ShipHullMass
                   + TRUNC(ENGINE_TECH_BONUS*cfg_EngineShieldRate/100)
                             if cfg_EngineShieldBonus is ON
              = above + 50 if ship is Federation and cfg_FedCrewBonus is ON
    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_FedCrewBonus is ON
             = MIN(ShipBeams, MaxHullBeams-TRUNC(MaxHullBeams*ShipDamage/DamageScale))

    Ship bay number =
             = ShipBays if ship is Federation and cfg_FedCrewBonus is ON
             = MIN(ShipBays, MaxShipBays-TRUNC(MaxShipBays*ShipDamage/DamageScale))

    Ship tube number
             = ShipTubes if ship is Federation and cfg_FedCrewBonus 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_AlternativeCombat is ON
                      = TRUNC(above + 1.5)
                                    if cfg_AlternativeCombat is OFF

    Damage to hull = (SmashPower * cfg_HullDamageScaling) / (Mass + 1)
                                    if cfg_AlternativeCombat is ON
                   = TRUNC((DAMAGE_TO_SHIELDS * cfg_HullDamageScaling)
                               / (Mass + 1) + 1.5)
                                    if cfg_AlternativeCombat is OFF

    Crew killed = (KillPower * cfg_CrewKillScaling) / (Mass + 1)
                                    if cfg_AlternativeCombat is ON
                = TRUNC(above + 0.5) if cfg_AlternativeCombat is OFF

Back to the index


Planetary Happiness Flowchart

    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) = (TRUNC(Xdf)+SGN(Xdf), TRUNC(Ydf)+SGN(Ydf))
                                   = (Xsi, Ysi)
       New ship location = (Xs+Xsi, Ys+Ysi)
    ENDIF

    ***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

      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

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 (phost-support@umich.edu).
Last updated March 2, 1998