Skip to content

Commit

Permalink
Refactor to place all keys + additional for a door at a time
Browse files Browse the repository at this point in the history
  • Loading branch information
IntelOrca committed Sep 22, 2024
1 parent ac6c68b commit 87507fa
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 5 deletions.
19 changes: 14 additions & 5 deletions IntelOrca.Biohazard.BioRand/Routing/Graph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,21 @@ public ImmutableArray<Node> GetEdges(Node node)
return ImmutableArray<Node>.Empty;
}

private Node[] GetKeys(Node node)
private string[] GetKeys(Node node)
{
return node.Requires
.Select(x => x.Node)
.Where(x => x.Kind == NodeKind.Key)
var edges = node.Requires
.Where(x => x.Node.Kind == NodeKind.Key)
.ToArray();
return edges
.Select(e => string.Join(" ", GetIcon(e), $"K<sub>{e.Node.Id}</sub>"))
.ToArray();
}

private static string GetIcon(Edge edge)
{
if ((edge.Flags & EdgeFlags.Consume) != 0)
return "fa:fa-triangle-exclamation";
return "";
}

private ImmutableArray<ImmutableArray<Node>> GetSubgraphs()
Expand Down Expand Up @@ -125,7 +134,7 @@ public string ToMermaid()
void EmitEdge(string sourceName, Node b)
{
var targetName = GetNodeName(b);
var label = string.Join(" + ", GetKeys(b).Select(k => $"K<sub>{k.Id}</sub>"));
var label = string.Join(" + ", GetKeys(b));
var edgeType = b.Kind == NodeKind.OneWay
? MermaidEdgeType.Dotted
: MermaidEdgeType.Solid;
Expand Down
2 changes: 2 additions & 0 deletions IntelOrca.Biohazard.BioRand/Routing/OneToManyDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ internal ImmutableOneToManyDictionary(
_valueToKeys = valueToKeys;
}

public int Count => _keyToValue.Count;

public TMany this[TOne key] => _keyToValue[key];

public ImmutableHashSet<TOne> GetKeysContainingValue(TMany value)
Expand Down
122 changes: 122 additions & 0 deletions IntelOrca.Biohazard.BioRand/Routing/RouteFinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,39 @@ private static State Fulfill(State state, Random rng)
if (!ValidateState(state))
return state;

// Choose a door to open
var bestState = state;
foreach (var n in Shuffle(rng, state.Next))
{
var required = GetRequiredKeys2(state, n);

// TODO do something better here
for (int retries = 0; retries < 10; retries++)
{
var slots = FindAvailableSlots(rng, state, required);
if (slots == null)
continue;

var newState = state;
for (var i = 0; i < required.Count; i++)
{
newState = newState.PlaceKey(slots[i], required[i]);
}

var finalState = Fulfill(newState, rng);
if (finalState.Next.Count == 0 && finalState.OneWay.Count == 0)
{
return finalState;
}
else if (finalState.ItemToKey.Count > bestState.ItemToKey.Count)
{
bestState = finalState;
}
}
}
return DoNextSubGraph(bestState, rng);

/*
var checklist = GetChecklist(state);
var requiredKeys = Shuffle(rng, checklist
.SelectMany(x => x.Need)
Expand Down Expand Up @@ -118,6 +151,7 @@ private static State Fulfill(State state, Random rng)
}
return firstState!;
}
*/
}

private static State Expand(State state)
Expand All @@ -144,6 +178,94 @@ private static State Expand(State state)
return state;
}

private static List<Node> GetRequiredKeys2(State state, Node node)
{
var required = GetMissingKeys(state.Keys, node);
var newKeys = state.Keys.AddRange(required.Select(x => x.Node));
foreach (var n in state.Next)
{
if (n == node)
continue;

var missingKeys = GetMissingKeys(newKeys, n);
if (missingKeys.Count == 0)
{
missingKeys = GetMissingKeys(state.Keys, n);
foreach (var k in missingKeys)
{
if ((k.Flags & EdgeFlags.Consume) != 0)
{
required.Add(k);
}
}
}
}

return required.Select(x => x.Node).ToList();
}

private static List<Edge> GetMissingKeys(ImmutableMultiSet<Node> keys, Node node)
{
var requiredKeys = node.Requires
.Where(x => x.Node.Kind == NodeKind.Key)
.GroupBy(x => x.Node)
.ToArray();

var required = new List<Edge>();
foreach (var g in requiredKeys)
{
var have = keys.GetCount(g.Key);
var need = g.Count() - have;
var flags = CombineFlags(g);
for (var i = 0; i < need; i++)
required.Add(new Edge(g.Key, flags));
}

return required;
}

private static EdgeFlags CombineFlags(IEnumerable<Edge> edges)
{
EdgeFlags result = 0;
foreach (var edge in edges)
result |= edge.Flags;
return result;
}

private static Node[]? FindAvailableSlots(Random rng, State state, List<Node> keys)
{
if (state.SpareItems.Count < keys.Count)
return null;

var available = Shuffle(rng, state.SpareItems).ToList();
var result = new Node[keys.Count];
for (var i = 0; i < keys.Count; i++)
{
for (var j = 0; j < available.Count; j++)
{
if (available[j].Group == keys[i].Group)
{
result[i] = available[j];
available.RemoveAt(j);
break;
}
}
if (result[i] == null)
return null;
}
return result;
}

private static State DoNextSubGraph(State state, Random rng)
{
var subGraphs = state.OneWay.ToArray();
foreach (var n in subGraphs)
{
state = DoSubgraph(state, new[] { n }, first: false, rng);
}
return state;
}

private static (State, Node[]) TakeNextNodes(State state)
{
var result = new List<Node>();
Expand Down

0 comments on commit 87507fa

Please sign in to comment.