I found my first real bug in the game recently. When looking at my random forage results I realised that they were always getting the same results every time the action completes, unless I restarted forage.
It’s a pretty stupid mistake really – because the random forage results are generated in advance, of course they’ll be the same until they’re regenerated. The problem is, I can’t just ask for more random numbers in the middle of the update. I need to flag up that I need to get new random numbers, and then run a command after my model update to get them.
What I’ve ended up with is a random cache structure that stores values that can be used later. The cache stores
- The random generator
- A list of cached values
- The expected capacity
- A count of how many were used since the last update
- A flag to say if it needs updating
When my forage requires some random number, it asks the cache for a bunch of random values and uses them. The cache then marks itself as needing new numbers.
getRandomFromCache : Int -> RandomCache x -> (List x, RandomCache x) getRandomFromCache count cache = let (list, rest) = splitList count cache.values in (list, { cache | values = rest, used = cache.used + count, update = True })
After the update cycle we check the caches. If we need updates, we fetch a list of new random values and add to our list of random values. It also checks that the capacity was sufficient and if we used more than 1/3 of our capacity, increases it. This ensures that we should have enough random numbers even if something unusual happens.
addToRandomCache : List x -> RandomCache x -> RandomCache x addToRandomCache list cache = let newCapacity = max (cache.used * 3) cache.capacity newValues = List.append cache.values list newUpdate = newCapacity < List.length newValues in { cache | values = newValues , used = 0 , update = newUpdate , capacity = newCapacity }
Strictly speaking the update flag isn’t necessary, it really is just a cache of capacity < value list length. That might be a premature optimisation. Note It is not the same as update != 0 as if we increase our buffer size we’d still have an used count of 0.
One benefit to this is that it allows me to tidy up my forage action – now it is a forage plus the number of random items, rather than storing exactly what it will get. I’m quite happy about that.
All of this works and I now have properly random forages. However, I feel like I’ve got something wrong here. This feels like a massively overengineered solution to a simple problem. Perhaps something will present itself in the future.