Skip to content

Commit

Permalink
Don't use Dictionary where GridEntity is key
Browse files Browse the repository at this point in the history
  • Loading branch information
joelverhagen committed Jan 14, 2024
1 parent ba61f98 commit ae7fb8d
Show file tree
Hide file tree
Showing 26 changed files with 184 additions and 313 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ int GetEntityNumber(ElectricPoleCenter pole)
return entityNumber;
}

foreach ((var gridEntity, var location) in context.Grid.EntityToLocation)
foreach (var location in context.Grid.EntityLocations.EnumerateItems())
{
var gridEntity = context.Grid[location];
var position = new Position
{
X = location.X,
Expand Down
4 changes: 4 additions & 0 deletions src/FactorioTools/OilField/Grid/BeaconCenter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

public class BeaconCenter : GridEntity
{
public BeaconCenter(int id) : base(id)
{
}

#if ENABLE_GRID_TOSTRING
public override string Label => "B";
#endif
Expand Down
2 changes: 1 addition & 1 deletion src/FactorioTools/OilField/Grid/BeaconSide.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

public class BeaconSide : GridEntity
{
public BeaconSide(BeaconCenter center)
public BeaconSide(int id, BeaconCenter center) : base(id)
{
Center = center;
}
Expand Down
4 changes: 4 additions & 0 deletions src/FactorioTools/OilField/Grid/ElectricPoleCenter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ public class ElectricPoleCenter : GridEntity
{
private readonly HashSet<ElectricPoleCenter> _neighbors = new();

public ElectricPoleCenter(int id) : base(id)
{
}

#if ENABLE_GRID_TOSTRING
public override string Label => "E";
#endif
Expand Down
2 changes: 1 addition & 1 deletion src/FactorioTools/OilField/Grid/ElectricPoleSide.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

public class ElectricPoleSide : GridEntity
{
public ElectricPoleSide(ElectricPoleCenter center)
public ElectricPoleSide(int id, ElectricPoleCenter center) : base(id)
{
Center = center;
}
Expand Down
7 changes: 7 additions & 0 deletions src/FactorioTools/OilField/Grid/GridEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@

public abstract class GridEntity
{
protected GridEntity(int id)
{
Id = id;
}

#if ENABLE_GRID_TOSTRING
public abstract string Label { get; }
#endif

public int Id { get; }

public virtual void Unlink()
{
}
Expand Down
4 changes: 4 additions & 0 deletions src/FactorioTools/OilField/Grid/Pipe.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

public class Pipe : GridEntity
{
public Pipe(int id) : base(id)
{
}

#if ENABLE_GRID_TOSTRING
public override string Label => "o";
#endif
Expand Down
4 changes: 4 additions & 0 deletions src/FactorioTools/OilField/Grid/PumpjackCenter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

public class PumpjackCenter : GridEntity
{
public PumpjackCenter(int id) : base(id)
{
}

#if ENABLE_GRID_TOSTRING
public override string Label => "J";
#endif
Expand Down
2 changes: 1 addition & 1 deletion src/FactorioTools/OilField/Grid/PumpjackSide.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

public class PumpjackSide : GridEntity
{
public PumpjackSide(PumpjackCenter center)
public PumpjackSide(int id, PumpjackCenter center) : base(id)
{
Center = center;
}
Expand Down
89 changes: 61 additions & 28 deletions src/FactorioTools/OilField/Grid/SquareGrid.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,36 @@ public abstract class SquareGrid
private const string EmptyLabel = ".";
#endif

private readonly Dictionary<GridEntity, Location> _entityToLocation;
private readonly Dictionary<int, Location> _entityIdToLocation;
private readonly ILocationSet _entityLocations;
private readonly GridEntity?[] _grid;
private int _nextId;

public SquareGrid(SquareGrid existing, bool clone)
{
Width = existing.Width;
Height = existing.Height;
Middle = new Location(Width / 2, Height / 2);
_entityToLocation = clone ? new Dictionary<GridEntity, Location>(existing._entityToLocation) : existing._entityToLocation;
Middle = existing.Middle;

if (clone)
{
_entityIdToLocation = new Dictionary<int, Location>(existing._entityIdToLocation);
#if USE_HASHSETS
_entityLocations = new LocationHashSet(existing._entityLocations.Count);
#else
_entityLocations = new LocationIntSet(existing.Width, existing._entityLocations.Count);
#endif
_entityLocations.UnionWith(existing._entityLocations);

_grid = (GridEntity?[])existing._grid.Clone();
_nextId = existing._nextId;
}
else
{
_entityIdToLocation = existing._entityIdToLocation;
_entityLocations = existing._entityLocations;
_grid = existing._grid;
_nextId = existing._nextId;
}
}

Expand All @@ -38,78 +51,94 @@ public SquareGrid(int width, int height)
Width = width;
Height = height;
Middle = new Location(Width / 2, Height / 2);
_entityToLocation = new Dictionary<GridEntity, Location>();
_entityIdToLocation = new Dictionary<int, Location>();
#if USE_HASHSETS
_entityLocations = new LocationHashSet();
#else
_entityLocations = new LocationIntSet(width);
#endif
_grid = new GridEntity?[width * height];
_nextId = 1;
}

public int Width { get; }
public int Height { get; }
public Location Middle { get; }

public GridEntity? this[Location id]
public GridEntity? this[Location location]
{
get
{
return _grid[GetIndex(id)];
return _grid[GetIndex(location)];
}
}

public IReadOnlyDictionary<GridEntity, Location> EntityToLocation => _entityToLocation;
public int GetId()
{
var id = _nextId;
_nextId++;
return id;
}

public IReadOnlyDictionary<int, Location> EntityIdToLocation => _entityIdToLocation;
public ILocationSet EntityLocations => _entityLocations;

public bool IsEmpty(Location id)
public bool IsEmpty(Location location)
{
return _grid[GetIndex(id)] is null;
return _grid[GetIndex(location)] is null;
}

public void AddEntity(Location id, GridEntity entity)
public void AddEntity(Location location, GridEntity entity)
{
var index = GetIndex(id);
var index = GetIndex(location);

if (_grid[index] is not null)
{
throw new FactorioToolsException($"There is already an entity at {id}.");
throw new FactorioToolsException($"There is already an entity at {location}.");
}

_grid[index] = entity;
_entityToLocation.Add(entity, id);
_entityLocations.Add(location);
_entityIdToLocation.Add(entity.Id, location);
}

public void RemoveEntity(Location id)
public void RemoveEntity(Location location)
{
var index = GetIndex(id);
var index = GetIndex(location);
var entity = _grid[index];
if (entity is not null)
{
_grid[index] = null;
_entityToLocation.Remove(entity);
_entityLocations.Remove(location);
_entityIdToLocation.Remove(entity.Id);
entity.Unlink();
}
}

public bool IsEntityType<T>(Location id) where T : GridEntity
public bool IsEntityType<T>(Location location) where T : GridEntity
{
return _grid[GetIndex(id)] is T;
return _grid[GetIndex(location)] is T;
}

public bool IsInBounds(Location id)
public bool IsInBounds(Location location)
{
return id.X >= 0 && id.X < Width && id.Y >= 0 && id.Y < Height;
return location.X >= 0 && location.X < Width && location.Y >= 0 && location.Y < Height;
}

public abstract void GetNeighbors(Span<Location> neighbors, Location id);
public abstract void GetNeighbors(Span<Location> neighbors, Location location);

public void GetAdjacent(Span<Location> adjacent, Location id)
public void GetAdjacent(Span<Location> adjacent, Location location)
{
var a = id.Translate(1, 0);
var a = location.Translate(1, 0);
adjacent[0] = IsInBounds(a) ? a : Location.Invalid;

var b = id.Translate(0, -1);
var b = location.Translate(0, -1);
adjacent[1] = IsInBounds(b) ? b : Location.Invalid;

var c = id.Translate(-1, 0);
var c = location.Translate(-1, 0);
adjacent[2] = IsInBounds(c) ? c : Location.Invalid;

var d = id.Translate(0, 1);
var d = location.Translate(0, 1);
adjacent[3] = IsInBounds(d) ? d : Location.Invalid;
}

Expand All @@ -129,7 +158,7 @@ public override string ToString()

public void ToString(StringBuilder builder, int spacing)
{
var maxLabelLength = _entityToLocation.Keys.Max(x => x.Label.Length) + spacing;
var maxLabelLength = _entityLocations.EnumerateItems().Max(x => this[x]!.Label.Length) + spacing;

for (var y = 0; y < Height; y++)
{
Expand Down Expand Up @@ -158,7 +187,11 @@ public void ToString(StringBuilder builder, int spacing)

private class Empty : GridEntity
{
public static Empty Instance { get; } = new Empty();
public static Empty Instance { get; } = new Empty(0);

public Empty(int id) : base(id)
{
}

#if ENABLE_GRID_TOSTRING
public override string Label => EmptyLabel;
Expand Down
4 changes: 4 additions & 0 deletions src/FactorioTools/OilField/Grid/TemporaryEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

public class TemporaryEntity : GridEntity
{
public TemporaryEntity(int id) : base(id)
{
}

#if ENABLE_GRID_TOSTRING
public override string Label => "?";
#endif
Expand Down
4 changes: 4 additions & 0 deletions src/FactorioTools/OilField/Grid/Terminal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

public class Terminal : Pipe
{
public Terminal(int id) : base(id)
{
}

#if ENABLE_GRID_TOSTRING
public override string Label => "+";
#endif
Expand Down
2 changes: 1 addition & 1 deletion src/FactorioTools/OilField/Grid/UndergroundPipe.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Knapcode.FactorioTools.OilField;

public class UndergroundPipe : Pipe
{
public UndergroundPipe(Direction direction)
public UndergroundPipe(int id, Direction direction) : base(id)
{
Direction = direction;
}
Expand Down
19 changes: 10 additions & 9 deletions src/FactorioTools/OilField/Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ public static class Helpers

public static PumpjackCenter AddPumpjack(SquareGrid grid, Location center)
{
var centerEntity = new PumpjackCenter();
var centerEntity = new PumpjackCenter(grid.GetId());
for (var x = -1; x <= 1; x++)
{
for (var y = -1; y <= 1; y++)
{
GridEntity entity = x != 0 || y != 0 ? new PumpjackSide(centerEntity) : centerEntity;
GridEntity entity = x != 0 || y != 0 ? new PumpjackSide(grid.GetId(), centerEntity) : centerEntity;
grid.AddEntity(new Location(center.X + x, center.Y + y), entity);
}
}
Expand Down Expand Up @@ -154,9 +154,9 @@ private static (ILocationDictionary<TInfo> CandidateToInfo, CountedBitArray Cove
var coveredEntities = new CountedBitArray(recipients.Count);

var providers = context.GetLocationDictionary<TProvider>();
foreach (var (entity, location) in context.Grid.EntityToLocation)
foreach (var location in context.Grid.EntityLocations.EnumerateItems())
{
var provider = entity as TProvider;
var provider = context.Grid[location] as TProvider;
if (provider is null)
{
continue;
Expand Down Expand Up @@ -401,15 +401,15 @@ private static void AddCoveredCenters(
}
else if (includePumpjacks && entity is PumpjackSide pumpjackSide)
{
coveredCenters.Add(grid.EntityToLocation[pumpjackSide.Center]);
coveredCenters.Add(grid.EntityIdToLocation[pumpjackSide.Center.Id]);
}
else if (includeBeacons && entity is BeaconCenter)
{
coveredCenters.Add(location);
}
else if (includeBeacons && entity is BeaconSide beaconSide)
{
coveredCenters.Add(grid.EntityToLocation[beaconSide.Center]);
coveredCenters.Add(grid.EntityIdToLocation[beaconSide.Center.Id]);
}
}
}
Expand Down Expand Up @@ -700,8 +700,9 @@ public static (List<ProviderRecipient> PoweredEntities, bool HasBeacons) GetPowe
var poweredEntities = new List<ProviderRecipient>();
var hasBeacons = false;

foreach ((var entity, var location) in context.Grid.EntityToLocation)
foreach (var location in context.Grid.EntityLocations.EnumerateItems())
{
var entity = context.Grid[location];
if (entity is PumpjackCenter)
{
poweredEntities.Add(new ProviderRecipient(location, PumpjackWidth, PumpjackHeight));
Expand Down Expand Up @@ -935,8 +936,8 @@ public static void AddBeaconsToGrid(SquareGrid grid, OilFieldOptions options, IE
AddProviderToGrid(
grid,
center,
new BeaconCenter(),
c => new BeaconSide(c),
new BeaconCenter(grid.GetId()),
c => new BeaconSide(grid.GetId(), c),
options.BeaconWidth,
options.BeaconHeight);
}
Expand Down
Loading

0 comments on commit ae7fb8d

Please sign in to comment.