public override void PlaceCombatants(SafeDictionary <ICombatant, IntVector2> locations) { if (Sector.SpaceObjects.OfType <WarpPoint>().Any()) { // HACK - warp point in sector, assume someone warped // TODO - do this for warp point exits instead since warp points may be one way // warp battles start with everyone mashed together to allow blockades foreach (var c in Combatants.OrderByDescending(q => q.Size)) { PlaceCombatant(locations, 0, 0, c); } } else { // place all combatants at the points of a regular polygon var sideLength = 20 + (int)Math.Ceiling((double)Combatants.GroupBy(q => q.Owner).Max(q => q.Count())); // make sure no one can shoot each other at the start // https://stackoverflow.com/questions/32169875/calculating-the-coordinates-of-a-regular-polygon-given-its-center-and-its-side-l var radius = sideLength / (2 * Sin(PI / Empires.Count())); var combs = Combatants.ToArray(); for (int i = 0; i < Empires.Count(); i++) { var x = radius * Cos(PI / Empires.Count() * (1 + 2 * i)); var y = radius * Sin(PI / Empires.Count() * (1 + 2 * i)); foreach (var comb in Combatants.Where(q => q.Owner == Empires.ElementAt(i)).OrderByDescending(q => q.Size)) { PlaceCombatant(locations, x, y, comb); } } } }