main function

void main()

Implementation

void main() async {
  // 1. Setup Architecture
  final transformer = TransformerDecoder(vocabSize: 4098, embedSize: 128);
  final model = MuZeroModel(transformer, 128);

  // 2. Initialize the Search Engine
  final searchEngine = MuZeroSearch(model);

  // 3. Load Weights
  print("Loading weights...");
  await loadModuleParameters(transformer, "muzero_chess_v1.json");

  // 4. Initialize Bishop Game
  final game = Game(variant: Variant.standard());
  List<int> history = [0];

  print("\n--- Model Play Test (Thinking Mode) ---\n");
  print(game.ascii());

  for (int turn = 0; turn < 50; turn++) {
    // 5. Get current latent state
    final rootState = model.represent(history);

    // 6. Get legal move indices for masking
    final legalMoves = game.generateLegalMoves();
    if (legalMoves.isEmpty) {
      print("Game Over: ${game.result?.readable}");
      break;
    }
    final List<int> legalActions = legalMoves
        .map((m) => encodeMove(m, game))
        .toList();

    // 7. THINK: Run MCTS simulations
    // This uses the Dynamics head to look ahead
    print("Model is thinking...");
    int bestActionIdx = searchEngine.search(
      rootState,
      legalActions,
      numSimulations: 30, // Adjust this for "deeper" thought
    );

    // 8. Execute the best move found by MCTS
    Move? chosenMove = decodeMove(bestActionIdx, game);

    if (chosenMove != null) {
      String san = game.toSan(chosenMove);
      game.makeMove(chosenMove);
      history.add(bestActionIdx);
      if (history.length > 16) history.removeAt(0);

      print("Turn ${turn + 1}: Model played $san");
      print(game.ascii());
      print("--------------------------------");
    } else {
      print("Error: Search returned an invalid move index.");
      break;
    }
  }

  print("\nFinal PGN: ${game.pgn()}");
}