Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 49 additions & 30 deletions src/games/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
#include <list>
#include <memory>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
Expand Down Expand Up @@ -663,6 +662,8 @@ class GamePlayerRep : public std::enable_shared_from_this<GamePlayerRep> {
//@}
};

enum class TraversalOrder { Preorder, Postorder };

/// A node in an extensive game
class GameNodeRep : public std::enable_shared_from_this<GameNodeRep> {
friend class GameTreeRep;
Expand Down Expand Up @@ -888,8 +889,6 @@ class GameSubgameRep : public std::enable_shared_from_this<GameSubgameRep> {
InfosetCollection GetSubgameDifference() const;
};

enum class TraversalOrder { Preorder, Postorder };

class CartesianProductSpace {
public:
std::vector<int> m_radices;
Expand Down Expand Up @@ -1088,49 +1087,69 @@ class GameRep : public std::enable_shared_from_this<GameRep> {
class iterator {
friend class Nodes;

struct NodeHandler {
std::queue<GameNode> m_queue;

static DFSCallbackResult OnEnter(const GameNode &, int)
{
return DFSCallbackResult::Continue;
}
static DFSCallbackResult OnAction(const GameNode &, const GameNode &, int)
{
return DFSCallbackResult::Continue;
}
static DFSCallbackResult OnExit(const GameNode &, int)
{
return DFSCallbackResult::Continue;
}
void OnVisit(const GameNode &p_node, int) { m_queue.push(p_node); }
using ChildIterator = ElementCollection<GameNode, GameNodeRep>::iterator;

// One frame per node currently open on the path from the root; this mirrors
// WalkDFS's own stack, but is kept alive across calls to advance() (instead of
// living inside a single call to WalkDFS) so the walk can pause after each node
// and resume from exactly where it left off, rather than visiting the whole tree
// up front.
struct Frame {
GameNode m_node;
ChildIterator m_current;
ChildIterator m_end;
bool m_entered{false};
};

Game m_owner{nullptr};
std::shared_ptr<NodeHandler> m_handler;
TraversalOrder m_order{TraversalOrder::Preorder};
std::stack<Frame> m_stack;
GameNode m_current{nullptr};

iterator(const Game &p_game, TraversalOrder p_order)
: m_owner(p_game), m_handler(std::make_shared<NodeHandler>())
iterator(const Game &p_game, TraversalOrder p_order) : m_owner(p_game), m_order(p_order)
{
if (!p_game) {
m_owner = nullptr;
return;
}
WalkDFS(p_game, p_game->GetRoot(), p_order, *m_handler);
m_stack.push(Frame{p_game->GetRoot(), {}, {}, false});
advance();
}

void advance()
{
if (!m_handler || m_handler->m_queue.empty()) {
m_current = nullptr;
m_owner = nullptr;
}
else {
m_current = m_handler->m_queue.front();
m_handler->m_queue.pop();
while (!m_stack.empty()) {
Frame &f = m_stack.top();

if (!f.m_entered) {
f.m_entered = true;
if (!f.m_node->IsTerminal()) {
auto children = f.m_node->GetChildren();
f.m_current = children.begin();
f.m_end = children.end();
}
if (m_order == TraversalOrder::Preorder) {
m_current = f.m_node;
return;
}
}

if (!f.m_node->IsTerminal() && f.m_current != f.m_end) {
GameNode const child = *f.m_current;
++f.m_current;
m_stack.push(Frame{child, {}, {}, false});
continue;
}

GameNode const finished = f.m_node;
m_stack.pop();
if (m_order == TraversalOrder::Postorder) {
m_current = finished;
return;
}
}
m_current = nullptr;
m_owner = nullptr;
}

public:
Expand Down
Loading