Skip to content
Closed
Show file tree
Hide file tree
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
2 changes: 2 additions & 0 deletions src/games/game.cc
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ size_t GamePlayerRep::NumSequences() const
// class GameRep
//========================================================================

GamePlayer GameRep::GetPlayer(int pl) const { return m_players.at(pl - 1); }

Array<GamePlayer> GameRep::GetPlayers() const
{
Array<GamePlayer> ret(NumPlayers());
Expand Down
3 changes: 2 additions & 1 deletion src/games/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ class GameRep : public BaseGameRep {
template <class T> friend class TableMixedStrategyProfileRep;

protected:
std::vector<GamePlayerRep *> m_players;
std::string m_title, m_comment;
unsigned int m_version{0};

Expand Down Expand Up @@ -535,7 +536,7 @@ class GameRep : public BaseGameRep {
/// Returns the number of players in the game
virtual size_t NumPlayers() const = 0;
/// Returns the pl'th player in the game
virtual GamePlayer GetPlayer(int pl) const = 0;
GamePlayer GetPlayer(int pl) const;
/// Returns the set of players in the game
virtual Array<GamePlayer> GetPlayers() const;
/// Returns the chance (nature) player
Expand Down
12 changes: 6 additions & 6 deletions src/games/gameagg.cc
Original file line number Diff line number Diff line change
Expand Up @@ -201,20 +201,20 @@ Game GameAGGRep::Copy() const
Array<int> GameAGGRep::NumStrategies() const
{
Array<int> ns;
for (int pl = 1; pl <= aggPtr->getNumPlayers(); pl++) {
ns.push_back(m_players[pl]->NumStrategies());
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is a good opportunity to modernise code by avoiding the use of indices altogether:

for (const auto &player : m_players) {
  ns.push_back(player->NumStrategies());
}

for (const auto &player : m_players) {
ns.push_back(player->NumStrategies());
}
return ns;
}

GameStrategy GameAGGRep::GetStrategy(int p_index) const
{
for (int pl = 1; pl <= aggPtr->getNumPlayers(); pl++) {
if (static_cast<int>(m_players[pl]->NumStrategies()) >= p_index) {
return m_players[pl]->GetStrategy(p_index);
for (const auto &player : m_players) {
if (static_cast<int>(player->NumStrategies()) >= p_index) {
return player->GetStrategy(p_index);
}
else {
p_index -= m_players[pl]->NumStrategies();
p_index -= player->NumStrategies();
}
}
throw IndexException();
Expand Down
3 changes: 0 additions & 3 deletions src/games/gameagg.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ class GameAGGRep : public GameRep {

private:
std::shared_ptr<agg::AGG> aggPtr;
Array<GamePlayerRep *> m_players;

public:
/// @name Lifecycle
Expand Down Expand Up @@ -77,8 +76,6 @@ class GameAGGRep : public GameRep {
//@{
/// Returns the number of players in the game
size_t NumPlayers() const override { return aggPtr->getNumPlayers(); }
/// Returns the pl'th player in the game
GamePlayer GetPlayer(int pl) const override { return m_players[pl]; }
/// Returns the chance (nature) player
GamePlayer GetChance() const override { throw UndefinedException(); }
/// Creates a new player in the game, with no moves
Expand Down
10 changes: 5 additions & 5 deletions src/games/gamebagg.cc
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ GameBAGGRep::GameBAGGRep(std::shared_ptr<agg::BAGG> _baggPtr)
for (int pl = 1; pl <= baggPtr->getNumPlayers(); pl++) {
for (int j = 0; j < baggPtr->getNumTypes(pl - 1); j++, k++) {
m_players.push_back(new GamePlayerRep(this, k, baggPtr->getNumActions(pl - 1, j)));
m_players[k]->m_label = lexical_cast<std::string>(k);
m_players.back()->m_label = std::to_string(k);
agent2baggPlayer[k] = pl;
std::for_each(m_players.back()->m_strategies.begin(), m_players.back()->m_strategies.end(),
[st = 1](GameStrategyRep *s) mutable { s->SetLabel(std::to_string(st++)); });
Expand All @@ -236,17 +236,17 @@ Game GameBAGGRep::Copy() const
Array<int> GameBAGGRep::NumStrategies() const
{
Array<int> ns;
for (size_t pl = 1; pl <= NumPlayers(); pl++) {
ns.push_back(m_players[pl]->m_strategies.size());
for (const auto &player : m_players) {
ns.push_back(player->m_strategies.size());
}
return ns;
}

int GameBAGGRep::MixedProfileLength() const
{
int res = 0;
for (size_t pl = 1; pl <= NumPlayers(); pl++) {
res += m_players[pl]->m_strategies.size();
for (const auto &player : m_players) {
res += player->m_strategies.size();
}
return res;
}
Expand Down
3 changes: 0 additions & 3 deletions src/games/gamebagg.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ class GameBAGGRep : public GameRep {
private:
std::shared_ptr<agg::BAGG> baggPtr;
Array<int> agent2baggPlayer;
Array<GamePlayerRep *> m_players;

public:
/// @name Lifecycle
Expand Down Expand Up @@ -78,8 +77,6 @@ class GameBAGGRep : public GameRep {
//@{
/// Returns the number of players in the game
size_t NumPlayers() const override { return m_players.size(); }
/// Returns the pl'th player in the game
GamePlayer GetPlayer(int pl) const override { return m_players[pl]; }
/// Returns the chance (nature) player
GamePlayer GetChance() const override { throw UndefinedException(); }
/// Creates a new player in the game, with no moves
Expand Down
6 changes: 3 additions & 3 deletions src/games/gameexpl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ Rational GameExplicitRep::GetMaxPayoff(const GamePlayer &p_player) const
Array<int> GameExplicitRep::NumStrategies() const
{
const_cast<GameExplicitRep *>(this)->BuildComputedValues();
Array<int> dim(m_players.size());
for (size_t pl = 1; pl <= m_players.size(); pl++) {
dim[pl] = m_players[pl]->m_strategies.size();
Array<int> dim;
for (const auto &player : m_players) {
dim.push_back(player->m_strategies.size());
}
return dim;
}
Expand Down
3 changes: 0 additions & 3 deletions src/games/gameexpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ class GameExplicitRep : public GameRep {
template <class T> friend class MixedStrategyProfile;

protected:
Array<GamePlayerRep *> m_players;
Array<GameOutcomeRep *> m_outcomes;

public:
Expand Down Expand Up @@ -69,8 +68,6 @@ class GameExplicitRep : public GameRep {
//@{
/// Returns the number of players in the game
size_t NumPlayers() const override { return m_players.size(); }
/// Returns the pl'th player in the game
GamePlayer GetPlayer(int pl) const override { return m_players[pl]; }
//@}

/// @name Outcomes
Expand Down
2 changes: 1 addition & 1 deletion src/games/gametree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -808,7 +808,7 @@ void GameTreeRep::Canonicalize()
NumberNodes(m_root, nodeindex);

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

// Sort nodes within information sets according to ID.
// Coded using a bubble sort for simplicity; large games might
Expand Down
6 changes: 6 additions & 0 deletions tests/test_players.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,14 @@ def test_player_index_by_string():

def test_player_index_out_of_range():
game = gbt.Game.new_table([2, 2])
print(f"Number of players: {len(game.players)}")
assert len(game.players) == 2
with pytest.raises(IndexError):
_ = game.players[2]
with pytest.raises(IndexError):
_ = game.players[3]
with pytest.raises(IndexError):
_ = game.players[-1]


def test_player_index_invalid():
Expand Down