public override void Execute() { int nConstellations; int factorA, factorB, a, b, factor; bool gotMatch; List<Region> neutralRegions = new List<Region>(); List<Region> spawnRegions = new List<Region>(); System.Diagnostics.Trace.WriteLine(this.Name + " - Execute - begin"); //BUILD REGIONS foreach (Color c in Galaxy.Instance.Configuration.shape().regions.Keys) Galaxy.Instance.Regions.Add(new Region(c)); neutralRegions.AddRange(Galaxy.Instance.Regions.FindAll((Region r) => { return !r.isSpawn(); })); spawnRegions.AddRange(Galaxy.Instance.Regions.FindAll((Region r) => { return r.isSpawn(); })); System.Diagnostics.Trace.WriteLine(Galaxy.Instance.Configuration.shape().regions.Keys.Count.ToString() + " theoretical regions"); System.Diagnostics.Trace.WriteLine(Galaxy.Instance.Regions.Count.ToString() + " actual regions"); System.Diagnostics.Trace.WriteLine(spawnRegions.Count.ToString() + " spawn regions"); foreach (Region r in spawnRegions) System.Diagnostics.Trace.WriteLine("-->" + r.Index.ToString() + " containing " + r.Count.ToString()+ " stars"); System.Diagnostics.Trace.WriteLine(neutralRegions.Count.ToString() + " neutral regions"); foreach (Region r in neutralRegions) System.Diagnostics.Trace.WriteLine("-->" + r.Index.ToString() + " containing " + r.Count.ToString() + " stars"); //DETERMINE ACTUAL CONSTELLATIONS NUMBER nConstellations = Galaxy.Instance.Configuration.constellations(); System.Diagnostics.Trace.WriteLine("Configuration requested constellations : " + Galaxy.Instance.Configuration.constellations().ToString()); while ((nConstellations * Settings.Instance.generationConstraints.minStarsPerConstellation) > Galaxy.Instance.Stars.Count) nConstellations--; if (nConstellations <= 0) nConstellations = 1; if (nConstellations < Galaxy.Instance.Configuration.constellations()) { System.Diagnostics.Trace.WriteLine("Min stars per constellation : " + Settings.Instance.generationConstraints.minStarsPerConstellation.ToString()); System.Diagnostics.Trace.WriteLine("Will use only " + nConstellations.ToString() + " constellations"); this.Defects.Add("Number of constellations was limited by stars number"); } //DISTRIBUTE CONSTELLATIONS ACROSS REGIONS if (nConstellations == 1) { System.Diagnostics.Trace.WriteLine("Single Constellation"); Constellation c = new Constellation(); c.AddRange(Galaxy.Instance.Stars); } else if (nConstellations == Galaxy.Instance.Regions.Count) { System.Diagnostics.Trace.WriteLine("One Constellation Per Region"); foreach (Region r in Galaxy.Instance.Regions) { Constellation c = new Constellation(); c.AddRange(r); } } else { System.Diagnostics.Trace.WriteLine("Other Case"); factorA = 0; factorB = 0; gotMatch = false; for (a = 1; a < 20; a++) { for (b = 0; b < 20; b++) { if (a * spawnRegions.Count + b * neutralRegions.Count == nConstellations) { gotMatch = true; factorA = a; factorB = b; } } } if (gotMatch) { System.Diagnostics.Trace.WriteLine("Could find integers A=" + factorA.ToString() + " and B=" + factorB.ToString()); System.Diagnostics.Trace.WriteLine("Allowing A Constellations in each Spawn Region"); System.Diagnostics.Trace.WriteLine("And B Constellation in each Neutral Region"); if (factorA > 0) { foreach (Region r in spawnRegions) { this.MakeConstellations(factorA, r); } } if (factorB > 0) { foreach (Region r in neutralRegions) { this.MakeConstellations(factorB, r); } } } else { System.Diagnostics.Trace.WriteLine("No exact match"); if (nConstellations >= spawnRegions.Count) { System.Diagnostics.Trace.WriteLine("More Constellations than Spawn Regions"); foreach (Region r in spawnRegions) { this.MakeConstellations(1, r); } if (nConstellations - spawnRegions.Count > 0) { List<StarSystem> pool = new List<StarSystem>(); foreach(Region r in neutralRegions) pool.AddRange(r); this.MakeConstellations(nConstellations - spawnRegions.Count, pool); } } else { System.Diagnostics.Trace.WriteLine("Less Constellations than Spawn Regions"); factor = 1; while (factor * nConstellations < spawnRegions.Count) factor++; Region start; Region merge; List<Region> adjacentSpawnRegions = new List<Region>(); List<Region> mergedRegions = new List<Region>(); List<Region> nextStartCandidates = new List<Region>(); List<StarSystem> pool = new List<StarSystem>(); int i; //loop //starting with one random spawn region //merge (factor adjacent spawn regions) into result //make one constellation in result //until remaining spawn regions number less than factor System.Diagnostics.Trace.WriteLine("Using topology to try grouping " + factor.ToString() + " Spawn Regions in each Constellation"); start = spawnRegions.ElementAt(GalaxyGeneratorPlugin.random.Next(spawnRegions.Count)); while ((spawnRegions.Count >= factor) && (start != null) && (Galaxy.Instance.Constellations.Count < nConstellations)) { i = 0; spawnRegions.Remove(start); mergedRegions.Clear(); mergedRegions.Add(start); adjacentSpawnRegions.AddRange(start.adjacentRegions().FindAll((r) => { return r.isSpawn(); })); adjacentSpawnRegions.RemoveAll((r) => { return !spawnRegions.Contains(r); }); for (; (i < factor-1) && (adjacentSpawnRegions.Count > 0); i++) { adjacentSpawnRegions.Clear(); foreach (Region r in mergedRegions) adjacentSpawnRegions.AddRange(r.adjacentRegions()); adjacentSpawnRegions.RemoveAll((r) => { return mergedRegions.Contains(r); }); adjacentSpawnRegions.RemoveAll((r) => { return !r.isSpawn(); }); adjacentSpawnRegions.RemoveAll((r) => { return !spawnRegions.Contains(r); }); if (adjacentSpawnRegions.Count > 0) { merge = adjacentSpawnRegions.ElementAt(GalaxyGeneratorPlugin.random.Next(adjacentSpawnRegions.Count)); mergedRegions.Add(merge); spawnRegions.Remove(merge); } } System.Diagnostics.Trace.WriteLine("Merging regions :"); foreach (Region r in mergedRegions) System.Diagnostics.Trace.WriteLine("--->"+r.Index.ToString()); pool.Clear(); foreach (Region r in mergedRegions) pool.AddRange(r); this.MakeConstellations(1, pool); nextStartCandidates.Clear(); foreach(Region r in mergedRegions) nextStartCandidates.AddRange(r.adjacentRegions()); nextStartCandidates.RemoveAll((r) => { return mergedRegions.Contains(r); }); nextStartCandidates.RemoveAll((r) => { return !r.isSpawn(); }); nextStartCandidates.RemoveAll((r) => { return !spawnRegions.Contains(r); }); if (nextStartCandidates.Count > 0) start = nextStartCandidates.ElementAt(GalaxyGeneratorPlugin.random.Next(nextStartCandidates.Count)); else if (spawnRegions.Count > 0) start = spawnRegions.ElementAt(GalaxyGeneratorPlugin.random.Next(spawnRegions.Count)); else start = null; } //merge (remaining spawn regions with neutral regions) into result //make (nConstellations - Galaxy.Instance.Constellations.Count) constellations in result System.Diagnostics.Trace.WriteLine("Merging remaining Spawn Regions with Neutral Regions"); System.Diagnostics.Trace.WriteLine("and making remaining Constellations"); pool.Clear(); foreach (Region r in spawnRegions) pool.AddRange(r); foreach (Region r in neutralRegions) pool.AddRange(r); this.MakeConstellations(nConstellations - Galaxy.Instance.Constellations.Count, pool); } } if (Galaxy.Instance.Constellations.Count == 0) { System.Diagnostics.Trace.WriteLine("Failing to associate regions and constellations"); System.Diagnostics.Trace.WriteLine("Creating brutally " + nConstellations.ToString() + " constellations with " + Galaxy.Instance.Stars.Count.ToString()); this.MakeConstellations(nConstellations, Galaxy.Instance.Stars); this.Defects.Add("Unable to correlate regions and constellations"); } this.AggregateIsolatedStars(); } this.Result = true; System.Diagnostics.Trace.WriteLine(this.Name + " - Execute - end"); }