Skip to content

Commit

Permalink
Tighten the grid to add less area around the edge (less memory usage)
Browse files Browse the repository at this point in the history
  • Loading branch information
joelverhagen committed Jan 19, 2024
1 parent 9102869 commit d84f671
Show file tree
Hide file tree
Showing 2,310 changed files with 104,259 additions and 135,803 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,11 @@ AMD Ryzen 9 3950X, 1 CPU, 32 logical and 16 physical cores

| Method | Mean | Error | StdDev |
| ----------------------------------------- | -------: | -------: | -------: |
| MediumElectricPole_NoBeacon_NoUnderground | 17.72 ms | 0.146 ms | 0.137 ms |
| SmallElectricPole_Beacon_Underground | 30.65 ms | 0.328 ms | 0.307 ms |
| MediumElectricPole_Beacon_Underground | 30.95 ms | 0.379 ms | 0.355 ms |
| BigElectricPole_Beacon_Underground | 73.10 ms | 0.602 ms | 0.534 ms |
| Substation_Beacon_Underground | 35.21 ms | 0.202 ms | 0.189 ms |
| MediumElectricPole_NoBeacon_NoUnderground | 17.43 ms | 0.090 ms | 0.085 ms |
| SmallElectricPole_Beacon_Underground | 31.82 ms | 0.122 ms | 0.114 ms |
| MediumElectricPole_Beacon_Underground | 31.78 ms | 0.292 ms | 0.273 ms |
| BigElectricPole_Beacon_Underground | 69.82 ms | 1.009 ms | 0.944 ms |
| Substation_Beacon_Underground | 33.92 ms | 0.199 ms | 0.186 ms |

### Lua performance log

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Knapcode.FactorioTools.OilField;

public static class NormalizeBlueprints
{
public static void Execute(string inputPath, string excludePath)
public static void Execute(string inputPath, string excludePath, bool allowComments)
{
var exclude = NormalizeFile(excludePath).ToLookup(x => x.Normalized);

Expand All @@ -17,24 +17,19 @@ public static void Execute(string inputPath, string excludePath)
var added = new HashSet<string>();
var orderedInput = input
.Concat(exclude.SelectMany(g => g))
.Where(x => x.Valid)
.Where(x => !exclude[x.Normalized].Any())
.Where(x => allowComments || x.Valid)
.Where(x => !x.Valid || !exclude[x.Normalized].Any())
.OrderBy(x => x.Index);

foreach (var line in orderedInput)
{
if (line.Normalized is null)
var outputLine = line.Normalized ?? line.Original;
if (added.Add(outputLine))
{
continue;
}

if (added.Add(line.Normalized))
{
output.Add(line.Normalized);
output.Add(outputLine);
}
}


File.WriteAllLines(inputPath, output);
}

Expand Down
2 changes: 1 addition & 1 deletion src/FactorioTools/CollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public static class CollectionExtensions
return min;
}

