games/tictactoe/regular-controller.js

/* --- FILE: js/games/tictactoe/regular-controller.js --- */
/**
 * @fileoverview Controller für 3x3 Tic-Tac-Toe
 * 
 * Extends BaseGameController mit regularem 3x3 Board-Support.
 * Verwaltet Spielstatus, Benutzer-Input und Rendering für klassisches TTT.
 * 
 * @class RegularGameController
 * @extends BaseGameController
 */
class RegularGameController extends BaseGameController {
    /**
     * Erstellt einen neuen Regular Controller.
     * @constructor
     */
    constructor() {
        super('regular', 'gameCanvas');
    }

    /**
     * Erzeugt ein neues Regular Board.
     * @returns {TTTRegularBoard} Ein neues 3x3 Tic-Tac-Toe Board
     */
    createGame() {
        return new TTTRegularBoard();
    }

    /**
     * Setzt das Spiel zurück und konfiguriert Canvas-Größe.
     * @override
     * @returns {void}
     */
    reset() {
        DebugConfig.log(DEBUG_DOMAINS.GAMES_TTT_REGULAR, "debug", '🔄 RegularGameController.reset() wird aufgerufen');
        DebugConfig.log(DEBUG_DOMAINS.GAMES_TTT_REGULAR, "debug", '   - Canvas vor Resize:', this.canvas?.width, 'x', this.canvas?.height);
        
        if (!this.canvas) {
            DebugConfig.log(DEBUG_DOMAINS.GAMES_TTT_REGULAR, "error", '❌ KRITISCHER FEHLER: Canvas ist null!');
            return;
        }
        
        // ✅ Canvas-Größe für Regular anpassen
        this.canvas.width = 400;
        this.canvas.height = 400;
        DebugConfig.log(DEBUG_DOMAINS.GAMES_TTT_REGULAR, "debug", '✅ Canvas resized zu 400x400');
        
        super.reset();
    }

    /**
     * Zeichnet das Regular TTT Board auf Canvas.
     * @override
     * @returns {void}
     */
    drawGame() {
        DebugConfig.log(DEBUG_DOMAINS.GAMES_TTT_REGULAR, "debug", '🎨 drawGame() - Zeichne Regular TTT Board');
        DebugConfig.log(DEBUG_DOMAINS.GAMES_TTT_REGULAR, "debug", '   - Canvas:', this.canvas.width, 'x', this.canvas.height);
        DebugConfig.log(DEBUG_DOMAINS.GAMES_TTT_REGULAR, "debug", '   - game.grid:', this.game.grid);
        DebugConfig.log(DEBUG_DOMAINS.GAMES_TTT_REGULAR, "debug", '   - game.winner:', this.game.winner);
        TTTRenderer.drawRegular(this.canvas, this.game);
        DebugConfig.log(DEBUG_DOMAINS.GAMES_TTT_REGULAR, "debug", '✅ Zeichnen abgeschlossen');
    }

    /**
     * Konvertiert Mauskoordinaten zu Board-Move-Index.
     * @param {number} mx - Maus X-Koordinate
     * @param {number} my - Maus Y-Koordinate
     * @returns {number|null} Move als 0-8 Index oder null wenn invalid
     */
    coordsToMove(mx, my) {
        const s = this.canvas.width / 3;
        const c = Math.floor(mx / s);
        const r = Math.floor(my / s);
        
        if (c >= 0 && c < 3 && r >= 0 && r < 3) {
            return r * 3 + c;
        }
        return null;
    }

    createAIAgent(type) {
        DebugConfig.log(DEBUG_DOMAINS.GAMES_TTT_REGULAR, "debug", '🤖 RegularGameController.createAIAgent() aufgerufen mit type:', type);
        
        try {
            if (type === 'random') {
                const agent = new RandomAgent();
                DebugConfig.log(DEBUG_DOMAINS.GAMES_TTT_REGULAR, "debug", '✅ RandomAgent erstellt');
                return agent;
            } else if (type === 'rulebased' || type === 'rulebased_elementary') {
                const tree = createStrategyTree('regular', 'elementary');
                return new RuleBasedAgent(tree);
            } else if (type === 'rulebased_advanced') {
                const tree = createStrategyTree('regular', 'advanced');
                return new RuleBasedAgent(tree);
            } else if (type.startsWith('minimax')) {
                // Profile-Mapping: minimax → v1_baseline, minimax_positional → v2_positional, etc.
                const profileMap = { minimax: 'v1_baseline', minimax_positional: 'v2_positional', minimax_aggressive: 'v3_aggressive' };
                const profile = profileMap[type] || 'v1_baseline';
                const regKey = `ttt:regular:${profile}`;
                const heuristicFn = (typeof HeuristicRegistry !== 'undefined' && HeuristicRegistry.has(regKey))
                    ? HeuristicRegistry.get(regKey).evaluate.bind(HeuristicRegistry.get(regKey))
                    : (typeof HeuristicRegistry !== 'undefined' && HeuristicRegistry.has('ttt', 'regular'))
                        ? HeuristicRegistry.get('ttt', 'regular').evaluate.bind(HeuristicRegistry.get('ttt', 'regular'))
                        : ((gameState, player) => {
                            if (gameState.winner === player) return 1000;
                            if (gameState.winner !== NONE && gameState.winner !== DRAW) return -1000;
                            return 0;
                        });
                return new MinimaxAgent({
                    name: `Minimax (${profile})`,
                    maxDepth: 9,
                    useAlphaBeta: true,
                    heuristicFn
                });
            }
            
            DebugConfig.log(DEBUG_DOMAINS.GAMES_TTT_REGULAR, "warn", '⚠️ Unbekannter Agent-Typ:', type);
            return null;
        } catch (error) {
            DebugConfig.log(DEBUG_DOMAINS.GAMES_TTT_REGULAR, "error", `❌ FEHLER beim Erstellen des ${type} Agents:`, error);
            DebugConfig.log(DEBUG_DOMAINS.GAMES_TTT_REGULAR, "error", '   Stack:', error.stack);
            return null;
        }
    }
}