Skip to content

Commit 34693af

Browse files
authored
Add GetPlayersWithChance() range (#711)
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.
1 parent 4639754 commit 34693af

3 files changed

Lines changed: 57 additions & 2 deletions

File tree

src/core/util.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <algorithm>
3131
#include <numeric>
3232
#include <map>
33+
#include <optional>
3334

3435
namespace Gambit {
3536

@@ -133,6 +134,60 @@ template <typename Container, typename Pred> class filter_if {
133134
iterator m_begin, m_end;
134135
};
135136

137+
template <typename Value, typename Range> class prepend_value {
138+
public:
139+
using Iter = decltype(std::begin(std::declval<Range &>()));
140+
141+
class iterator {
142+
public:
143+
using iterator_category = std::forward_iterator_tag;
144+
;
145+
using value_type = Value;
146+
using difference_type = std::ptrdiff_t;
147+
using reference = Value;
148+
using pointer = Value;
149+
150+
iterator(std::optional<Value> first, Iter current, Iter end)
151+
: m_first(std::move(first)), m_current(current), m_end(end)
152+
{
153+
}
154+
155+
reference operator*() const { return m_first ? *m_first : *m_current; }
156+
157+
iterator &operator++()
158+
{
159+
if (m_first) {
160+
m_first.reset();
161+
}
162+
else {
163+
++m_current;
164+
}
165+
return *this;
166+
}
167+
168+
bool operator==(const iterator &other) const
169+
{
170+
return m_first == other.m_first && m_current == other.m_current;
171+
}
172+
173+
bool operator!=(const iterator &other) const { return !(*this == other); }
174+
175+
private:
176+
std::optional<Value> m_first;
177+
Iter m_current, m_end;
178+
};
179+
180+
prepend_value(Value first, Range range) : m_first(first), m_range(std::move(range)) {}
181+
182+
iterator begin() const { return {m_first, std::begin(m_range), std::end(m_range)}; }
183+
184+
iterator end() const { return {std::nullopt, std::end(m_range), std::end(m_range)}; }
185+
186+
private:
187+
Value m_first;
188+
Range m_range;
189+
};
190+
136191
/// @brief Returns the maximum value of the function over the *non-empty* container
137192
template <class Container, class Func>
138193
auto maximize_function(const Container &p_container, const Func &p_function)

src/games/behavspt.cc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@ BehaviorSupportProfile::BehaviorSupportProfile(const Game &p_efg) : m_efg(p_efg)
4040
}
4141

4242
// Initialize the list of reachable information sets and nodes
43-
for (size_t pl = 0; pl <= GetGame()->NumPlayers(); pl++) {
44-
const GamePlayer player = (pl == 0) ? GetGame()->GetChance() : GetGame()->GetPlayer(pl);
43+
for (const auto &player : p_efg->GetPlayersWithChance()) {
4544
for (const auto &infoset : player->GetInfosets()) {
4645
m_infosetReachable[infoset] = true;
4746
for (const auto &member : infoset->GetMembers()) {

src/games/game.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -939,6 +939,7 @@ class GameRep : public std::enable_shared_from_this<GameRep> {
939939
}
940940
/// Returns the chance (nature) player
941941
virtual GamePlayer GetChance() const = 0;
942+
auto GetPlayersWithChance() const { return prepend_value(GetChance(), GetPlayers()); }
942943
/// Creates a new player in the game, with no moves
943944
virtual GamePlayer NewPlayer() = 0;
944945
//@}

0 commit comments

Comments
 (0)