public static TResult? Min<TSource, TResult>(this IReadOnlyList<TSource> source, Func<TSource, TResult> selector)
public static TResult? Min<TSource, TResult>(this IReadOnlyCollection<TSource> source, Func<TSource, TResult> selector)
{
TResult? min = default;
var hasItem = false;
Expand Down
8 changes: 6 additions & 2 deletions src/FactorioTools/OilField/Grid/SquareGrid.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,14 @@ public override string ToString()
public void ToString(StringBuilder builder, int spacing)
{
var maxLabelLength = _entityLocations.EnumerateItems().Max(x => this[x]!.Label.Length) + spacing;
var minX = _entityLocations.EnumerateItems().Min(l => l.X);
var minY = _entityLocations.EnumerateItems().Min(l => l.Y);
var maxX = _entityLocations.EnumerateItems().Max(l => l.X);
var maxY = _entityLocations.EnumerateItems().Max(l => l.Y);

for (var y = 0; y < Height; y++)
for (var y = minY; y <= maxY; y++)
{
for (var x = 0; x < Width; x++)
for (var x = minX; x <= maxX; x++)
{
var location = new Location(x, y);
var entity = _grid[y * Width + x];
Expand Down
157 changes: 85 additions & 72 deletions src/FactorioTools/OilField/Steps/InitializeContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,7 @@ public static class InitializeContext
{
public static Context Execute(OilFieldOptions options, Blueprint blueprint, IReadOnlyList<AvoidLocation> avoid)
{
// Translate the blueprint by the minimum X and Y. Leave three spaces on both lesser (left for X, top for Y) sides to cover:
// - The side of the pumpjack. It is a 3x3 entity and the position of the entity is the center.
// - A spot for a pipe, if needed.
// - A spot for an electric pole, if needed.
var marginX = 1 + 1 + options.ElectricPoleWidth;
var marginY = 1 + 1 + options.ElectricPoleHeight;

if (options.AddBeacons)
{
marginX += options.BeaconSupplyWidth + (options.BeaconWidth / 2);
marginY += options.BeaconSupplyHeight + (options.BeaconHeight / 2);
}

return Execute(options, blueprint, avoid, marginX, marginY);
return Execute(options, blueprint, avoid, minWidth: 0, minHeight: 0);
}

public static Context GetEmpty(OilFieldOptions options, int width, int height)
Expand All @@ -49,11 +36,11 @@ public static Context GetEmpty(OilFieldOptions options, int width, int height)
return Execute(options, blueprint, Array.Empty<AvoidLocation>(), width, height);
}

private static Context Execute(OilFieldOptions options, Blueprint blueprint, IReadOnlyList<AvoidLocation> avoid, int marginX, int marginY)
public static Context Execute(OilFieldOptions options, Blueprint blueprint, IReadOnlyList<AvoidLocation> avoid, int minWidth, int minHeight)
{
var (centerAndOriginalDirections, avoidLocations, deltaX, deltaY) = TranslateLocations(blueprint, avoid, marginX, marginY);
var (centerAndOriginalDirections, avoidLocations, deltaX, deltaY, width, height) = TranslateLocations(options, blueprint, avoid, minWidth, minHeight);

var grid = InitializeGrid(centerAndOriginalDirections, avoidLocations, marginX, marginY);
var grid = InitializeGrid(centerAndOriginalDirections, avoidLocations, width, height);

var centers = new List<Location>(centerAndOriginalDirections.Count);
PopulateCenters(centerAndOriginalDirections, centers);
Expand Down Expand Up @@ -148,9 +135,15 @@ private static int[] GetLocationToAdjacentCount(SquareGrid grid)
return locationToHasAdjacentPumpjack;
}

private record TranslatedLocations(List<Tuple<Location, Direction>> CenterAndOriginalDirections, List<Location> AvoidLocations, float DeltaX, float DeltaY);
private record TranslatedLocations(
List<Tuple<Location, Direction>> CenterAndOriginalDirections,
List<Location> AvoidLocations,
float DeltaX,
float DeltaY,
int Width,
int Height);

private static TranslatedLocations TranslateLocations(Blueprint blueprint, IReadOnlyList<AvoidLocation> avoid, int marginX, int marginY)
private static TranslatedLocations TranslateLocations(OilFieldOptions options, Blueprint blueprint, IReadOnlyList<AvoidLocation> avoid, int minWidth, int minHeight)
{
var pumpjacks = new List<Entity>();
for (var i = 0; i < blueprint.Entities.Length; i++)
Expand All @@ -174,77 +167,97 @@ private static TranslatedLocations TranslateLocations(Blueprint blueprint, IRead
float deltaX = 0;
float deltaY = 0;

if (pumpjacks.Count > 0 || avoid.Count > 0)
if (pumpjacks.Count == 0 && avoid.Count == 0)
{
float minX = float.MaxValue;
float minY = float.MaxValue;
return new TranslatedLocations(centerAndOriginalDirections, avoidLocations, deltaX, deltaY, minWidth, minHeight);
}

if (pumpjacks.Count > 0)
{
minX = pumpjacks.Min(p => p.Position.X);
minY = pumpjacks.Min(p => p.Position.Y);
}
var minX = float.MaxValue;
var minY = float.MaxValue;
var maxX = float.MinValue;
var maxY = float.MinValue;

if (avoid.Count > 0)
{
minX = Math.Min(minX, avoid.Min(a => a.X));
minY = Math.Min(minY, avoid.Min(a => a.Y));
}
if (pumpjacks.Count > 0)
{
var pumpjackOffsetX = PumpjackWidth / 2;
var pumpjackOffsetY = PumpjackHeight / 2;

deltaX = 0 - minX + marginX;
deltaY = 0 - minY + marginY;
minX = pumpjacks.Min(p => p.Position.X) - pumpjackOffsetX;
minY = pumpjacks.Min(p => p.Position.Y) - pumpjackOffsetY;
maxX = pumpjacks.Max(p => p.Position.X) + pumpjackOffsetX;
maxY = pumpjacks.Max(p => p.Position.Y) + pumpjackOffsetY;

for (int i = 0; i < pumpjacks.Count; i++)
if (options.AddBeacons)
{
var p = pumpjacks[i];
var x = ToInt(p.Position.X + deltaX, $"Entity {p.EntityNumber} (a '{p.Name}') does not have an integer X value after translation.");
var y = ToInt(p.Position.Y + deltaY, $"Entity {p.EntityNumber} (a '{p.Name}') does not have an integer Y value after translation.");
var center = new Location(x, y);
var originalDirection = p.Direction.GetValueOrDefault(Direction.Up);
centerAndOriginalDirections.Add(Tuple.Create(center, originalDirection));
// leave room around pumpjacks for beacons
var beaconOffsetX = ((options.BeaconSupplyWidth - 1) / 2) + (options.BeaconWidth / 2);
var beaconOffsetY = ((options.BeaconSupplyHeight - 1) / 2) + (options.BeaconHeight / 2);
minX -= beaconOffsetX;
minY -= beaconOffsetY;
maxX += beaconOffsetX;
maxY += beaconOffsetY;
}
}

for (var i = 0; i < avoid.Count; i++)
{
var a = avoid[i];
var x = ToInt(a.X + deltaX, $"Avoided location {i} does not have an integer X value after translation.");
var y = ToInt(a.Y + deltaY, $"Avoided location {i} does not have an integer Y value after translation.");
var avoidLocation = new Location(x, y);
avoidLocations.Add(avoidLocation);
}
if (avoid.Count > 0)
{
minX = Math.Min(minX, avoid.Min(a => a.X));
minY = Math.Min(minY, avoid.Min(a => a.Y));
maxX = Math.Max(maxX, avoid.Max(a => a.X));
maxY = Math.Max(maxY, avoid.Max(a => a.Y));
}

return new TranslatedLocations(centerAndOriginalDirections, avoidLocations, deltaX, deltaY);
}
// Leave some space on all sides to cover:
// - A spot for a pipe.
// - A spot for a electric pole.
minX -= 1 + options.ElectricPoleWidth;
minY -= 1 + options.ElectricPoleHeight;
maxX += 1 + options.ElectricPoleWidth;
maxY += 1 + options.ElectricPoleHeight;

private static SquareGrid InitializeGrid(List<Tuple<Location, Direction>> centerAndOriginalDirections, List<Location> avoidLocations, int marginX, int marginY)
{
// Make a grid to contain game state. Similar to the above, we add extra spots for the pumpjacks, pipes, and
// electric poles.
int width = marginX;
int height = marginY;
deltaX = -minX;
deltaY = -minY;

if (centerAndOriginalDirections.Count > 0 || avoidLocations.Count > 0)
var width = ToInt(maxX - minX, "The grid width is not an integer after translation.") + 1;
var height = ToInt(maxY - minY, "The grid height is not an integer after translation.") + 1;

if (minWidth > width)
{
var maxX = int.MinValue;
var maxY = int.MinValue;
deltaX += (minWidth - width) / 2;
width = minWidth;
}

if (centerAndOriginalDirections.Count > 0)
{
maxX = centerAndOriginalDirections.Max(p => p.Item1.X);
maxY = centerAndOriginalDirections.Max(p => p.Item1.Y);
}
if (minHeight > height)
{
deltaY += (minHeight - height) / 2;
height = minHeight;
}

if (avoidLocations.Count > 0)
{
maxX = Math.Max(maxX, avoidLocations.Max(a => a.X));
maxY = Math.Max(maxY, avoidLocations.Max(a => a.Y));
}
for (int i = 0; i < pumpjacks.Count; i++)
{
var p = pumpjacks[i];
var x = ToInt(p.Position.X + deltaX, $"Entity {p.EntityNumber} (a '{p.Name}') does not have an integer X value after translation.");
var y = ToInt(p.Position.Y + deltaY, $"Entity {p.EntityNumber} (a '{p.Name}') does not have an integer Y value after translation.");
var center = new Location(x, y);
var originalDirection = p.Direction.GetValueOrDefault(Direction.Up);
centerAndOriginalDirections.Add(Tuple.Create(center, originalDirection));
}

width += 1 + maxX;
height += 1 + maxY;
for (var i = 0; i < avoid.Count; i++)
{
var a = avoid[i];
var x = ToInt(a.X + deltaX, $"Avoided location {i} does not have an integer X value after translation.");
var y = ToInt(a.Y + deltaY, $"Avoided location {i} does not have an integer Y value after translation.");
var avoidLocation = new Location(x, y);
avoidLocations.Add(avoidLocation);
}


return new TranslatedLocations(centerAndOriginalDirections, avoidLocations, deltaX, deltaY, width, height);
}

private static SquareGrid InitializeGrid(List<Tuple<Location, Direction>> centerAndOriginalDirections, List<Location> avoidLocations, int width, int height)
{
const int maxWidth = 1000;
const int maxHeight = 1000;
const int maxArea = 500 * 500;
Expand Down
3 changes: 2 additions & 1 deletion src/Sandbox/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ private static void Main(string[] args)
{
if (args.Length > 0 && args[0] == "normalize")
{
NormalizeBlueprints.Execute(BigListDataPath, SmallListDataPath);
NormalizeBlueprints.Execute(SmallListDataPath, BigListDataPath, allowComments: true);
NormalizeBlueprints.Execute(BigListDataPath, SmallListDataPath, allowComments: false);
}
else if (args.Length > 0 && args[0] == "sample")
{
Expand Down
Loading

0 comments on commit d84f671

Please sign in to comment.