diff --git a/Stars Assistant/Model/Planet.cs b/Stars Assistant/Model/Planet.cs
index b7ab232..08ea465 100644
--- a/Stars Assistant/Model/Planet.cs
+++ b/Stars Assistant/Model/Planet.cs
@@ -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
diff --git a/Stars Assistant/Model/Race.cs b/Stars Assistant/Model/Race.cs
index 691ce4b..2bdf7b6 100644
--- a/Stars Assistant/Model/Race.cs
+++ b/Stars Assistant/Model/Race.cs
@@ -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;
}
diff --git a/Stars Assistant/Services/Game.cs b/Stars Assistant/Services/Game.cs
index 795aa54..e44edfc 100644
--- a/Stars Assistant/Services/Game.cs
+++ b/Stars Assistant/Services/Game.cs
@@ -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));
diff --git a/Stars Assistant/Services/GameEngine.cs b/Stars Assistant/Services/GameEngine.cs
index b6b9fda..cfb9e89 100644
--- a/Stars Assistant/Services/GameEngine.cs
+++ b/Stars Assistant/Services/GameEngine.cs
@@ -1,8 +1,162 @@
using System;
+using Splat;
namespace StarsAssistant.Services;
public class GameEngine
{
+ ///
+ /// Helper reference to the Game, populated during service registration for the
+ /// loaded game.
+ ///
+ // TODO: check for better options here.
+ public static Game Game { get; set; } = null!;
+
+ ///
+ /// Minimum effective value of a planet for purposes of maximum population etc.
+ ///
+ public const int MinEffectiveValue = 5;
+
+ ///
+ /// Normalize a planet value for minimum effetive value.
+ ///
+ /// Real planet value
+ /// Effective plante value
+ public static int EffectivePlanetValue(int value) => (value < MinEffectiveValue) ? MinEffectiveValue : value;
+
+ ///
+ /// Compute the maximum regular (non-overcrowded) population on a planet for the active player.
+ ///
+ /// Real planet value
+ /// effective maximum population
+ public static int MaxPopOnPlanetForPlayer(int value) => Game.Player.MaxPopOnPlanet * EffectivePlanetValue(value) / 100;
+
+ ///
+ /// Compute population growth for player planets.
+ ///
+ /// Current population on planet
+ /// Real planet value
+ /// population growth per turn
+ 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;
+ }
+
+ ///
+ /// Returns the maximum operable factories on a given player planet for a given value.
+ ///
+ /// Population on planet
+ /// Real planet value
+ /// Maximum operable factories for currentPop
+ 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;
+ }
+
+ ///
+ /// Maximum buildable factories on a player planet with a given value.
+ ///
+ /// Real Planet Value
+ /// Maximum buildable factories
+ public static int MaxBuildableFactoriesForPlayer(int value)
+ {
+ double tmp = (double) MaxPopOnPlanetForPlayer(value) / 10000 * Game.Player.FactoryNumberPer10k;
+ return (int) tmp;
+ }
+
+ ///
+ /// Returns the maximum operable mines on a given player planet for a given value.
+ ///
+ /// Population on planet
+ /// Real planet value
+ /// Maximum operable mines for currentPop
+ 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;
+ }
+
+ ///
+ /// Maximum buildable factories on a player planet with a given value.
+ ///
+ /// Real Planet Value
+ /// Maximum buildable factories
+ public static int MaxBuildableMinesForPlayer(int value)
+ {
+ double tmp = (double) MaxPopOnPlanetForPlayer(value) / 10000 * Game.Player.MineNumberPer10k;
+ return (int) tmp;
+ }
+
+ ///
+ /// Ressources produced by population on a player planet with a given value. Takes
+ /// less effective overcrowding pop into account.
+ ///
+ /// Current planetary population
+ /// Real planet value
+ /// Resources generated by populationa
+ 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;
+ }
+
+ ///
+ /// Ressources generated by factories on a player planet for a given value an
+ /// population. Takes maximum operable factories into account.
+ ///
+ /// Current planetary population
+ /// Number of factories built
+ /// Real planet value
+ /// Resources generated by factories
+ 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;
+ }
}
diff --git a/Stars Assistant/ViewModels/PlanetViewModel.cs b/Stars Assistant/ViewModels/PlanetViewModel.cs
index 9ed7cf3..cdd39b2 100644
--- a/Stars Assistant/ViewModels/PlanetViewModel.cs
+++ b/Stars Assistant/ViewModels/PlanetViewModel.cs
@@ -38,6 +38,10 @@ public partial class PlanetViewModel : ViewModelBase
public int SurfaceGermanium => Planet.SurfaceGermanium ?? 0;
+
+
+ // ### TESTING CODE ###
+
public static ObservableCollection LoadAll()
{
using var db = Locator.Current.GetService()!;