From 31f88a55796cfb7c49acc105b2a3b6c57e0a60ed Mon Sep 17 00:00:00 2001 From: Theodore Turocy Date: Tue, 16 Dec 2025 16:03:58 +0000 Subject: [PATCH 1/2] Implement collection of players including chance. This adds a convenience collection `GetPlayersWithChance`, which allows for iteration over all players, with the object representing the chance player first in the iteration. --- src/core/util.h | 54 +++++++++++++++++++++++++++++++++++++++++++ src/games/behavspt.cc | 3 +-- src/games/game.h | 1 + 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src/core/util.h b/src/core/util.h index f5678c706..fa33f5384 100644 --- a/src/core/util.h +++ b/src/core/util.h @@ -135,6 +135,60 @@ template class exclude_value { iterator m_begin, m_end; }; +template class prepend_value { +public: + using Iter = decltype(std::begin(std::declval())); + + class iterator { + public: + using iterator_category = std::forward_iterator_tag; + ; + using value_type = Value; + using difference_type = std::ptrdiff_t; + using reference = Value; + using pointer = Value; + + iterator(std::optional first, Iter current, Iter end) + : m_first(std::move(first)), m_current(current), m_end(end) + { + } + + reference operator*() const { return m_first ? *m_first : *m_current; } + + iterator &operator++() + { + if (m_first) { + m_first.reset(); + } + else { + ++m_current; + } + return *this; + } + + bool operator==(const iterator &other) const + { + return m_first == other.m_first && m_current == other.m_current; + } + + bool operator!=(const iterator &other) const { return !(*this == other); } + + private: + std::optional m_first; + Iter m_current, m_end; + }; + + prepend_value(Value first, Range range) : m_first(first), m_range(std::move(range)) {} + + iterator begin() const { return {m_first, std::begin(m_range), std::end(m_range)}; } + + iterator end() const { return {std::nullopt, std::end(m_range), std::end(m_range)}; } + +private: + Value m_first; + Range m_range; +}; + /// @brief Returns the maximum value of the function over the *non-empty* container template auto maximize_function(const Container &p_container, const Func &p_function) diff --git a/src/games/behavspt.cc b/src/games/behavspt.cc index 81cd29c9f..95f055b97 100644 --- a/src/games/behavspt.cc +++ b/src/games/behavspt.cc @@ -40,8 +40,7 @@ BehaviorSupportProfile::BehaviorSupportProfile(const Game &p_efg) : m_efg(p_efg) } // Initialize the list of reachable information sets and nodes - for (size_t pl = 0; pl <= GetGame()->NumPlayers(); pl++) { - const GamePlayer player = (pl == 0) ? GetGame()->GetChance() : GetGame()->GetPlayer(pl); + for (const auto &player : p_efg->GetPlayersWithChance()) { for (const auto &infoset : player->GetInfosets()) { m_infosetReachable[infoset] = true; for (const auto &member : infoset->GetMembers()) { diff --git a/src/games/game.h b/src/games/game.h index 4ff655df8..e060fb061 100644 --- a/src/games/game.h +++ b/src/games/game.h @@ -936,6 +936,7 @@ class GameRep : public std::enable_shared_from_this { } /// Returns the chance (nature) player virtual GamePlayer GetChance() const = 0; + auto GetPlayersWithChance() const { return prepend_value(GetChance(), GetPlayers()); } /// Creates a new player in the game, with no moves virtual GamePlayer NewPlayer() = 0; //@} From 89373d7310386cab7dcbf797b5cd5395871a2ddd Mon Sep 17 00:00:00 2001 From: Theodore Turocy Date: Tue, 16 Dec 2025 16:19:01 +0000 Subject: [PATCH 2/2] Include header --- src/core/util.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/util.h b/src/core/util.h index fa33f5384..1607f1fa1 100644 --- a/src/core/util.h +++ b/src/core/util.h @@ -30,6 +30,7 @@ #include #include #include +#include namespace Gambit {