I'm writing a C++ project and have a generic evaluate method in a class template.
My only question is how would I define the generateAllMoves
and isPosFinal
so that it is defined inside the classes that use this class template?
I've read that using pure virtual functions is a no no. I also do not want to make it static.
I foresee myself rewriting this as an abstract class, but then I would end up with a problem that requires generic types.
#ifndef ENGINE_H
#define ENGINE_H
#include <map>
using namespace std;
template< class M, class P >
class Engine {
public:
Engine() { };
struct Move {
P move;
P pos;
int score;
};
Move evaluate( P position ) {
Move best;
if ( posIsFinal( position ) ) {
Move newMove;
newMove.pos = position;
newMove.score = 1;
return newMove;
}
else {
map< M , P > allMoves = generateAllMoves( position );
typename map< M , P > :: iterator it;
for (it = allMoves.begin(); it != allMoves.end(); it++ ) {
Move next = evaluate(it->second);
if (next.score > best.score ) {
best.pos = next.pos;
best.move = next.move;
best.score = next.score;
}
}
return best;
}
}
};
#endif
Edit: To be more clear for everyone!
I have two different games right that defines its own generateAllMoves and isPosFinal methods. They use different algorithms and return different types.... For example, I will be soon implementing a chess game, but right now I'm implementing nim. Both interpret move and is this position final, differently.
2nd Edit:
Final code compiles!
#ifndef ENGINE_H
#define ENGINE_H
#include <map>
using namespace std;
template< typename Derived, class M, class P >
class Engine {
public:
struct Move {
P move;
P pos;
int score;
};
Move evaluate( P position ) {
Move best;
if ( static_cast<Derived*>(this)->posIsFinal( position ) ) {
Move newMove;
newMove.pos = position;
newMove.score = 1;
return newMove;
}
else {
map< M , P > allMoves = static_cast<Derived*>(this)->generateAllMoves( position );
typename map< M , P > :: iterator it;
for (it = allMoves.begin(); it != allMoves.end(); it++ ) {
Move next = evaluate(it->second);
if (next.score > best.score ) {
best.pos = next.pos;
best.move = next.move;
best.score = next.score;
}
}
return best;
}
}
bool posIsFinal( P position ) {
cerr << "Generic posIsFinal\n";
exit(1);
}
map< M , P > generateAllMoves( P position ) {
cerr << "Generic generateAllMoves\n";
exit(1);
}
private:
};
#endif