SuneF wrote:I wonder how many have considered the design of their engine from an object orientated perspective.
In particular:
1: What classes do you use and what is their resposibility?
2: How are they coupled?
3: What patterns are you using?
4: When do you trade design for speed?
I'm kinda struggling a bit myself to find the right balance and design.
I've designed a ChessGame class to encapsulate the state of the game.
There is an abstract Protocol class, which the ChessGame knows about.
The Protocol is specialized into WinboardProtocol and UciProtocol classes - of which the ChessGame doesn't know about.
The idea here is to isolate all protocol stuff from the main system, making it easier to implement new protocols without changing so much as a line in the very messy game/search stuff.
Okay that is basic I guess.
Then I currently have Board, Node and Tree classes.
The board is for holding the current state.
Node is like an extended Board class, it contains Undo information, move lists and so on.
The Tree is a Node container for holding the entire search info.
The main problem here is that these classes get fat, real fat real quick.
Can they be broken up in a natural way?
Hi Sune,
I have a similar design. Since my nodes are somehow distributed, I use embedded node subclasses, that cover incremental updates, stuff on the stack, and data generated from scratch once per node with limited lifetime.
A former mistake of mine seemed to derivate tree from node, to expand it with the node container. In CTree, I often had bugs like (this->)foo versus node.foo issues, the compiler could not catch.
SuneF wrote:Another design issue, is which class should be resposible for driving the search()?
Clearly, the protocol stuff belongs to seperate classes. Since Xboard and UCI require almost disjoint game state handling, a thin interface between a Game Controller model and the "dumb" tree-searcher(s) would be appropriate.
SuneF wrote:
The search must call the Evaluation(), it must do pruning and extensions, so this would make Board a candidate.
But how can the Board know about "the next ply", the Tree knows about the plies, so this would make Tree a candidate.
Finally, at every node we have lots of parameters, alpha, beta, depth etc.. These are natually stored in a Node or locally declared.
This would make Node a candidate.
My favorite is the Node class, primarily for notation reasons, though the nodes would have to be linked or know about the Tree to go to the next node.
One design decision I've made, is that I accept "global" tables, ie. data floating in a namespace.
My reasoning is, that the notation would get awkward if everything had to get prefixed by some named object or as static members of a class. Not to mention it would probably be slower.
There are many more issues of course, not to mention what is a good parallel design?
Yes, so far I use multiple instances of tree searchers, where a specialized "search" method creates a thread ...
Cheers,
Gerd