/* --- FILE: js/games/tictactoe/ultimate-controller.js --- */
/**
* @fileoverview Controller für Ultimate Tic-Tac-Toe (9x9 mit Subboards)
*
* Extends BaseGameController mit Ultimate TTT Board-Support.
* Verwaltet Sperr-Logik für deaktivierte Subboards und 2-Level Navigation.
*
* @class UltimateGameController
* @extends BaseGameController
* @author Alexander Wolf
*/
class UltimateGameController extends BaseGameController {
constructor() {
super('ultimate', 'gameCanvas');
}
createGame() {
return new UltimateBoard();
}
reset() {
// ✅ Canvas-Größe für Ultimate anpassen (HiDPI-fähig)
setupHiDPICanvas(this.canvas, 600, 600);
super.reset();
}
drawGame() {
TTTRenderer.drawUltimate(this.canvas, this.game);
}
coordsToMove(mx, my) {
const bigS = getCanvasLogicalWidth(this.canvas) / 3;
const smallS = bigS / 3;
const bX = Math.floor(mx / bigS);
const bY = Math.floor(my / bigS);
const sX = Math.floor((mx % bigS) / smallS);
const sY = Math.floor((my % bigS) / smallS);
if (bX >= 0 && bX < 3 && bY >= 0 && bY < 3) {
return { big: bY * 3 + bX, small: sY * 3 + sX };
}
return null;
}
createAIAgent(type) {
if (type === 'random') {
return new RandomAgent();
} else if (type === 'rulebased' || type === 'rulebased_elementary') {
return new RuleBasedAgent(createStrategyTree('ultimate', 'elementary'));
} else if (type === 'rulebased_advanced') {
return new RuleBasedAgent(createStrategyTree('ultimate', 'advanced'));
} else if (type.startsWith('minimax')) {
const profileMap = {
minimax: 'v2_positional',
minimax_positional: 'v2_positional',
minimax_aggressive: 'v3_aggressive',
minimax_defensive: 'v4_defensive',
minimax_offensive: 'v5_offensive',
minimax_expert: 'v4_defensive'
};
const profile = profileMap[type] || 'v1_baseline';
const regKey = `ttt:ultimate:${profile}`;
const heuristicFn = (typeof HeuristicRegistry !== 'undefined' && HeuristicRegistry.has(regKey))
? HeuristicRegistry.get(regKey).evaluate.bind(HeuristicRegistry.get(regKey))
: (typeof HeuristicRegistry !== 'undefined' && HeuristicRegistry.has('ttt', 'ultimate'))
? HeuristicRegistry.get('ttt', 'ultimate').evaluate.bind(HeuristicRegistry.get('ttt', 'ultimate'))
: ((gameState, player) => {
if (gameState.winner === player) return 100000;
if (gameState.winner !== NONE && gameState.winner !== DRAW) return -100000;
return 0;
});
return new MinimaxAgent({
name: `Minimax Ultimate (${profile})`,
maxDepth: 5,
useAlphaBeta: true,
heuristicFn
});
}
return null;
}
}
// ===== WICHTIG: Die alte draw() Methode wurde entfernt =====
// Sie wird jetzt über drawGame() aufgerufen, die in der Basisklasse definiert ist.
// Fallback für HTML-inline onclick="..."
const draw = () => UltimateController?.drawGame?.();