From 1ad3551f571296e5ddf7cef86f5279a1ba7e1951 Mon Sep 17 00:00:00 2001 From: drdkad Date: Tue, 20 Jan 2026 07:58:44 +0000 Subject: [PATCH] Refactor BuildOwnPriorActions to use Visitor pattern --- src/games/gametree.cc | 87 +++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 48 deletions(-) diff --git a/src/games/gametree.cc b/src/games/gametree.cc index 3df2700c0..0f0ff9b35 100644 --- a/src/games/gametree.cc +++ b/src/games/gametree.cc @@ -980,70 +980,61 @@ std::vector GameTreeRep::BuildConsistentPlaysRecursiveImpl(GameNo void GameTreeRep::BuildOwnPriorActions() const { - auto info = std::make_shared(); - if (m_root->IsTerminal()) { - m_ownPriorActionInfo = info; + m_ownPriorActionInfo = std::make_shared(); return; } - info->node_map[m_root.get()] = nullptr; - if (m_root->m_infoset) { - info->infoset_map[m_root->m_infoset].insert(nullptr); - } - - using ActiveEdge = GameNodeRep::Actions::iterator; - - std::stack position; - std::map> prior_actions; + struct OwnPriorActionsVisitor { + std::shared_ptr m_info; + std::map> m_priorActions; - for (auto player_rep : m_players) { - prior_actions[GamePlayer(player_rep)].emplace(nullptr); - } - prior_actions[GamePlayer(m_chance)].emplace(nullptr); + explicit OwnPriorActionsVisitor(const GameTreeRep *p_game) + : m_info(std::make_shared()) + { + for (const auto &player : p_game->GetPlayersWithChance()) { + m_priorActions[player].emplace(nullptr); + } + } - position.emplace(m_root->GetActions().begin()); - if (m_root->m_infoset) { - prior_actions[m_root->m_infoset->m_player->shared_from_this()].emplace(nullptr); - } + DFSCallbackResult OnEnter(GameNode p_node, int) + { + if (auto *infoset = p_node->m_infoset) { + auto &stack = m_priorActions.at(infoset->m_player->shared_from_this()); + GameActionRep *raw_prior = stack.top() ? stack.top().get() : nullptr; - while (!position.empty()) { - ActiveEdge ¤t_edge = position.top(); - auto node = current_edge.GetOwner(); + m_info->node_map[p_node.get()] = raw_prior; + m_info->infoset_map[infoset].insert(raw_prior); - if (current_edge == node->GetActions().end()) { - if (node->m_infoset) { - prior_actions.at(node->m_infoset->m_player->shared_from_this()).pop(); + stack.emplace(nullptr); } - position.pop(); - continue; + return DFSCallbackResult::Continue; } - auto [action, child] = *current_edge; - ++current_edge; + DFSCallbackResult OnAction(GameNode p_parent, GameNode p_child, int) + { + m_priorActions.at(p_parent->m_infoset->m_player->shared_from_this()).top() = + p_child->GetPriorAction(); + return DFSCallbackResult::Continue; + } - if (node->m_infoset) { - prior_actions.at(node->m_infoset->m_player->shared_from_this()).top() = action; + DFSCallbackResult OnExit(const GameNode &p_node, int) + { + if (auto *infoset = p_node->m_infoset) { + m_priorActions.at(infoset->m_player->shared_from_this()).pop(); + } + return DFSCallbackResult::Continue; } - if (!child->IsTerminal()) { - if (child->m_infoset) { - auto child_player = child->m_infoset->m_player->shared_from_this(); - auto prior_action = prior_actions.at(child_player).top(); - GameActionRep *raw_prior = prior_action ? prior_action.get() : nullptr; + void OnVisit(GameNode, int) {} + }; - info->node_map[child.get()] = raw_prior; - info->infoset_map[child->m_infoset].insert(raw_prior); + OwnPriorActionsVisitor visitor(this); - position.emplace(child->GetActions().begin()); - prior_actions.at(child_player).emplace(nullptr); - } - else { - position.emplace(child->GetActions().begin()); - } - } - } - m_ownPriorActionInfo = info; + WalkDFS(const_cast(this)->shared_from_this(), m_root, TraversalOrder::Preorder, + visitor); + + m_ownPriorActionInfo = visitor.m_info; } GameAction GameTreeRep::GetOwnPriorAction(const GameNode &p_node) const