/**
* 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;
}
}