I’ve got my free action problem solved, at least for the time being. The crux of the problem is that if you have a choice-with-a-choice, the inner choice gets completely resolved without considering what may come afterwards. I needed some way for the inner choice to ‘fork’ the options and consider all of them.
Repelled on Multistates
One crazy idea was to put a layer on top of Yggdrasil states that would perform all operations on multiple underlying states in parallel. The problem I couldn’t work out was keeping the abstraction from leaking like a thunderstorm. Currently, in order for Yggdrasil to work, all versioned data has to use a strict read-modify-write access pattern, so that only the current state can be modified. For the new scheme to work, it would have to be done as transformations (all hail the almighty lambda) that could be executed against each sub-state. Where I really ran into a wall was that sometimes, you want to read back a value (does x equal 5?) and the only way to do that would be to suck the entire thing into a transform. Would you like a mop?
Recoiling from Continuations
I was all set to try implementing continuations in spite of limited portability. Continuations were out of Ruby 1.9 for a while, and still aren’t available in some of the alternate implementations. However, I figured out passing the remainder of the computation as a block wasn’t really all that different from what I was doing with cards, which made it more palatable.
choose free_actions do |action| execute action ... end
Which is just annoying enough to need a wrapper:
with_free_actions do ... end
Waiting, for Defeat
The combined effect of Yggdrasil and considering free actions makes the execution of the program take a perceptible amount of time. I suspect much of this comes from searching through Yggdrasil’s history, which I may be able to address with some caching and history compaction.
Strategic Retreat from DevBlog
For a while, I gathered up all these articles and put them in a file within the source code repository. I figured it would save me have to switch editor projects, and server as a kind of documentation. However, I was considering opening up a branch for the continuation experiment, and I realized that whole devblog idea kind of fell down in the face of branches. It would have the advantage that only successful experiments would show up in the final version, but that would also lose some history. I’ve also had a little friction trying to keep commits cleanly code or writing.
p.s. I posted Disk Clock 1.8; it’s just a little internal refactoring, but I recentered the indicator line, which was off a few pixels.