There's a useful often overlooked solution to the problem of implementing a complex dynamic process: table lookup. The trick is to build a table ahead of time of all possible answers, and then just look them up at run-time.
This technique works whenever there is a finite number of possible answers, and works well when the number of table entries relatively small or searching the table is cheap.
At the very least, significant time can be saved. In this situation, however, the programming complexity is also greatly reduced, because it's almost trivial to generate all possible answers. The hard part is working backwards.
Therefore, one simple solution to implement does the following:
Note that this solution easily supports asking whether some conjunction of facts is consistent with the current set of results. It's feasible in any GBS-Lite kind of situation, because there are never more than a handful of internal states to discover, or more than a handful of tests to run. In addition, if the states and test results are put in the table in a canonical order, as the implementation does, then the match function is very simple and efficient.
This implementation is much cleaner than
anyone would be expected to write in an hour, with everything divided
up into simple subfunctions. However, if you look at
you'll see that all three are fairly simple.