core/game-adapter.js

/**
 * Einheitliche Schnittstelle für alle Tic-Tac-Toe Varianten.
 * 
 * Macht alle Spiele (Regular, 3D, Ultimate) über eine standardisierte API zugänglich.
 * Verhindert Code-Duplikation und sorgt für konsistentes Verhalten.
 * @fileoverview
 */

class GameAdapter {
    /**
     * Erstellt einen Adapter für eines der Spiele.
     * @param {TTTRegularBoard|TTT3DBoard|UltimateBoard} gameBoard 
     * @param {string} type - 'regular', '3d', oder 'ultimate'
     */
    constructor(gameBoard, type = 'regular') {
        this.gameBoard = gameBoard;
        this.type = type;
        
        // 🔴 NEURALGISCH: Adapter-Initialisierung (Phase 3)
        DebugConfig.log(DEBUG_DOMAINS.CORE_GAME_ADAPTER, 'debug',
            'GameAdapter initialized', {
                gameType: type,
                validMoves: gameBoard.getAllValidMoves().length,
                currentPlayer: gameBoard.currentPlayer,
                boardState: gameBoard.winner === 0 ? 'running' : 'finished'
            });
    }

    /**
     * Macht einen Zug mit einheitlicher Schnittstelle.
     * 
     * Für Regular/3D: makeMove(index)
     * Für Ultimate: makeMove({big, small})
     * 
     * @param {number|object} moveParam1 - Index oder Move-Objekt
     * @param {number} [moveParam2] - Optional: small-Index für Ultimate (bei zwei Parametern)
     * @returns {boolean} True wenn Zug erfolgreich
     */
    makeMove(moveParam1, moveParam2) {
        // 🔴 NEURALGISCH: Zug-Eingabe (Phase 3)
        DebugConfig.log(DEBUG_DOMAINS.CORE_GAME_ADAPTER, 'debug',
            'makeMove called', {
                moveType: this.type,
                moveInput: this.type === 'ultimate' ? 
                    (typeof moveParam1 === 'object' ? moveParam1 : { big: moveParam1, small: moveParam2 }) :
                    moveParam1,
                currentPlayer: this.gameBoard.currentPlayer,
                validMovesAvailable: this.gameBoard.getAllValidMoves().length
            });
        
        let result;
        if (this.type === 'ultimate') {
            // Ultimate: Beide Parameter oder Objekt
            if (typeof moveParam1 === 'object') {
                result = this.gameBoard.makeMove(moveParam1.big, moveParam1.small);
            } else {
                result = this.gameBoard.makeMove(moveParam1, moveParam2);
            }
        } else {
            // Regular & 3D: Nur ein Parameter
            result = this.gameBoard.makeMove(moveParam1);
        }
        
        // 🔴 NEURALGISCH: Zug-Ausführungs-Resultat (Phase 3)
        if (result) {
            DebugConfig.log(DEBUG_DOMAINS.CORE_GAME_ADAPTER, 'debug',
                'makeMove successful', {
                    newPlayer: this.gameBoard.currentPlayer,
                    remainingMoves: this.gameBoard.getAllValidMoves().length,
                    gameStatus: this.gameBoard.winner === 0 ? 'running' : 
                                 (this.gameBoard.winner === 3 ? 'draw' : 'winner=' + this.gameBoard.winner)
                });
        } else {
            DebugConfig.log(DEBUG_DOMAINS.CORE_GAME_ADAPTER, 'warn',
                'makeMove failed - invalid move', {
                    attemptedMove: this.type === 'ultimate' ? 
                        (typeof moveParam1 === 'object' ? moveParam1 : { big: moveParam1, small: moveParam2 }) :
                        moveParam1
                });
        }
        
        return result;
    }

    /**
     * Gibt gültige Züge für die nächste Entscheidung zurück.
     * Format ist spiel-spezifisch, aber vollständig nutzbar.
     * 
     * @returns {Array} Array von Zug-Objekten oder Indizes
     */
    getValidMoves() {
        const moves = this.gameBoard.getAllValidMoves();
        // 🔴 NEURALGISCH: Gültige Züge-Abfrage (nur bei Debug)
        DebugConfig.log(DEBUG_DOMAINS.CORE_GAME_ADAPTER, 'debug',
            'getValidMoves queried', {
                count: moves.length,
                currentPlayer: this.gameBoard.currentPlayer
            });
        return moves;
    }

    /**
     * Alias für getValidMoves(), um Konsistenz mit Board-Interface zu wahren.
     * @returns {Array} Array von Zug-Objekten oder Indizes
     */
    getAllValidMoves() {
        return this.gameBoard.getAllValidMoves();
    }

    /**
     * Gibt an, ob das Spiel vorbei ist.
     * @returns {boolean}
     */
    isGameOver() {
        const gameOver = this.gameBoard.winner !== 0;
        // 🔴 NEURALGISCH: Spielende-Check (nur bei Status-Änderung wichtig)
        if (gameOver && this.lastWinnerState !== this.gameBoard.winner) {
            DebugConfig.log(DEBUG_DOMAINS.CORE_GAME_ADAPTER, 'debug',
                'Game Over detected', {
                    winner: this.gameBoard.winner === 3 ? 'draw' : 'Player ' + this.gameBoard.winner,
                    finalMoveCount: (this.gameBoard.grid ? this.gameBoard.grid.length : 'unknown')
                });
            this.lastWinnerState = this.gameBoard.winner;
        }
        return gameOver;
    }

    /**
     * Gibt die verbleibenden gültigen Züge an.
     * @returns {number}
     */
    getRemainingMoves() {
        return this.gameBoard.getAllValidMoves().length;
    }

    /**
     * Klont das aktuelle Spiel für KI-Simulationen.
     * @returns {GameAdapter}
     */
    clone() {
        const clonedBoard = this.gameBoard.clone();
        return new GameAdapter(clonedBoard, this.type);
    }

    /**
     * Direkter Zugriff auf das unterliegende Board (wenn nötig).
     * @returns {TTTRegularBoard|TTT3DBoard|UltimateBoard}
     */
    getBoard() {
        return this.gameBoard;
    }

    /**
     * Alias für getBoard() - liefert den aktuellen Game State.
     * @returns {TTTRegularBoard|TTT3DBoard|UltimateBoard}
     */
    getState() {
        return this.gameBoard;
    }

    /**
     * Gibt den aktuellen Spieler zurück.
     * @returns {number} 1 oder 2
     */
    getCurrentPlayer() {
        return this.gameBoard.currentPlayer;
    }

    /**
     * Gibt den Gewinner zurück.
     * @returns {number} 0=laufend, 1/2=Gewinner, 3=Remis
     */
    getWinner() {
        return this.gameBoard.winner;
    }
}