/**
* @fileoverview Knights-Tour-Heuristik (Warnsdorf).
* @author Alexander Wolf
*/
/**
* Heuristik für Knights-Tour mit Warnsdorf-Prinzip.
*/
class KnightsTourHeuristic extends BaseHeuristic {
/**
* @param {Object} config
*/
constructor(config) {
const mergedConfig = { game: 'knights-tour', ...(config || {}) };
const validated = (typeof validateHeuristicConfig === 'function')
? validateHeuristicConfig(mergedConfig)
: mergedConfig;
super(validated);
}
/**
* @returns {Object}
*/
getDefaultWeights() {
return {
win: 1000,
loss: -1000,
draw: 0,
mobilityWeight: 1
};
}
/**
* Warnsdorf: je weniger Folgezüge, desto besser.
* Erwartet ein GameState mit currentPosition und Methode getValidKnightMovesFrom(pos).
* @param {Object} gameState
* @param {number} player
* @returns {number}
*/
evaluate(gameState, player) {
if (!gameState || !gameState.currentPosition || typeof gameState.getValidKnightMovesFrom !== 'function') {
DebugConfig.log(DEBUG_DOMAINS.AI_HEURISTICS, 'warn', 'KnightsTourHeuristic fallback: missing required API', {
player
});
return 0;
}
const nextMoves = gameState.getValidKnightMovesFrom(gameState.currentPosition) || [];
if (nextMoves.length === 0) return this.weights.loss;
let minDegree = Infinity;
for (const move of nextMoves) {
const futureMoves = gameState.getValidKnightMovesFrom(move) || [];
if (futureMoves.length < minDegree) {
minDegree = futureMoves.length;
}
}
return -minDegree * this.weights.mobilityWeight;
}
}
HeuristicRegistry.registerConstructor('knights-tour', KnightsTourHeuristic);
HeuristicRegistry.register(new KnightsTourHeuristic({ variant: 'warnsdorf', name: 'Knights Tour Warnsdorf' }));