Skip to content

Commit 3ccc8cf

Browse files
committed
Convert player to use shared pointers
1 parent 16d9ad9 commit 3ccc8cf

File tree

14 files changed

+108
-78
lines changed

14 files changed

+108
-78
lines changed

src/games/game.cc

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,13 @@ GameAction GameStrategyRep::GetAction(const GameInfoset &p_infoset) const
6363
// class GamePlayerRep
6464
//========================================================================
6565

66-
GamePlayerRep::GamePlayerRep(GameRep *p_game, int p_id, int p_strats)
67-
: m_game(p_game), m_number(p_id)
66+
std::shared_ptr<GamePlayerRep> GamePlayerRep::CreatePlayer(GameRep *p_game, int p_id, int p_strats)
6867
{
68+
auto player = std::make_shared<GamePlayerRep>(p_game, p_id);
6969
for (int j = 1; j <= p_strats; j++) {
70-
m_strategies.push_back(new GameStrategyRep(this, j, ""));
70+
player->m_strategies.push_back(new GameStrategyRep(player, j, ""));
7171
}
72+
return player;
7273
}
7374

7475
GamePlayerRep::~GamePlayerRep()
@@ -94,7 +95,8 @@ void GamePlayerRep::MakeStrategy()
9495
}
9596
}
9697

97-
auto *strategy = new GameStrategyRep(this, m_strategies.size() + 1, "");
98+
auto *strategy = new GameStrategyRep(std::const_pointer_cast<GamePlayerRep>(shared_from_this()),
99+
m_strategies.size() + 1, "");
98100
strategy->m_behav = c;
99101

100102
// We generate a default labeling -- probably should be changed in future
@@ -123,7 +125,7 @@ void GamePlayerRep::MakeReducedStrats(GameNodeRep *n, GameNodeRep *nn)
123125
}
124126

