2024-08-23 15:57:09 +00:00
|
|
|
using System;
|
2024-09-24 18:17:49 +00:00
|
|
|
using Splat;
|
2024-08-23 15:57:09 +00:00
|
|
|
|
|
|
|
namespace StarsAssistant.Services;
|
|
|
|
|
|
|
|
public class GameEngine
|
|
|
|
{
|
2024-09-24 18:17:49 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Helper reference to the Game, populated during service registration for the
|
|
|
|
/// loaded game.
|
|
|
|
/// </summary>
|
|
|
|
// TODO: check for better options here.
|
|
|
|
public static Game Game { get; set; } = null!;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Minimum effective value of a planet for purposes of maximum population etc.
|
|
|
|
/// </summary>
|
|
|
|
public const int MinEffectiveValue = 5;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Normalize a planet value for minimum effetive value.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="value">Real planet value</param>
|
|
|
|
/// <returns>Effective plante value</returns>
|
|
|
|
public static int EffectivePlanetValue(int value) => (value < MinEffectiveValue) ? MinEffectiveValue : value;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Compute the maximum regular (non-overcrowded) population on a planet for the active player.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="value">Real planet value</param>
|
|
|
|
/// <returns>effective maximum population</returns>
|
|
|
|
public static int MaxPopOnPlanetForPlayer(int value) => Game.Player.MaxPopOnPlanet * EffectivePlanetValue(value) / 100;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Compute population growth for player planets.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="currentPop">Current population on planet</param>
|
|
|
|
/// <param name="value">Real planet value</param>
|
|
|
|
/// <returns>population growth per turn</returns>
|
|
|
|
public static int PlanetPopGrowthForPlayer(int currentPop, int value)
|
|
|
|
{
|
|
|
|
int maxPop = MaxPopOnPlanetForPlayer(value);
|
2024-09-25 17:01:49 +00:00
|
|
|
int growth;
|
2024-09-24 18:17:49 +00:00
|
|
|
|
|
|
|
if (value < 0)
|
|
|
|
{
|
2024-09-24 20:32:13 +00:00
|
|
|
growth = currentPop * value / 1000;
|
2024-09-24 18:17:49 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-09-24 20:32:13 +00:00
|
|
|
double popRatio = (double) currentPop / maxPop;
|
2024-09-25 17:01:49 +00:00
|
|
|
if (popRatio <= 0.25)
|
|
|
|
{
|
|
|
|
growth = currentPop
|
|
|
|
* Game.Player.GrowthRatePercent / 100
|
|
|
|
* value / 100;
|
|
|
|
}
|
|
|
|
else if (popRatio < 1)
|
|
|
|
{
|
|
|
|
double factor = Math.Pow(1.0 - popRatio, 2);
|
|
|
|
growth = currentPop
|
|
|
|
* Game.Player.GrowthRatePercent / 100
|
|
|
|
* value / 100
|
|
|
|
* 16 / 9;
|
|
|
|
growth = (int) ((double) growth * factor);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
double factor = 0.04 * (popRatio - 1);
|
|
|
|
growth = (int) ((double) currentPop * factor);
|
|
|
|
}
|
2024-09-24 18:17:49 +00:00
|
|
|
}
|
|
|
|
|
2024-09-25 17:01:49 +00:00
|
|
|
// round down by 100
|
|
|
|
return growth / 100 * 100;
|
2024-09-24 18:17:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Returns the maximum operable factories on a given player planet for a given value.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="currentPop">Population on planet</param>
|
|
|
|
/// <param name="value">Real planet value</param>
|
|
|
|
/// <returns>Maximum operable factories for currentPop</returns>
|
|
|
|
public static int MaxOperableFactoriesForPlayer(int currentPop, int value)
|
|
|
|
{
|
|
|
|
int effectivePop = Math.Min(currentPop, MaxPopOnPlanetForPlayer(value));
|
|
|
|
double tmp = (double) effectivePop / 10000 * Game.Player.FactoryNumberPer10k;
|
|
|
|
return (int) tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Maximum buildable factories on a player planet with a given value.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="value">Real Planet Value</param>
|
|
|
|
/// <returns>Maximum buildable factories</returns>
|
|
|
|
public static int MaxBuildableFactoriesForPlayer(int value)
|
|
|
|
{
|
|
|
|
double tmp = (double) MaxPopOnPlanetForPlayer(value) / 10000 * Game.Player.FactoryNumberPer10k;
|
|
|
|
return (int) tmp;
|
|
|
|
}
|
|
|
|
|
2024-09-26 20:18:50 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Returns the Germanium cost for the given number of factories.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="count">Factory count</param>
|
|
|
|
/// <returns>Germanium cost</returns>
|
|
|
|
public static int FactoryGermaniumCostForPlayer(int count) => count * Game.Player.FactoryGerCost;
|
|
|
|
|
2024-09-24 18:17:49 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Returns the maximum operable mines on a given player planet for a given value.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="currentPop">Population on planet</param>
|
|
|
|
/// <param name="value">Real planet value</param>
|
|
|
|
/// <returns>Maximum operable mines for currentPop</returns>
|
|
|
|
public static int MaxOperableMinesForPlayer(int currentPop, int value)
|
|
|
|
{
|
|
|
|
int effectivePop = Math.Min(currentPop, MaxPopOnPlanetForPlayer(value));
|
|
|
|
double tmp = (double) effectivePop / 10000 * Game.Player.MineNumberPer10k;
|
|
|
|
return (int) tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Maximum buildable factories on a player planet with a given value.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="value">Real Planet Value</param>
|
|
|
|
/// <returns>Maximum buildable factories</returns>
|
|
|
|
public static int MaxBuildableMinesForPlayer(int value)
|
|
|
|
{
|
|
|
|
double tmp = (double) MaxPopOnPlanetForPlayer(value) / 10000 * Game.Player.MineNumberPer10k;
|
|
|
|
return (int) tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Ressources produced by population on a player planet with a given value. Takes
|
|
|
|
/// less effective overcrowding pop into account.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="currentPop">Current planetary population</param>
|
|
|
|
/// <param name="value">Real planet value</param>
|
|
|
|
/// <returns>Resources generated by populationa</returns>
|
|
|
|
public static int ResourcesFromPopForPlayer(int currentPop, int value)
|
|
|
|
{
|
|
|
|
if (Game.Player.ColonistsPerResource == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
int maxPop = MaxPopOnPlanetForPlayer(value);
|
|
|
|
int popFullEfficiency;
|
|
|
|
int popHalfEfficiency;
|
|
|
|
if (currentPop <= maxPop) {
|
|
|
|
popHalfEfficiency = 0;
|
|
|
|
popFullEfficiency = currentPop;
|
|
|
|
}
|
|
|
|
else if (currentPop <= 3 * maxPop) {
|
|
|
|
popFullEfficiency = maxPop;
|
|
|
|
popHalfEfficiency = currentPop - maxPop;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
popFullEfficiency = maxPop;
|
|
|
|
popHalfEfficiency = 2 * maxPop;
|
|
|
|
}
|
|
|
|
int popEffective = popFullEfficiency + (popHalfEfficiency / 2);
|
|
|
|
return popEffective / Services.Game.Player.ColonistsPerResource;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Ressources generated by factories on a player planet for a given value an
|
|
|
|
/// population. Takes maximum operable factories into account.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="currentPop">Current planetary population</param>
|
|
|
|
/// <param name="factories">Number of factories built</param>
|
|
|
|
/// <param name="value">Real planet value</param>
|
|
|
|
/// <returns>Resources generated by factories</returns>
|
|
|
|
public static int ResourcesFromFactForPlayer(int currentPop, int factories, int value)
|
|
|
|
{
|
|
|
|
int maxPop = MaxPopOnPlanetForPlayer(value);
|
|
|
|
int effectivePop = Math.Min(currentPop, maxPop);
|
|
|
|
double tmp = (double) effectivePop / 10000 * Game.Player.FactoryNumberPer10k;
|
|
|
|
int maxOperableFactories = (int) tmp;
|
|
|
|
int operableFactories = Math.Min(factories, maxOperableFactories);
|
|
|
|
tmp = (double) operableFactories / 10 * Services.Game.Player.FactoryResPer10;
|
|
|
|
return (int) tmp;
|
|
|
|
}
|
2024-08-23 15:57:09 +00:00
|
|
|
|
|
|
|
}
|