In my continuous quest to incorporate versioned state all the way down, I’ve been looking with suspicion on the execute method. It’s what ultimately gets called to do a card or action. It’s also part of the language, in case, such as in ‘use twice’, one needs to do something without trying to discard it. However, it’s status as a primitive of sorts means it doesn’t have have the speculation safety check that prevents illegal actions; only the chance that so far it’s always been called inside another speculation has averted disaster.
Simply implementing this has far from desired results however, because it’s been hiding a deeper problem. I’ve discovered that my legality check only works for one level. Illegal actions aren’t performed, but they also aren’t propagated in case of multi-step processes. The speculation creates an exception barrier to later speculations.
My strategy so far has been to make the illegal state poisonous. Right now I’m not committing an illegal speculation. In the new scheme, I would always commit it where there would otherwise be a legality check. The thing that will (or should) keep illegal actions from being performed is a combination of the choice process and a fitness function that always rates illegal actions lower than any legal action. If an illegal state is ever committed to reality, the only thing to do is raise an language error informing the author that he needs a better fitness function for the AI or a ‘pass’ action that is always legal.
Actually, I’m a ninny. I’ve introduced new mechanics, but they are still being used in old ways. I’ve changed how things are supposed to work and kept the same mechanisms. Every ‘illegal state’ originates in an exception. What the speculation does it commute that into a boolean that can be examined later. Previously, I’d been checking for legal states before performing things, but this hid errors. Now I’m not checking that flag anymore, and I’ve written a bunch of code of propagate errors, most of it specs, refactoring, and debug support. I could just let the exception keep on going to much the same effect. Catching the errors only matters where the program will make some decision based upon it. This is only the choice points now.
Did I Waste My Day?
Maybe. Error propagation might come into play where all choices are illegal, when the best one got committed, it would set the illegal flag and propagate it up. This might be useful for choice-within-choice scenarios. On the other hand, I’m probably better off raising a “no legal choice” exception, which is really a better description of the problem.
A Little Less Than Random
I made one small tweak to the stopgap fitness function – add the number of changes to game state. I was trying to get rid of needless discards, but it turns out that a discard touches as much game state as most actions (cards still move from hand to discard, plus some book-keeping information.)