/**
* @fileoverview Abstrakte Basisklasse für Heuristiken.
* Definiert die gemeinsame Schnittstelle für alle Heuristik-Evaluatoren.
* @author Alexander Wolf
*/
/**
* Abstrakte Basisklasse für Heuristik-Evaluatoren.
* @abstract
*/
class BaseHeuristic {
/**
* @param {Object} config
* @param {string} config.game
* @param {string} config.variant
* @param {string} [config.name]
* @param {Object} [config.weights]
*/
constructor(config) {
if (new.target === BaseHeuristic) {
throw new Error('BaseHeuristic ist abstrakt und darf nicht direkt instanziiert werden.');
}
this.game = config.game;
this.variant = config.variant;
this.name = config.name || `${config.game}-${config.variant}`;
this.weights = { ...this.getDefaultWeights(), ...(config.weights || {}) };
this.id = `${this.game}:${this.variant}`;
if (typeof DebugConfig !== 'undefined' && typeof DEBUG_DOMAINS !== 'undefined') {
DebugConfig.log(DEBUG_DOMAINS.AI_HEURISTICS, 'debug', 'Heuristic created', {
id: this.id,
name: this.name
});
}
}
/**
* @param {GameState} gameState
* @param {number} player
* @returns {number}
*/
evaluate(gameState, player) {
throw new Error(`evaluate() muss in ${this.constructor.name} implementiert werden.`);
}
/**
* @returns {Object}
*/
getDefaultWeights() {
return {
win: 1000,
loss: -1000,
draw: 0
};
}
/**
* @returns {Object}
*/
toConfig() {
return {
game: this.game,
variant: this.variant,
name: this.name,
weights: { ...this.weights }
};
}
/**
* @param {Object} newWeights
*/
updateWeights(newWeights) {
this.weights = { ...this.weights, ...newWeights };
if (typeof DebugConfig !== 'undefined' && typeof DEBUG_DOMAINS !== 'undefined') {
DebugConfig.log(DEBUG_DOMAINS.AI_HEURISTICS, 'debug', 'Heuristic weights updated', {
id: this.id,
weights: this.weights
});
}
}
/**
* @param {GameState} gameState
* @param {number} player
* @returns {number|null}
*/
checkTerminal(gameState, player) {
if (gameState.winner === player) return this.weights.win;
if (gameState.winner !== NONE && gameState.winner !== DRAW) return this.weights.loss;
if (gameState.winner === DRAW) return this.weights.draw;
return null;
}
}