using System; namespace ProjectI.Enemies { public static class EnemyDirectorRules { public static double Accrue(double available, double elapsed, double incomePerSecond, double ceiling) { if (!Finite(available) || available < 0) return 0; if (!Finite(elapsed) || elapsed < 0 || !Finite(incomePerSecond) || incomePerSecond < 0 || !Finite(ceiling) || ceiling < available) return available; if (incomePerSecond == 0 || elapsed == 0) return available; double remaining = ceiling - available; return elapsed >= remaining / incomePerSecond ? ceiling : Math.Min(ceiling, available + elapsed * incomePerSecond); } public static double Income(double baseIncome, int stage, double activeMinutes, double difficulty, int participants) { if (!Finite(baseIncome) || baseIncome < 0 || stage < 1 || !Finite(activeMinutes) || activeMinutes < 0 || !Finite(difficulty) || difficulty <= 0 || participants < 1 || participants > 4) return 0; double scale = (1 + .4 * (participants - 1)) * Math.Min(4, Math.Pow(1.15, Math.Min(11, stage - 1))) * (activeMinutes >= 50 ? 3 : 1 + .04 * activeMinutes); // Saturate extreme finite inputs without permitting Infinity in a bank calculation. double smaller = Math.Min(baseIncome, difficulty), larger = Math.Max(baseIncome, difficulty); double rate = smaller * scale; if (!Finite(rate) || rate > double.MaxValue / larger) return double.MaxValue; return rate * larger; } internal static bool Finite(double value) => !double.IsNaN(value) && !double.IsInfinity(value); } }