sa/Stars Assistant/Services/GameEngine.cs

177 lines
6.8 KiB
C#
Raw Normal View History

using System;
using Splat;
namespace StarsAssistant.Services;
public class GameEngine
{
/// <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);
int growth;
if (value < 0)
{
2024-09-24 20:32:13 +00:00
growth = currentPop * value / 1000;
}
else
{
2024-09-24 20:32:13 +00:00
double popRatio = (double) currentPop / maxPop;
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);
}
}
// round down by 100
return growth / 100 * 100;
}
/// <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;
}
/// <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;
}
}