runSelfPlaySession method
Future<void>
runSelfPlaySession(
- int numGames
)
Implementation
Future<void> runSelfPlaySession(int numGames) async {
final random = math.Random();
for (int g = 0; g < numGames; g++) {
final game = Game(variant: Variant.standard());
List<int> history = [0];
List<GameStep> gameSteps = [];
while (!game.gameOver && history.length < 100) {
final legalMoves = game.generateLegalMoves();
if (legalMoves.isEmpty) break;
// 1. Prediction & Masking
final state = model.represent(history);
final pred = model.predict(state);
final logits = pred['policy']!.data;
double maxLogit = -double.infinity;
for (var m in legalMoves) {
int idx = encodeMove(m, game);
if (logits[idx] > maxLogit) maxLogit = logits[idx];
}
// 2. Softmax for Target Policy
double sumExp = 0;
List<double> probs = List.filled(4098, 0.0);
for (var m in legalMoves) {
int idx = encodeMove(m, game);
double p = math.exp((logits[idx] - maxLogit).clamp(-10, 10));
probs[idx] = p;
sumExp += p;
}
for (int j = 0; j < probs.length; j++) {
if (probs[j] > 0) probs[j] /= (sumExp + 1e-10);
}
// 3. Move Selection
double r = random.nextDouble();
double cumulative = 0;
Move chosenMove = legalMoves.first;
for (var m in legalMoves) {
int idx = encodeMove(m, game);
cumulative += probs[idx];
if (r <= cumulative) {
chosenMove = m;
break;
}
}
gameSteps.add(GameStep(List.from(history), List.from(probs)));
// 4. Update Game
game.makeMove(chosenMove);
history.add(encodeMove(chosenMove, game));
if (history.length > 16) history.removeAt(0);
}
// 5. Calculate Result
double outcome = 0.0;
final result = game.result;
if (result is WonGame) {
outcome = (result.winner == Bishop.white) ? 1.0 : -1.0;
}
for (var step in gameSteps) {
step.targetValue = outcome;
if (replayBuffer.length >= maxBufferSize) replayBuffer.removeAt(0);
replayBuffer.add(step);
}
}
}