I think having a ChoiceAdventure class with one instantiation per choice and data and methods to replace giant switch statements and the data structure used to control which choice adventures and options are visible in the GUI seems good.
The visitChoice, preChoice, postChoice0,1,2 methods seem necessary; there are very specific places in GenericRequest where each of those is called, and every time we've done major munging (such as when I made multi-fights and multi-choices (and mixes of the two) accumulate all item drops so that only at the very end do you see everything complete with use links), it's been a big job to make sure that everything still works, both in automation and in the Relay Browser.
I have never liked the static globals in FIghtRequest, GenericRequest, and ChoiceManager. It is true that your character can't ever actually be in more than one fight or choice at a time, but that's still tricky and fragile.
Regarding whether you should split the choices into groups, I have no objections to large files. I propose something like this:
ChoiceAdventureData.java
- the class with fields and methods for one choice
ChoiceManager.java
- data structures (hash tables? arrays?) of ChoiceAdventure objects.
- top-level methods called from GenericRequest and other parts of KoLMafia that take a choice#, look up the object, and call methods, retrieve data, whatever, as needed.
- a registerChoice method which takes a ChoiceManager object and is called at the end of the creator method to update all the data structures as needed. Or perhaps to simply add all ChoiceAdventure objects into a TreeSet, and then all the other data structures can be created from that Set after all the choice objects have been initialized. Whatever.
ChoiceAdventures.java
- a single large file which creates every ChoiceAdventureData object as static initialization. Perhaps even just a series of calls like this in a static block:
Code:
new ChoiceAdventureData (
param1,
param2,
...,
paramN ) {
@Override
public final void visitChoice(final GenericRequest request ) {
...
}
@Override
public final void PREChoice(final GenericRequest request ) {
...
}
...
};
Perhaps there is choices.txt with a lot of constant data that can be read once and used at object creation time, rather than calling a BOA Constructor like this (or like CoinMasterData)
Perhaps the TreeSet of choices is in this file.
Perhaps ChoiceManager, which imports this file, static initializes its own data structures from that Set.
Whatever; those are all design choices.
This is wild brainstorming; this is not a proposed design. But it does accomplish what I think are desirable goals:
- We retain the carefully defined-over-years external interface to ChoiceManager
- Everything that differs between choices is captured in a ChoiceAdventure object
- There still is a large file (meh), but adding a new choice is nothing more than adding a new static object creation in the appropriate (numeric) place with exactly the method overrides needed to make it work.
Why do we care about large files that define data (like this) or methods (like RuntimeLibrary)?