Create Game Engine, update race model with defaults.
This commit is contained in:
		@@ -7,8 +7,6 @@ public class Planet
 | 
			
		||||
{
 | 
			
		||||
    #region Persistant and derived propeties
 | 
			
		||||
 | 
			
		||||
    public const int MinEffectiveValue = 5;
 | 
			
		||||
 | 
			
		||||
    [Key]
 | 
			
		||||
    public required string Name { get; set; }
 | 
			
		||||
 | 
			
		||||
@@ -90,94 +88,19 @@ public class Planet
 | 
			
		||||
 | 
			
		||||
    #region Derived Properties
 | 
			
		||||
 | 
			
		||||
    public static int EffectiveValue(int? value) {
 | 
			
		||||
        if (value == null) return 0;
 | 
			
		||||
        if (value < MinEffectiveValue) return MinEffectiveValue;
 | 
			
		||||
        return (int) value;
 | 
			
		||||
    }
 | 
			
		||||
    // public int EffectiveValue() => EffectiveValue(Value);
 | 
			
		||||
 | 
			
		||||
    public int EffectiveValue() => EffectiveValue(Value);
 | 
			
		||||
    // public int MaxPopOnPlanet() => MaxPopOnPlanet(Value);
 | 
			
		||||
 | 
			
		||||
    public static int MaxPopOnPlanet (int? value) {
 | 
			
		||||
        return Services.Game.Player.MaxPopOnPlanet * EffectiveValue(value) / 100;
 | 
			
		||||
    }
 | 
			
		||||
    // public int PopGrowth() => PopGrowth(Population ?? 0, MaxPopOnPlanet(), Value ?? 0);
 | 
			
		||||
 | 
			
		||||
    public int MaxPopOnPlanet() => MaxPopOnPlanet(Value);
 | 
			
		||||
    // public int MaxFact() => MaxFact(Population ?? 0);
 | 
			
		||||
 | 
			
		||||
    public int PopGrowth(int currentPop, int maxPop, int value) {
 | 
			
		||||
        // What to do with non player races?
 | 
			
		||||
        if (OwnerId != Services.Game.Player.Name) return 0;
 | 
			
		||||
    // public int MaxMines() => MaxMines(Population ?? 0);
 | 
			
		||||
 | 
			
		||||
        double popRatio = currentPop / maxPop;
 | 
			
		||||
        int growth = 0;
 | 
			
		||||
        if (value < 0)
 | 
			
		||||
            growth = currentPop * value / 10;
 | 
			
		||||
        else if (popRatio <= 0.25)
 | 
			
		||||
            growth = currentPop * value * (Services.Game.Player.GrowthRatePercent ?? 0) / 100;
 | 
			
		||||
        else if (popRatio <= 1)
 | 
			
		||||
            growth = currentPop * value * (Services.Game.Player.GrowthRatePercent ?? 0) /100 * 16 / 9 * ((int) Math.Pow(1 - popRatio, 2));
 | 
			
		||||
        else
 | 
			
		||||
            growth = (int) (currentPop * (popRatio - 1) * 0.04);
 | 
			
		||||
    // public int ResourcesFromPop() => ResourcesFromPop(Population ?? 0, Value ?? 0);
 | 
			
		||||
 | 
			
		||||
        return growth / 100 * 100;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public int PopGrowth() => PopGrowth(Population ?? 0, MaxPopOnPlanet(), Value ?? 0);
 | 
			
		||||
 | 
			
		||||
    public int MaxFact(int currentPop) {
 | 
			
		||||
        int effectivePop = Math.Min(currentPop, MaxPopOnPlanet());
 | 
			
		||||
        double tmp = (double) effectivePop / 10000 * Services.Game.Player.FactoryNumberPer10k ?? 0;
 | 
			
		||||
        return (int) tmp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public int MaxFact() => MaxFact(Population ?? 0);
 | 
			
		||||
 | 
			
		||||
    public int MaxMines(int currentPop) {
 | 
			
		||||
        int effectivePop = Math.Min(currentPop, MaxPopOnPlanet());
 | 
			
		||||
        double tmp = (double) effectivePop / 10000 * Services.Game.Player.MineNumberPer10k ?? 0;
 | 
			
		||||
        return (int) tmp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public int MaxMines() => MaxMines(Population ?? 0);
 | 
			
		||||
 | 
			
		||||
    public static int ResourcesFromPop(int currentPop, int value) {
 | 
			
		||||
        if (Services.Game.Player.ColonistsPerResource == null
 | 
			
		||||
            || Services.Game.Player.ColonistsPerResource == 0) 
 | 
			
		||||
        {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        int maxPop = MaxPopOnPlanet(value);
 | 
			
		||||
        int popFullEfficiency = 0;
 | 
			
		||||
        int popHalfEfficiency = 0;
 | 
			
		||||
        if (currentPop <= maxPop) {
 | 
			
		||||
            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) ?? 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public int ResourcesFromPop() => ResourcesFromPop(Population ?? 0, Value ?? 0);
 | 
			
		||||
 | 
			
		||||
    public static int ResourcesFromFact(int currentPop, int factories, int value) {
 | 
			
		||||
        int maxPop = MaxPopOnPlanet(value);
 | 
			
		||||
        int effectivePop = Math.Min(currentPop, maxPop);
 | 
			
		||||
        double tmp = (double) effectivePop / 10000 * Services.Game.Player.FactoryNumberPer10k ?? 0;
 | 
			
		||||
        int maxOperableFactories = (int) tmp;
 | 
			
		||||
        int operableFactories = Math.Min(factories, maxOperableFactories);
 | 
			
		||||
        tmp = (double) operableFactories / 10 * Services.Game.Player.FactoryResPer10 ?? 0;
 | 
			
		||||
        return (int) tmp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public int ResourcesFromFact() => ResourcesFromFact(Population ?? 0, Factories ?? 0, Value ?? 0);
 | 
			
		||||
    // public int ResourcesFromFact() => ResourcesFromFact(Population ?? 0, Factories ?? 0, Value ?? 0);
 | 
			
		||||
 | 
			
		||||
    #endregion
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -24,9 +24,9 @@ public class Race
 | 
			
		||||
 | 
			
		||||
    public int? PlayerFileId { get; set; }
 | 
			
		||||
 | 
			
		||||
    public int? ColonistsPerResource { get; set; }
 | 
			
		||||
    public int ColonistsPerResource { get; set; } = 1_000;
 | 
			
		||||
 | 
			
		||||
    public int? GrowthRatePercent { get; set; }
 | 
			
		||||
    public int GrowthRatePercent { get; set; } = 15;
 | 
			
		||||
 | 
			
		||||
    private PRT _PRT = PRT.Other;
 | 
			
		||||
    public PRT PRT { 
 | 
			
		||||
@@ -37,8 +37,8 @@ public class Race
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private bool? _hasOBRM;
 | 
			
		||||
    public bool? HasOBRM { 
 | 
			
		||||
    private bool _hasOBRM = false;
 | 
			
		||||
    public bool HasOBRM { 
 | 
			
		||||
        get => _hasOBRM; 
 | 
			
		||||
        set {
 | 
			
		||||
            _hasOBRM = value;
 | 
			
		||||
@@ -55,29 +55,29 @@ public class Race
 | 
			
		||||
    [NotMapped]
 | 
			
		||||
    public int MaxEffectivePopOnGreen { get; private set; }
 | 
			
		||||
 | 
			
		||||
    private bool? _factoryCost3;
 | 
			
		||||
    public bool? FactoryCost3 { 
 | 
			
		||||
    private bool _factoryCost3 = false;
 | 
			
		||||
    public bool FactoryCost3 { 
 | 
			
		||||
        get => _factoryCost3; 
 | 
			
		||||
        set {
 | 
			
		||||
            _factoryCost3 = value;
 | 
			
		||||
            FactoryGerCost = (_factoryCost3 ?? false) ? 3 : 4;
 | 
			
		||||
            FactoryGerCost = _factoryCost3 ? 3 : 4;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [NotMapped]
 | 
			
		||||
    public int FactoryGerCost { get; private set; }
 | 
			
		||||
 | 
			
		||||
    public int? FactoryNumberPer10k { get; set; }
 | 
			
		||||
    public int FactoryNumberPer10k { get; set; } = 10;
 | 
			
		||||
 | 
			
		||||
    public int? FactoryResCost { get; set; }
 | 
			
		||||
    public int FactoryResCost { get; set; } = 10;
 | 
			
		||||
 | 
			
		||||
    public int? FactoryResPer10 { get; set; }
 | 
			
		||||
    public int FactoryResPer10 { get; set; } = 10;
 | 
			
		||||
 | 
			
		||||
    public int? MineResCost { get; set; }
 | 
			
		||||
    public int MineResCost { get; set; } = 5;
 | 
			
		||||
 | 
			
		||||
    public int? MineNumberPer10k { get; set; }
 | 
			
		||||
    public int MineNumberPer10k { get; set; } = 10;
 | 
			
		||||
 | 
			
		||||
    public int? MineMineralsPer10 { get; set; }
 | 
			
		||||
    public int MineMineralsPer10 { get; set; } = 10;
 | 
			
		||||
 | 
			
		||||
    #endregion
 | 
			
		||||
 | 
			
		||||
@@ -101,9 +101,9 @@ public class Race
 | 
			
		||||
            PRT.JOAT => 1.2,
 | 
			
		||||
            _ => 1,
 | 
			
		||||
        };
 | 
			
		||||
        double obrmMod = (HasOBRM ?? false) ? 1.1 : 1.0;
 | 
			
		||||
        double obrmMod = HasOBRM ? 1.1 : 1.0;
 | 
			
		||||
        MaxPopOnPlanet = Convert.ToInt32(basePop * prtMod * obrmMod);
 | 
			
		||||
        MaxEffectivePopOnRed = MaxPopOnPlanet * Planet.MinEffectiveValue / 100 * 3;
 | 
			
		||||
        MaxEffectivePopOnRed = MaxPopOnPlanet * Services.GameEngine.MinEffectiveValue / 100 * 3;
 | 
			
		||||
        MaxEffectivePopOnGreen = MaxPopOnPlanet * 3;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -120,6 +120,7 @@ public class Game
 | 
			
		||||
    public void RegisterServicesForGame()
 | 
			
		||||
    {
 | 
			
		||||
        Locator.CurrentMutable.RegisterConstant(this, typeof(Services.Game));
 | 
			
		||||
        GameEngine.Game = this;
 | 
			
		||||
        Locator.CurrentMutable.RegisterConstant(new CSVDataLoader(), typeof(CSVDataLoader));
 | 
			
		||||
        Locator.CurrentMutable.Register(() => new StarsDatabase(DatabaseFileName), typeof(StarsDatabase));
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,162 @@
 | 
			
		||||
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)
 | 
			
		||||
        {
 | 
			
		||||
            growth = currentPop * value / 10;
 | 
			
		||||
        } 
 | 
			
		||||
        else 
 | 
			
		||||
        {
 | 
			
		||||
            double popRatio = currentPop / maxPop;
 | 
			
		||||
            if (popRatio <= 0.25)
 | 
			
		||||
                growth = currentPop * value * Game.Player.GrowthRatePercent / 100;
 | 
			
		||||
            else if (popRatio <= 1)
 | 
			
		||||
                growth = currentPop * value * Game.Player.GrowthRatePercent /100 * 16 / 9 * ((int) Math.Pow(1 - popRatio, 2));
 | 
			
		||||
            else
 | 
			
		||||
                 growth = (int) (currentPop * (popRatio - 1) * 0.04);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // round to nearest 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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,10 @@ public partial class PlanetViewModel : ViewModelBase
 | 
			
		||||
 | 
			
		||||
    public int SurfaceGermanium => Planet.SurfaceGermanium ?? 0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // ### TESTING CODE ###
 | 
			
		||||
 | 
			
		||||
    public static ObservableCollection<PlanetViewModel> LoadAll() 
 | 
			
		||||
    {
 | 
			
		||||
        using var db = Locator.Current.GetService<StarsDatabase>()!;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user