You can reduce the memory footprint by using [`BitVector32`](https://docs.microsoft.com/en-us/dotnet/api/system.collections.specialized.bitvector32) instead of `bool`. A `bool` in .NET occupies a full word in memory. A `BitVector32` allows you to store the equivalent of 32 bools the same memory space.

By replacing all  of the `bool` fields in `State` with a single `BitVector32`, I was able to reduce `State`'s memory footprint from 68 bytes to 12 (as measured by [`Marshal.SizeOf<State>()`](https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.sizeof)). Since `State` is the key in the dictionary, that adds up to a decent reduction in memory usage overall.

After applying my changes to your `master` branch and running for 1,000,000 steps, the memory usage of the state dictionary dropped from ~215 MB to ~167 MB (as measured by the Visual Studio profiler). After 5,000,000 steps, it dropped from ~864 MB to ~671 MB.

You could push this technique even further by packing numeric values into bit vectors. There are some examples of doing so in the docs.

Here's a sample of the code that I used. All of the changes happened within `State`. I opted for the most convenient refactoring path... there might be a more efficient/performant way to code all this.

```csharp
BitVector32 bits;

private const int ReinforcedIndexFingerMask = 1 << 0;
private const int CarpalTunnelPreventionCreamMask = 1 << 1;

public bool ReinforcedIndexFinger
{
    get => bits[ReinforcedIndexFingerMask];
    set => bits[ReinforcedIndexFingerMask] = value;
}

public bool CarpalTunnelPreventionCream
{
    get => bits[CarpalTunnelPreventionCreamMask];
    set => bits[CarpalTunnelPreventionCreamMask] = value;
}
```