125127
if (!n->IsTerminal()) {
126-
if (n->m_infoset->m_player == this) {
128+
if (n->m_infoset->m_player.get() == this) {
127129
if (n->m_infoset->flag == 0) {
128130
// we haven't visited this infoset before
129131
n->m_infoset->flag = 1;
@@ -367,7 +369,7 @@ MixedStrategyProfile<T>::operator=(const MixedStrategyProfile<T> &p_profile)
367369
// MixedStrategyProfile<T>: General data access
368370
//========================================================================
369371

370-
template <class T> Vector<T> MixedStrategyProfile<T>::operator[](const GamePlayer &p_player) const
372+
template <class T> Vector<T> MixedStrategyProfile<T>::get(const GamePlayer &p_player) const
371373
{
372374
CheckVersion();
373375
auto strategies = m_rep->m_support.GetStrategies(p_player);

src/games/game.h

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class GameStrategyRep;
4949
using GameStrategy = GameObjectPtr<GameStrategyRep>;
5050

5151
class GamePlayerRep;
52-
using GamePlayer = GameObjectPtr<GamePlayerRep>;
52+
using GamePlayer = GameObjectSharedPtr<GamePlayerRep>;
5353

5454
class GameNodeRep;
5555
using GameNode = GameObjectPtr<GameNodeRep>;
@@ -271,7 +271,7 @@ class GameOutcomeRep : public std::enable_shared_from_this<GameOutcomeRep> {
271271
GameRep *m_game;
272272
int m_number;
273273
std::string m_label;
274-
std::map<GamePlayerRep *, Number> m_payoffs;
274+
std::map<std::shared_ptr<GamePlayerRep>, Number> m_payoffs;
275275

276276
public:
277277
/// @name Lifecycle
@@ -348,10 +348,10 @@ class GameInfosetRep : public std::enable_shared_from_this<GameInfosetRep> {
348348
template <class T> friend class MixedBehaviorProfile;
349349

350350
bool m_valid{true};
351-
GameRep *m_game;
352-
int m_number;
351+
GameRep *m_game{nullptr};
352+
int m_number{0};
353353
std::string m_label;
354-
GamePlayerRep *m_player;
354+
std::shared_ptr<GamePlayerRep> m_player;
355355
std::vector<std::shared_ptr<GameActionRep>> m_actions;
356356
std::vector<GameNodeRep *> m_members;
357357
int flag{0}, whichbranch{0};
@@ -371,7 +371,8 @@ class GameInfosetRep : public std::enable_shared_from_this<GameInfosetRep> {
371371
~GameInfosetRep();
372372

373373
static std::shared_ptr<GameInfosetRep> CreateInfoset(GameRep *p_efg, int p_number,
374-
GamePlayerRep *p_player, int p_actions);
374+
std::shared_ptr<GamePlayerRep> p_player,
375+
int p_actions);
375376

376377
/// @name Validity management
377378
//@{
@@ -441,7 +442,7 @@ class GameStrategyRep : public GameObject {
441442
template <class T> friend class TableMixedStrategyProfileRep;
442443
template <class T> friend class MixedBehaviorProfile;
443444

444-
GamePlayerRep *m_player;
445+
std::shared_ptr<GamePlayerRep> m_player;
445446
int m_number;
446447
long m_offset{-1L};
447448
std::string m_label;
@@ -450,7 +451,8 @@ class GameStrategyRep : public GameObject {
450451
/// @name Lifecycle
451452
//@{
452453
/// Creates a new strategy for the given player.
453-
explicit GameStrategyRep(GamePlayerRep *p_player, int p_number, const std::string &p_label)
454+
explicit GameStrategyRep(std::shared_ptr<GamePlayerRep> p_player, int p_number,
455+
const std::string &p_label)
454456
: m_player(p_player), m_number(p_number), m_label(p_label)
455457
{
456458
}
@@ -475,7 +477,7 @@ class GameStrategyRep : public GameObject {
475477
};
476478

477479
/// A player in a game
478-
class GamePlayerRep : public GameObject {
480+
class GamePlayerRep : public std::enable_shared_from_this<GamePlayerRep> {
479481
friend class GameRep;
480482
friend class GameExplicitRep;
481483
friend class GameTreeRep;
@@ -494,20 +496,27 @@ class GamePlayerRep : public GameObject {
494496
void MakeReducedStrats(class GameNodeRep *, class GameNodeRep *);
495497
//@}
496498

499+
bool m_valid{true};
497500
GameRep *m_game;
498501
int m_number;
499502
std::string m_label;
500503
std::vector<std::shared_ptr<GameInfosetRep>> m_infosets;
501504
std::vector<GameStrategyRep *> m_strategies;
502505

503-
GamePlayerRep(GameRep *p_game, int p_id) : m_game(p_game), m_number(p_id) {}
504-
GamePlayerRep(GameRep *p_game, int p_id, int m_strats);
505-
~GamePlayerRep() override;
506-
507506
public:
508507
using Infosets = SmartElementCollection<GamePlayer, GameInfosetRep>;
509508
using Strategies = ElementCollection<GamePlayer, GameStrategyRep>;
510509

510+
GamePlayerRep(GameRep *p_game, int p_id) : m_game(p_game), m_number(p_id) {}
511+
static std::shared_ptr<GamePlayerRep> CreatePlayer(GameRep *p_game, int p_id, int p_strats);
512+
~GamePlayerRep();
513+
514+
/// @name Validity management
515+
//@{
516+
bool IsValid() const { return m_valid; }
517+
void Invalidate() { m_valid = false; }
518+
//@}
519+
511520
int GetNumber() const { return m_number; }
512521
Game GetGame() const;
513522

@@ -521,7 +530,10 @@ class GamePlayerRep : public GameObject {
521530
/// Returns the p_index'th information set
522531
GameInfoset GetInfoset(int p_index) const { return m_infosets.at(p_index - 1); }
523532
/// Returns the information sets for the player
524-
Infosets GetInfosets() const { return Infosets(this, &m_infosets); }
533+
Infosets GetInfosets() const
534+
{
535+
return Infosets(std::const_pointer_cast<GamePlayerRep>(shared_from_this()), &m_infosets);
536+
}
525537

526538
/// @name Strategies
527539
//@{
@@ -605,7 +617,7 @@ class GameRep : public BaseGameRep {
605617
template <class T> friend class TableMixedStrategyProfileRep;
606618

607619
protected:
608-
std::vector<GamePlayerRep *> m_players;
620+
std::vector<std::shared_ptr<GamePlayerRep>> m_players;
609621
std::vector<std::shared_ptr<GameOutcomeRep>> m_outcomes;
610622
std::string m_title, m_comment;
611623
unsigned int m_version{0};
@@ -619,7 +631,7 @@ class GameRep : public BaseGameRep {
619631
//@}
620632

621633
public:
622-
using Players = ElementCollection<Game, GamePlayerRep>;
634+
using Players = SmartElementCollection<Game, GamePlayerRep>;
623635
using Outcomes = SmartElementCollection<Game, GameOutcomeRep>;
624636

625637
class Nodes {
@@ -834,17 +846,19 @@ class GameRep : public BaseGameRep {
834846
int NumStrategyContingencies() const
835847
{
836848
BuildComputedValues();
837-
return std::transform_reduce(m_players.begin(), m_players.end(), 0, std::multiplies<>(),
838-
[](const GamePlayerRep *p) { return p->m_strategies.size(); });
849+
return std::transform_reduce(
850+
m_players.begin(), m_players.end(), 0, std::multiplies<>(),
851+
[](const std::shared_ptr<GamePlayerRep> p) { return p->m_strategies.size(); });
839852
}
840853
/// Returns the total number of actions in the game
841854
virtual int BehavProfileLength() const = 0;
842855
/// Returns the total number of strategies in the game
843856
int MixedProfileLength() const
844857
{
845858
BuildComputedValues();
846-
return std::transform_reduce(m_players.begin(), m_players.end(), 0, std::plus<>(),
847-
[](const GamePlayerRep *p) { return p->m_strategies.size(); });
859+
return std::transform_reduce(
860+
m_players.begin(), m_players.end(), 0, std::plus<>(),
861+
[](const std::shared_ptr<GamePlayerRep> p) { return p->m_strategies.size(); });
848862
}
849863
//@}
850864

@@ -988,7 +1002,7 @@ inline GameStrategy GamePlayerRep::GetStrategy(int st) const
9881002
inline GamePlayerRep::Strategies GamePlayerRep::GetStrategies() const
9891003
{
9901004
m_game->BuildComputedValues();
991-
return Strategies(this, &m_strategies);
1005+
return Strategies(std::const_pointer_cast<GamePlayerRep>(shared_from_this()), &m_strategies);
9921006
}
9931007

9941008
inline Game GameNodeRep::GetGame() const { return m_game; }

src/games/gameagg.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,10 +136,10 @@ template <class T>
136136
T AGGMixedStrategyProfileRep<T>::GetPayoffDeriv(int pl, const GameStrategy &ps1,
137137
const GameStrategy &ps2) const
138138
{
139-
GamePlayerRep *player1 = ps1->GetPlayer();
140-
GamePlayerRep *player2 = ps2->GetPlayer();
139+
const std::shared_ptr<GamePlayerRep> player1 = ps1->GetPlayer();
140+
const std::shared_ptr<GamePlayerRep> player2 = ps2->GetPlayer();
141141
if (player1 == player2) {
142-
return (T)0;
142+
return static_cast<T>(0);
143143
}
144144

145145
auto &g = dynamic_cast<GameAGGRep &>(*(this->m_support.GetGame()));
@@ -179,7 +179,7 @@ template class AGGMixedStrategyProfileRep<Rational>;
179179
GameAGGRep::GameAGGRep(std::shared_ptr<agg::AGG> p_aggPtr) : aggPtr(p_aggPtr)
180180
{
181181
for (int pl = 1; pl <= aggPtr->getNumPlayers(); pl++) {
182-
m_players.push_back(new GamePlayerRep(this, pl, aggPtr->getNumActions(pl - 1)));
182+
m_players.push_back(GamePlayerRep::CreatePlayer(this, pl, aggPtr->getNumActions(pl - 1)));
183183
m_players.back()->m_label = lexical_cast<std::string>(pl);
184184
std::for_each(m_players.back()->m_strategies.begin(), m_players.back()->m_strategies.end(),
185185
[st = 1](GameStrategyRep *s) mutable { s->SetLabel(std::to_string(st++)); });

src/games/gamebagg.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,10 @@ template <class T>
156156
T BAGGMixedStrategyProfileRep<T>::GetPayoffDeriv(int pl, const GameStrategy &ps1,
157157
const GameStrategy &ps2) const
158158
{
159-
GamePlayerRep *player1 = ps1->GetPlayer();
160-
GamePlayerRep *player2 = ps2->GetPlayer();
159+
const std::shared_ptr<GamePlayerRep> player1 = ps1->GetPlayer();
160+
const std::shared_ptr<GamePlayerRep> player2 = ps2->GetPlayer();
161161
if (player1 == player2) {
162-
return (T)0;
162+
return static_cast<T>(0);
163163
}
164164

165165
auto &g = dynamic_cast<GameBAGGRep &>(*(this->m_support.GetGame()));
@@ -212,7 +212,7 @@ GameBAGGRep::GameBAGGRep(std::shared_ptr<agg::BAGG> _baggPtr)
212212
int k = 1;
213213
for (int pl = 1; pl <= baggPtr->getNumPlayers(); pl++) {
214214
for (int j = 0; j < baggPtr->getNumTypes(pl - 1); j++, k++) {
215-
m_players.push_back(new GamePlayerRep(this, k, baggPtr->getNumActions(pl - 1, j)));
215+
m_players.push_back(GamePlayerRep::CreatePlayer(this, k, baggPtr->getNumActions(pl - 1, j)));
216216
m_players.back()->m_label = std::to_string(k);
217217
agent2baggPlayer[k] = pl;
218218
std::for_each(m_players.back()->m_strategies.begin(), m_players.back()->m_strategies.end(),

src/games/gametable.cc

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ GameOutcome TablePureStrategyProfileRep::GetOutcome() const
8686

8787
void TablePureStrategyProfileRep::SetOutcome(GameOutcome p_outcome)
8888
{
89-
dynamic_cast<GameTableRep &>(*m_nfg).m_results[m_index] = std::shared_ptr<GameOutcomeRep>(p_outcome);
89+
dynamic_cast<GameTableRep &>(*m_nfg).m_results[m_index] =
90+
std::shared_ptr<GameOutcomeRep>(p_outcome);
9091
}
9192

9293
Rational TablePureStrategyProfileRep::GetPayoff(const GamePlayer &p_player) const
@@ -103,9 +104,8 @@ Rational TablePureStrategyProfileRep::GetPayoff(const GamePlayer &p_player) cons
103104
Rational TablePureStrategyProfileRep::GetStrategyValue(const GameStrategy &p_strategy) const
104105
{
105106
const auto &player = p_strategy->GetPlayer();
106-
auto outcome =
107-
dynamic_cast<GameTableRep &>(*m_nfg)
108-
.m_results[m_index - m_profile.at(player)->m_offset + p_strategy->m_offset];
107+
auto outcome = dynamic_cast<GameTableRep &>(*m_nfg)
108+
.m_results[m_index - m_profile.at(player)->m_offset + p_strategy->m_offset];
109109
if (outcome) {
110110
return outcome->GetPayoff<Rational>(player);
111111
}
@@ -246,8 +246,8 @@ template <class T>
246246
T TableMixedStrategyProfileRep<T>::GetPayoffDeriv(int pl, const GameStrategy &strategy1,
247247
const GameStrategy &strategy2) const
248248
{
249-
GamePlayerRep *player1 = strategy1->GetPlayer();
250-
GamePlayerRep *player2 = strategy2->GetPlayer();
249+
auto player1 = strategy1->GetPlayer();
250+
auto player2 = strategy2->GetPlayer();
251251
if (player1 == player2) {
252252
return T(0);
253253
}
@@ -269,7 +269,7 @@ GameTableRep::GameTableRep(const std::vector<int> &dim, bool p_sparseOutcomes /*
269269
: m_results(std::accumulate(dim.begin(), dim.end(), 1, std::multiplies<>()))
270270
{
271271
for (const auto &nstrat : dim) {
272-
m_players.push_back(new GamePlayerRep(this, m_players.size() + 1, nstrat));
272+
m_players.push_back(GamePlayerRep::CreatePlayer(this, m_players.size() + 1, nstrat));
273273
m_players.back()->m_label = lexical_cast<std::string>(m_players.size());
274274
std::for_each(
275275
m_players.back()->m_strategies.begin(), m_players.back()->m_strategies.end(),
@@ -279,8 +279,9 @@ GameTableRep::GameTableRep(const std::vector<int> &dim, bool p_sparseOutcomes /*
279279

280280
if (!p_sparseOutcomes) {
281281
m_outcomes = std::vector<std::shared_ptr<GameOutcomeRep>>(m_results.size());
282-
std::generate(m_outcomes.begin(), m_outcomes.end(),
283-
[this, outc = 1]() mutable { return std::make_shared<GameOutcomeRep>(this, outc++); });
282+
std::generate(m_outcomes.begin(), m_outcomes.end(), [this, outc = 1]() mutable {
283+
return std::make_shared<GameOutcomeRep>(this, outc++);
284+
});
284285
std::copy(m_outcomes.begin(), m_outcomes.end(), m_results.begin());
285286
}
286287
}
@@ -370,7 +371,7 @@ void GameTableRep::WriteNfgFile(std::ostream &p_file) const
370371
GamePlayer GameTableRep::NewPlayer()
371372
{
372373
IncrementVersion();
373-
auto player = new GamePlayerRep(this, m_players.size() + 1, 1);
374+
auto player = GamePlayerRep::CreatePlayer(this, m_players.size() + 1, 1);
374375
m_players.push_back(player);
375376
for (auto outcome : m_outcomes) {
376377
outcome->m_payoffs[player] = Number();
@@ -385,9 +386,10 @@ GamePlayer GameTableRep::NewPlayer()
385386
void GameTableRep::DeleteOutcome(const GameOutcome &p_outcome)
386387
{
387388
IncrementVersion();
388-
std::replace(m_results.begin(), m_results.end(),
389-
std::shared_ptr<GameOutcomeRep>(p_outcome), std::shared_ptr<GameOutcomeRep>());
390-
m_outcomes.erase(std::find(m_outcomes.begin(), m_outcomes.end(), std::shared_ptr<GameOutcomeRep>(p_outcome)));
389+
std::replace(m_results.begin(), m_results.end(), std::shared_ptr<GameOutcomeRep>(p_outcome),
390+
std::shared_ptr<GameOutcomeRep>());
391+
m_outcomes.erase(
392+
std::find(m_outcomes.begin(), m_outcomes.end(), std::shared_ptr<GameOutcomeRep>(p_outcome)));
391393
p_outcome->Invalidate();
392394
std::for_each(m_outcomes.begin(), m_outcomes.end(),
393395
[outc = 1](std::shared_ptr<GameOutcomeRep> c) mutable { c->m_number = outc++; });
@@ -411,7 +413,7 @@ GameStrategy GameTableRep::NewStrategy(const GamePlayer &p_player, const std::st
411413

412414
void GameTableRep::DeleteStrategy(const GameStrategy &p_strategy)
413415
{
414-
GamePlayerRep *player = p_strategy->GetPlayer();
416+
auto player = p_strategy->GetPlayer();
415417
if (player->m_game != this) {
416418
throw MismatchException();
417419
}

src/games/gametree.cc

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,8 @@ GameInfoset GameActionRep::GetInfoset() const { return m_infoset.lock(); }
152152
//========================================================================
153153

154154
std::shared_ptr<GameInfosetRep>
155-
GameInfosetRep::CreateInfoset(GameRep *p_efg, int p_number, GamePlayerRep *p_player, int p_actions)
155+
GameInfosetRep::CreateInfoset(GameRep *p_efg, int p_number,
156+
std::shared_ptr<GamePlayerRep> p_player, int p_actions)
156157
{
157158
auto infoset = std::make_shared<GameInfosetRep>();
158159
infoset->m_game = p_efg;
@@ -189,7 +190,7 @@ void GameTreeRep::SetPlayer(GameInfoset p_infoset, GamePlayer p_player)
189190
return;
190191
}
191192

192-
GamePlayerRep *oldPlayer = p_infoset->GetPlayer();
193+
auto oldPlayer = p_infoset->GetPlayer();
193194
IncrementVersion();
194195
oldPlayer->m_infosets.erase(std::find(oldPlayer->m_infosets.begin(), oldPlayer->m_infosets.end(),
195196
std::shared_ptr<GameInfosetRep>(p_infoset)));
@@ -564,7 +565,7 @@ GameInfoset GameTreeRep::LeaveInfoset(GameNode p_node)
564565
return oldInfoset;
565566
}
566567

567-
GamePlayerRep *player = oldInfoset->m_player;
568+
auto player = oldInfoset->m_player;
568569
RemoveMember(oldInfoset, node);
569570
node->m_infoset = GameInfosetRep::CreateInfoset(this, player->m_infosets.size() + 1, player,
570571
node->m_children.size());
@@ -813,7 +814,7 @@ void GameTreeRep::Canonicalize()
813814
NumberNodes(m_root, nodeindex);
814815

815816
for (size_t pl = 0; pl <= m_players.size(); pl++) {
816-
GamePlayerRep *player = (pl) ? m_players[pl - 1] : m_chance;
817+
auto player = (pl) ? m_players[pl - 1] : m_chance;
817818

818819
// Sort nodes within information sets according to ID.
819820
// Coded using a bubble sort for simplicity; large games might
@@ -992,7 +993,7 @@ int GameTreeRep::BehavProfileLength() const
992993
GamePlayer GameTreeRep::NewPlayer()
993994
{
994995
IncrementVersion();
995-
auto player = new GamePlayerRep(this, m_players.size() + 1);
996+
auto player = std::make_shared<GamePlayerRep>(this, m_players.size() + 1);
996997
m_players.push_back(player);
997998
for (auto &outcome : m_outcomes) {
998999
outcome->m_payoffs[player] = Number();

src/games/gametree.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class GameTreeRep : public GameExplicitRep {
3535
protected:
3636
mutable bool m_computedValues{false}, m_doCanon{true};
3737
GameNodeRep *m_root;
38-
GamePlayerRep *m_chance;
38+
std::shared_ptr<GamePlayerRep> m_chance;
3939
std::size_t m_numNodes = 1;
4040
std::size_t m_numNonterminalNodes = 0;
4141
std::map<GameNodeRep *, std::vector<GameNodeRep *>> m_nodePlays;

0 commit comments

Comments
 (0)