games/tictactoe/ultimate-controller.js

/* --- 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
 */
class UltimateGameController extends BaseGameController {
    constructor() {
        super('ultimate', 'gameCanvas');
    }

    createGame() {
        return new UltimateBoard();
    }

    reset() {
        // ✅ Canvas-Größe für Ultimate anpassen (größer für Details)
        this.canvas.width = 600;
        this.canvas.height = 600;
        super.reset();
    }

    drawGame() {
        TTTRenderer.drawUltimate(this.canvas, this.game);
    }

    coordsToMove(mx, my) {
        const bigS = this.canvas.width / 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: 'v1_baseline', minimax_positional: 'v2_positional', minimax_aggressive: 'v3_aggressive' };
            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: 4,
                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?.();