bugfix in Manage_Solution test_wrap. was testing original step for the wrap instead of testing the step returned from using next.
roughly halved 10% of total solution time to 5% by calculating state string outside instead of inside the duplicate optimizer.
removed inconsistent ValueError condition with Investigate_State so for now, there is a consistent None return value if somehow the state can't be determined, etc. when a solution is requested. Might be better in the future to use Exceptions (consistently) that include meaningful messages. But for the user, either it will be obvious what is wrong or they won't be able to do anything about it anyway, so leave it for now.
removed old code and added a main covering function.
adjusted TileLibrarian to be more normal. moved module level methods into the class. Simply set things up at __init__ instead of making class attributes. Instead, responsibility will be on users to share a single Librarian if they wish to. could set it up to always produce the same singleton object if wanting to hide the shared nature of it.
Completely removed "_tile_singletons" and replaced all usages with the newly redone TileLibrarian. Includes specifications for everything added. Seems cleaner, more straightforward now.
Also updated TileLibrarian to raise KeyErrors on unknown tile/character/name input since those are relatively straight forward and user shouldn't be providing random inputs.
renamed TargetGroup to PositionGroup for clarity
forgot to update UI with change from tile_singletons to TileLibrarian
completely removed the module attribute 'singleton' of _tile_librarian and replaced it with an explicit Singleton Instance() of the TileLibrarian itself.
Renamed TargetGroup --> PositionGroup to be more explicit.
Replaced dict lookups of action/state with a namedtuple version of state.
Also implemented spec in Manage_Solution that wasn't actually finished and didn't have any test in it.
forgot to replace UI instance of TileLibrarian with new style. Done now.
moved board_string testing all within a Board classmethod rather than doing it elsewhere (like it was done in state investigator). Also seemed to have been a specification bug that the test was not failing when it should have been. Didn't affect the code though, so just adjusted the specification.
Updated __str__ and __repr__ to be readable and explicit respectively. Basically just added a class name before __str__().
In specification and code, reversed yielded tuple order for Board tile_positions
Found board._match was building a whole list instead of just generating results. Updated to generator for consistency and may get minor performance bonus.
specified and implemented new functions required for Board._step optimization
Updated board _step, _match_, and _match_rows to accept and use the previous board argument for optimization.
finished specification and implementation of new _match reduction optimization. With other code the same, reduced Giant Rat capture from ~60s to ~40s or around 30% reduction in simulation time.
relocated _extract_steps to Simulator where it belonged anyway. This is also necessary for isolating the Simulator before running parts of it in a thread.