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?
Another design issue, is which class should be resposible for driving the search()?
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?
The grand design
Moderator: Ras
-
- Posts: 12791
- Joined: Wed Mar 08, 2006 8:57 pm
- Location: Redmond, WA USA
Re: The grand design
It seems to me that search is a property of the game state. It isn't really owned by board or nodes or any of the others that I can think of.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?
Another design issue, is which class should be resposible for driving the search()?
So I would probably make it Game.Search()
I always ask these questions about class X: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?
If x IS A y, then it is a specialization of y (inheritance).
If x HAS a y, then y is a member object.
If x PERFORMS y, then y is a member function of x.
It helps me to think along these lines because (for me) it creates the most natural representation.
-
- Posts: 127
- Joined: Thu Sep 17, 2009 11:19 am
Re: The grand design
I think yes, Game would expose a public method called Search(), it would be needed by the Protocol when interfacing the Game. Game would thus take the role of a controller for managing the search and state stuff.Dann Corbit wrote: It seems to me that search is a property of the game state. It isn't really owned by board or nodes or any of the others that I can think of.
So I would probably make it Game.Search()
But how would Game implement Search(). Game would have references to at least a Board and a Tree. So the request would delegate to Tree which would delegate to the current node which would then do the search().
Hmm or what?
Yes indeed, no argument thereDann Corbit wrote: I always ask these questions about class X:
If x IS A y, then it is a specialization of y (inheritance).
If x HAS a y, then y is a member object.
If x PERFORMS y, then y is a member function of x.
It helps me to think along these lines because (for me) it creates the most natural representation.

I see the confusion now, because Game performs Search you want Game to implement the Search()? There is problem with that though, Game is not the information expert, Board and Node is. So to keep the amount of couplings low, Board and Node are the two best candidates (IMHO).
-
- Posts: 12791
- Joined: Wed Mar 08, 2006 8:57 pm
- Location: Redmond, WA USA
Re: The grand design
Board.search() can make sense to me, but node.search() sounds very strange to me. It feels like an atom searching his universe.SuneF wrote:I think yes, Game would expose a public method called Search(), it would be needed by the Protocol when interfacing the Game. Game would thus take the role of a controller for managing the search and state stuff.Dann Corbit wrote: It seems to me that search is a property of the game state. It isn't really owned by board or nodes or any of the others that I can think of.
So I would probably make it Game.Search()
But how would Game implement Search(). Game would have references to at least a Board and a Tree. So the request would delegate to Tree which would delegate to the current node which would then do the search().
Hmm or what?
Yes indeed, no argument thereDann Corbit wrote: I always ask these questions about class X:
If x IS A y, then it is a specialization of y (inheritance).
If x HAS a y, then y is a member object.
If x PERFORMS y, then y is a member function of x.
It helps me to think along these lines because (for me) it creates the most natural representation.
I see the confusion now, because Game performs Search you want Game to implement the Search()? There is problem with that though, Game is not the information expert, Board and Node is. So to keep the amount of couplings low, Board and Node are the two best candidates (IMHO).
Perhaps tree.search()?
-
- Posts: 916
- Joined: Sun Nov 19, 2006 9:16 pm
- Location: Russia
- Full name: Aleks Peshkov
Re: The grand design
My Node object knows internally how to generate a move list, but do not know what to do with it. I store Evaluator object inside Node object. Node evaluates itself using static evaluator or various recursive search evaluators (pv_search, q_search, etc.).
Node can copy own evaluator with different parameters or can create a different evaluator when it needed to evaluate recursively its child nodes.
Node can copy own evaluator with different parameters or can create a different evaluator when it needed to evaluate recursively its child nodes.
Code: Select all
class Node {
//color and tree independent position information
PieceLayout my; //side to move pieces
PieceLayout op;
class Search {
typedef bool (*Evaluator) (Node&);
Evaluator evaluator;
Ply depth;
Eval alpha, beta;
} evaluator;
};
-
- Posts: 170
- Joined: Mon Sep 13, 2010 9:57 am
- Location: Frankfurt am Main
Re: The grand design
If you want to break up your big classes, you could split them according to the Model-View-Controller Architecture.
E.g for the Board class:
Board view => graphics and mouse handling
Board model => keep board state and updates (setMove, unsetMove, setPosition, throw Exception for illegal moves)
Board controller => interaction with other classes, send events and the like.
Actually I would prefer to have a more global controller, e.g. a GameState object that acts as a dispatcher. E.g. you want a move not only played at the board, but also update the score sheet etc... so the GameState would notify all concerned objects that a move has been played.
I would make the search neither part of the Board nor the Tree class but I would rather make an Engine class. I'm thinking of a design like this:
Think of the controller notifying a Player that it is his turn to move. The Player will raise an event if he wants to play a move. Now, if you notified a Human, the controller just waits for move input after starting the humans clock. For an ICS connection, you wait for the connection to raise the move event once it has received the remote players move. In case of an Engine, you call engine.search() and wait. The protocol handler for UCI and Winboard should somehow be part of the Engine.
Conceptually I have something like the following in mind.
E.g for the Board class:
Board view => graphics and mouse handling
Board model => keep board state and updates (setMove, unsetMove, setPosition, throw Exception for illegal moves)
Board controller => interaction with other classes, send events and the like.
Actually I would prefer to have a more global controller, e.g. a GameState object that acts as a dispatcher. E.g. you want a move not only played at the board, but also update the score sheet etc... so the GameState would notify all concerned objects that a move has been played.
I would make the search neither part of the Board nor the Tree class but I would rather make an Engine class. I'm thinking of a design like this:
Code: Select all
Player (abstract)
/ | \
/ | \
Human ICS Engine
/ \
/ \
UCI XBoard
Conceptually I have something like the following in mind.
Code: Select all
public abstract class Engine extends Player
{
public abstract void startEngine();
public abstract void startSearch();
public abstract void abortSearch();
public abstract void firePrincipalVariationEvent(Move[] pv);
public abstract void fireBestMoveEvent(Move best, Move ponder);
....
}
public class UciEngine extends Engine
{
protected String exePath;
protected Stream pipe; // no idea how to do the piping in Java yet (-:
public void startEngine()
{
// start engine process, create pipes...
}
public void startSearch()
{
// pack the following into a separate thread an return,
// so that caller won't wait for this method to return.
pipe.printf("go wtime 200000 ....");
// read input from pipe
// and parse it
this.fireBestMoveEvent(best, ponder);
}
}
-
- Posts: 98
- Joined: Sat Jul 31, 2010 8:48 pm
- Full name: Ubaldo Andrea Farina
Re: The grand design
back to work on Frenzee, Sune? 

