Skip to content

Commit c7293cc

Browse files
committed
Attempt to Windows-proof common MSVC issues.
1 parent 7a5cabf commit c7293cc

File tree

2 files changed

+36
-13
lines changed

2 files changed

+36
-13
lines changed

src/games/game.h

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -985,8 +985,7 @@ class GameRep::Infosets {
985985
iterator(outer_iter outer, outer_iter outer_end) : outer_(outer), outer_end_(outer_end)
986986
{
987987
if (outer_ != outer_end_) {
988-
inner_ = (*outer_)->m_infosets.begin();
989-
inner_end_ = (*outer_)->m_infosets.end();
988+
init_inner();
990989
satisfy_invariant();
991990
}
992991
}
@@ -1001,21 +1000,44 @@ class GameRep::Infosets {
10011000
return *this;
10021001
}
10031002

1003+
// -------- Windows/MSVC-safe equality ----------
10041004
bool operator==(const iterator &other) const
10051005
{
1006-
return outer_ == other.outer_ && (outer_ == outer_end_ || inner_ == other.inner_);
1006+
// Both are end() ⇒ equal
1007+
if (is_end() && other.is_end()) {
1008+
return true;
1009+
}
1010+
1011+
// Otherwise, must match outer + inner (safe because both non-end)
1012+
return outer_ == other.outer_ && inner_ == other.inner_;
10071013
}
10081014

10091015
bool operator!=(const iterator &other) const { return !(*this == other); }
10101016

10111017
private:
1018+
bool is_end() const { return outer_ == outer_end_; }
1019+
1020+
// Safe initialization even when shared_ptr is null
1021+
void init_inner()
1022+
{
1023+
const auto &playerPtr = *outer_;
1024+
1025+
if (!playerPtr) {
1026+
// Null shared_ptr → no infosets
1027+
inner_ = inner_end_ = inner_iter{};
1028+
return;
1029+
}
1030+
1031+
inner_ = playerPtr->m_infosets.begin();
1032+
inner_end_ = playerPtr->m_infosets.end();
1033+
}
1034+
10121035
void satisfy_invariant()
10131036
{
1014-
while (outer_ != outer_end_ && inner_ == inner_end_) {
1037+
while (!is_end() && inner_ == inner_end_) {
10151038
++outer_;
1016-
if (outer_ != outer_end_) {
1017-
inner_ = (*outer_)->m_infosets.begin();
1018-
inner_end_ = (*outer_)->m_infosets.end();
1039+
if (!is_end()) {
1040+
init_inner();
10191041
}
10201042
}
10211043
}
@@ -1027,14 +1049,16 @@ class GameRep::Infosets {
10271049
};
10281050

10291051
// View interface
1030-
iterator begin() const { return {players_.begin(), players_.end()}; }
1052+
iterator begin() const { return iterator(players_->begin(), players_->end()); }
1053+
iterator end() const { return iterator(players_->end(), players_->end()); }
10311054

1032-
iterator end() const { return {players_.end(), players_.end()}; }
1033-
1034-
explicit Infosets(const GameRep *game) : players_(game->m_players) {}
1055+
explicit Infosets(const GameRep *game)
1056+
: players_(&game->m_players) // ✔ store pointer, not reference
1057+
{
1058+
}
10351059

10361060
private:
1037-
const std::vector<std::shared_ptr<GamePlayerRep>> &players_;
1061+
const std::vector<std::shared_ptr<GamePlayerRep>> *players_;
10381062
};
10391063

10401064
inline GameRep::Infosets GameRep::GetInfosets() const { return Infosets(this); }

tests/test_actions.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,6 @@ def test_strategy_action_raises_value_error_for_wrong_player(game, player_ind, i
231231
def test_strategy_action_raises_error_for_strategic_game():
232232
"""Verify `Strategy.action` retrieves the action prescribed by the strategy
233233
"""
234-
return
235234
game_efg = games.read_from_file("e02.efg")
236235
game_nfg = game_efg.from_arrays(game_efg.to_arrays()[0], game_efg.to_arrays()[1])
237236
alice = game_nfg.players[0]

0 commit comments

Comments
 (0)