/// <summary> /// Reconstitutes the given tree into a new one (balances it) /// </summary> /// <param name="OldTree"></param> public Company_KDTree(Company_KDTree OldTree) { List<Company> CompanyList = new List<Company>(); OldTree.GetAllCompanies(ref CompanyList); Company[] CompanyArray = CompanyList.ToArray(); SplitDimensionIndex = 0; if (CompanyArray.Length > 2) { SortByDimension(ref CompanyArray, SplitDimensionIndex); int MedianIndex = CompanyArray.Length / 2; SplitPosition = CompanyArray[MedianIndex].Location[SplitDimensionIndex]; Company[] LowerList = new Company[MedianIndex + 1]; Company[] UpperList = new Company[CompanyArray.Length - MedianIndex - 1]; Array.Copy(CompanyArray, 0, LowerList, 0, LowerList.Length); Array.Copy(CompanyArray, MedianIndex + 1, UpperList, 0, UpperList.Length); LessEqualNode = new Company_KDTree(SplitDimensionIndex, LowerList); GreaterNode = new Company_KDTree(SplitDimensionIndex, UpperList); } else { Constituents = CompanyArray; isLeafNode = true; } }
public double DistanceTo(Company Other) { double Distance = 0.0; for (int i = 0; i < Location.Length; i++) { Distance += Math.Pow(Location[i] - Other.Location[i], 2); } Other.DistanceRegister = Math.Sqrt(Distance); return Other.DistanceRegister; }
/// <summary> /// Organizes Companies by X Y Z coordinates /// More efficient to recreate a tree rather than update it /// </summary> /// <param name="ParentSplitDimensionIndex">Outside of this constructor, inputs should be -1</param> /// <param name="UnitList">Should be converted from a List</param> public Company_KDTree(int ParentSplitDimensionIndex, Company[] CompanyList) { SplitDimensionIndex = (ParentSplitDimensionIndex + 1) % 3; if (CompanyList.Length > 2) { SortByDimension(ref CompanyList, SplitDimensionIndex); int MedianIndex = CompanyList.Length / 2; SplitPosition = CompanyList[MedianIndex].Location[SplitDimensionIndex]; Company[] LowerList = new Company[MedianIndex + 1]; Company[] UpperList = new Company[CompanyList.Length - MedianIndex - 1]; Array.Copy(CompanyList, 0, LowerList, 0, LowerList.Length); Array.Copy(CompanyList, MedianIndex + 1, UpperList, 0, UpperList.Length); LessEqualNode = new Company_KDTree(SplitDimensionIndex, LowerList); GreaterNode = new Company_KDTree(SplitDimensionIndex, UpperList); } else { Constituents = CompanyList; isLeafNode = true; } }
public void Update() { Age += 0.01; //Assets slowly degrade and turn into money Assets *= Math.Pow(Math.E, -0.001 * SkillLevel); Money += Assets * (Math.Pow(Math.E, 0.0001 * SkillLevel) - 1.0); //Search through the closest businesses for the best bargains and opportunities List<Company> Shops = new List<Company>(); double Distance = double.PositiveInfinity; Manager.Businesses.FindClosestBusinesses(this, ref Shops, ref Distance, MyGame.random.Next(5, 10)); if (Dynasty == null) { if (Employer == null) { //Look for a job or try to start one if (Shops.Count > 0) { Shops[MyGame.random.Next(Shops.Count)].QueryForEmployment(this); if (Employer == null) { Manager.FractionalDynasties += 0.05 * SkillLevel; if (Manager.FractionalDynasties > 1.0 && Money > 10) { Manager.FractionalDynasties--; Dynasty = new Conglomerate(Location, Money * 0.95); Money *= 0.05; } } } else { //With nothing nearby, someone must be an entrepreneur Manager.FractionalDynasties += 0.25 * SkillLevel; if (Manager.FractionalDynasties > 1.0 && Money > 10) { Manager.FractionalDynasties--; Dynasty = new Conglomerate(Location, Money * 0.95); Money *= 0.05; } } } else { //Consider quitting the job and starting a new Dynasty if (MyGame.random.NextDouble() > 0.9) { Manager.FractionalDynasties += 0.01 * SkillLevel; if (Manager.FractionalDynasties > 1.0 && Money > 10) { Manager.FractionalDynasties--; Dynasty = new Conglomerate(Location, Money * 0.95); Money *= 0.05; Employer.Employees.Remove(this); Employer = null; } } } } else { Dynasty.Update(); if (Dynasty.Subsidaries.Count > 0) { double SelfSalary = SkillLevel + Productivity; if (Dynasty.Money > SelfSalary) { Dynasty.Money -= SelfSalary; Money += SelfSalary; } else { Dynasty.Money *= 0.5; Money += Dynasty.Money; } } else { Money += Dynasty.Money; Contentness += Dynasty.SurplusInventory * Math.Pow(1.5, Dynasty.SurplusQuality); Dynasty = null; } } if (Assets > Math.E) { Contentness -= Productivity / Math.Log(Assets); } else { Contentness -= Productivity; } //Iterate through the list of nearby Companies and buy goods with available money for (int i = 0; i < Shops.Count && Money > 0.0; i++) { if (Shops[i].Inventory > 0.0 && Shops[i].Effectiveness > 0.0) { double units = Money / Shops[i].Price; if (units > Shops[i].Inventory) { units = Shops[i].Inventory; } Money -= units * Shops[i].Price; Shops[i].Inventory -= units; Shops[i].Money += units * Shops[i].Price; Assets += units * Shops[i].Effectiveness / 10.0; Contentness += units * Shops[i].Effectiveness; } } //Evaluate the effects of Contentness on Productivity if (Contentness > 1) { Productivity += 0.001; } else if (Contentness < 0) { Productivity *= Math.Pow(Math.E, -0.001); Contentness /= 2; } }
private static void SortByDimension(ref Company[] Unsorted, int DimensionIndex) { if (Unsorted.Length > 0) { List<List<Company>> Sorter = new List<List<Company>>(); for (int i = 0; i < Unsorted.Length; i++) { Sorter.Add(new List<Company>()); Sorter[i].Add(Unsorted[i]); } while (Sorter.Count > 1) { for (int i = 0; i < Sorter.Count - 1; i++) { for (int a = 0; a < Sorter[i].Count; a++) { for (int b = 0; b < Sorter[i + 1].Count; b++) { if (Sorter[i + 1][b].Location[DimensionIndex] < Sorter[i][a].Location[DimensionIndex]) { Sorter[i].Insert(a++, Sorter[i + 1][b]); Sorter[i + 1].RemoveAt(b--); } } } Sorter[i].AddRange(Sorter[i + 1]); Sorter.RemoveAt(i + 1); } } Unsorted = Sorter[0].ToArray(); } }
public void InsertCompany(Company Newbie) { if (isLeafNode) { Array.Resize<Company>(ref Constituents, Constituents.Length + 1); Constituents[Constituents.Length - 1] = Newbie; } else { if (Newbie.Location[SplitDimensionIndex] > SplitPosition) { GreaterNode.InsertCompany(Newbie); } else { LessEqualNode.InsertCompany(Newbie); } } }
public void FindClosestBusinesses(Company Searcher , ref List<Company> CurrentClosest, ref double MaxDistance, int NumCompanies , double MinCapitalLevel, double MaxCapitalLevel) { if (isLeafNode) { for (int i = 0; i < Constituents.Length; i++) { if (Constituents[i].CapitalLevel > MinCapitalLevel && Constituents[i].CapitalLevel < MaxCapitalLevel && Constituents[i].Inventory > 0.0 && Constituents[i].Price > 0.0 && Searcher.DistanceTo(Constituents[i]) <= MaxDistance) { if (CurrentClosest.Count == 0) { CurrentClosest.Add(Constituents[i]); } else { for (int j = CurrentClosest.Count - 1; j >= 0; j--) { if (Constituents[i].DistanceRegister > CurrentClosest[j].DistanceRegister) { CurrentClosest.Insert(j + 1, Constituents[i]); } } } } } if (CurrentClosest.Count > NumCompanies) { CurrentClosest.RemoveRange(NumCompanies, CurrentClosest.Count - NumCompanies); } } else { if (Searcher.Location[SplitDimensionIndex] > SplitPosition) { GreaterNode.FindClosestBusinesses(Searcher , ref CurrentClosest, ref MaxDistance, NumCompanies , MinCapitalLevel, MaxCapitalLevel); if (Searcher.Location[SplitDimensionIndex] - MaxDistance < SplitPosition) { LessEqualNode.FindClosestBusinesses(Searcher , ref CurrentClosest, ref MaxDistance, NumCompanies , MinCapitalLevel, MaxCapitalLevel); } } else { LessEqualNode.FindClosestBusinesses(Searcher , ref CurrentClosest, ref MaxDistance, NumCompanies , MinCapitalLevel, MaxCapitalLevel); if (Searcher.Location[SplitDimensionIndex] + MaxDistance > SplitPosition) { GreaterNode.FindClosestBusinesses(Searcher , ref CurrentClosest, ref MaxDistance, NumCompanies , MinCapitalLevel, MaxCapitalLevel); } } } }