-
- Posts: 127
- Joined: Thu Sep 17, 2009 11:19 am
Re: The grand design
Board.Search() is possible, but I think the Board already has its hands full with Evaluation and making smart decisions about the current state of the Board.Dann Corbit wrote: Board.search() can make sense to me, but node.search() sounds very strange to me. It feels like an atom searching his universe.
Perhaps tree.search()?
Tree.Search() at first looks like the most natural choice to me. Downside is one would have to pass around another node-parameter and there would be no implict this pointer, so one would have to use the C-style notation (node->x,.. node->y).
An atom searching the Universe is perhaps strange, but what if the atoms are all linked. The nodes could be the media through which the information flows, ie. like sound waves propagate through air molecules..
Binary search trees and such work much the same way.
Guess it would result in something like this:
score = - next->Search(board, alpha, beta...);
-
- Posts: 127
- Joined: Thu Sep 17, 2009 11:19 am
Re: The grand design
Yes MVC is not far off, of course there would be no actual view since the engine is using standard I/O to communicates, it's more of a service layer I suppose.OliverUwira wrote:If you want to break up your big classes, you could split them according to the Model-View-Controller Architecture.
E.g for the Board class:
Board view => graphics and mouse handling
Board model => keep board state and updates (setMove, unsetMove, setPosition, throw Exception for illegal moves)
Board controller => interaction with other classes, send events and the like.
Actually I would prefer to have a more global controller, e.g. a GameState object that acts as a dispatcher. E.g. you want a move not only played at the board, but also update the score sheet etc... so the GameState would notify all concerned objects that a move has been played.
I would make the search neither part of the Board nor the Tree class but I would rather make an Engine class. I'm thinking of a design like this:
Code: Select all
Player (abstract) / | \ / | \ Human ICS Engine / \ / \ UCI XBoard
Think of the controller notifying a Player that it is his turn to move. The Player will raise an event if he wants to play a move. Now, if you notified a Human, the controller just waits for move input after starting the humans clock. For an ICS connection, you wait for the connection to raise the move event once it has received the remote players move. In case of an Engine, you call engine.search() and wait. The protocol handler for UCI and Winboard should somehow be part of the Engine.
Conceptually I have something like the following in mind.
Code: Select all
public abstract class Engine extends Player { public abstract void startEngine(); public abstract void startSearch(); public abstract void abortSearch(); public abstract void firePrincipalVariationEvent(Move[] pv); public abstract void fireBestMoveEvent(Move best, Move ponder); .... } public class UciEngine extends Engine { protected String exePath; protected Stream pipe; // no idea how to do the piping in Java yet (-: public void startEngine() { // start engine process, create pipes... } public void startSearch() { // pack the following into a separate thread an return, // so that caller won't wait for this method to return. pipe.printf("go wtime 200000 ...."); // read input from pipe // and parse it this.fireBestMoveEvent(best, ponder); } }
Yes for a View that sounds like a good design.
-
- Posts: 127
- Joined: Thu Sep 17, 2009 11:19 am
Re: The grand design
A little bit now and then...uaf wrote:back to work on Frenzee, Sune?
