mirror of
https://github.com/nolen777/eagle0.git
synced 2026-07-28 21:55:42 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e91f1792c |
@@ -687,6 +687,24 @@ auto AbstractMCTSAI::LogSearchResults(
|
||||
result.nodesEvaluated,
|
||||
rootNode->visitCount);
|
||||
|
||||
// Helper to check if a node is a "chance parent" - all children have the same action
|
||||
// This indicates the children represent different probabilistic outcomes of the same action
|
||||
auto isChanceParent = [](const MCTSNode* node) -> bool {
|
||||
if (!node || node->children.size() < 2) return false;
|
||||
const std::string* firstDesc = nullptr;
|
||||
for (const auto& child : node->children) {
|
||||
if (child->isRedundant) continue;
|
||||
if (!child->action) return false;
|
||||
const auto& desc = child->action->getDescription();
|
||||
if (!firstDesc) {
|
||||
firstDesc = &desc;
|
||||
} else if (*firstDesc != desc) {
|
||||
return false; // Different actions = not a chance node
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
// Log best sequence from chosen action (following most-visited path)
|
||||
std::vector<const MCTSNode*> bestSequence;
|
||||
bestSequence.reserve(10);
|
||||
@@ -712,18 +730,50 @@ auto AbstractMCTSAI::LogSearchResults(
|
||||
|
||||
if (!bestSequence.empty()) {
|
||||
printf("MCTS: Best sequence from chosen action (final: %.2f):\n", sequenceScore);
|
||||
int displayedStep = 0;
|
||||
for (size_t i = 0; i < bestSequence.size(); ++i) {
|
||||
const auto* node = bestSequence[i];
|
||||
printf(" %zu.", i + 1);
|
||||
|
||||
// Check if this node's parent was a chance node - if so, skip displaying this
|
||||
// outcome node separately since we already consolidated it with the action
|
||||
if (i > 0 && node->parent && isChanceParent(node->parent)) {
|
||||
// This is an outcome of a chance node - already displayed, skip
|
||||
continue;
|
||||
}
|
||||
|
||||
displayedStep++;
|
||||
printf(" %d.", displayedStep);
|
||||
if (node->action) { printf(" %s", node->action->getDescription().c_str()); }
|
||||
|
||||
// Check if this node is a chance parent (has multiple outcome children)
|
||||
if (isChanceParent(node)) {
|
||||
// Collect outcome information
|
||||
std::vector<std::pair<double, double>> outcomes; // (weight, lookahead)
|
||||
double totalWeight = 0;
|
||||
for (const auto& child : node->children) {
|
||||
if (child->isRedundant) continue;
|
||||
outcomes.emplace_back(child->actionWeight, child->lookaheadScore);
|
||||
totalWeight += child->actionWeight;
|
||||
}
|
||||
printf(" [%zu outcomes:", outcomes.size());
|
||||
for (size_t j = 0; j < std::min(outcomes.size(), size_t(3)); ++j) {
|
||||
const double pct =
|
||||
totalWeight > 0 ? (outcomes[j].first / totalWeight * 100) : 0;
|
||||
printf(" %.0f%%->%.1f", pct, outcomes[j].second);
|
||||
}
|
||||
if (outcomes.size() > 3) printf(" ...");
|
||||
printf("]");
|
||||
}
|
||||
|
||||
printf(" (visits:%d, immediate:%.2f, lookahead:%.2f)\n",
|
||||
node->visitCount,
|
||||
node->immediateScore,
|
||||
node->lookaheadScore);
|
||||
|
||||
// For non-root nodes in the sequence, show what the top alternatives were
|
||||
// This helps diagnose if opponent moves are being properly explored
|
||||
if (i > 0 && node->parent && !node->parent->children.empty()) {
|
||||
// Skip showing alternatives for chance outcome nodes (parent was chance)
|
||||
if (i > 0 && node->parent && !node->parent->children.empty() &&
|
||||
!isChanceParent(node->parent)) {
|
||||
// Collect all siblings (including this node) and sort by visit count
|
||||
std::vector<const MCTSNode*> siblings;
|
||||
siblings.reserve(node->parent->children.size());
|
||||
|
||||
Reference in New Issue
Block a user