@@ -967,122 +967,66 @@ class GameRep : public std::enable_shared_from_this<GameRep> {
967967 virtual void BuildComputedValues () const {}
968968};
969969
970- #include < assert.h>
971-
972970class GameRep ::Infosets {
973971public:
974972 class iterator {
975973 public:
976- using iterator_category = std::forward_iterator_tag; // diagnostic: proper category
974+ using iterator_category = std::forward_iterator_tag;
977975 using value_type = GameInfoset;
978976 using difference_type = std::ptrdiff_t ;
979- using pointer = value_type * ;
980- using reference = value_type & ;
977+ using pointer = value_type;
978+ using reference = value_type;
981979
982980 using outer_iter = std::vector<std::shared_ptr<GamePlayerRep>>::const_iterator;
983981 using inner_iter = std::vector<std::shared_ptr<GameInfosetRep>>::const_iterator;
984982
985- iterator () : owner_id_( 0 ), players_( nullptr ) {}
983+ iterator () = default ;
986984
987- iterator (outer_iter outer, outer_iter outer_end,
988- const std::vector<std::shared_ptr<GamePlayerRep>> *players, std::size_t owner_id)
989- : outer_(outer), outer_end_(outer_end), players_(players), owner_id_(owner_id)
985+ iterator (std::shared_ptr<GameRep> game, outer_iter outer, outer_iter outer_end)
986+ : game_(std::move(game)), outer_(outer), outer_end_(outer_end)
990987 {
991- // ------ DIAGNOSTICS ----------------------------------------------------
992-
993- // Detect dangling players pointer
994- assert (players_ != nullptr && " Infosets iterator constructed with null players pointer." );
995-
996- // Detect begin()==end() but outer mismatch
997- if (outer_ == outer_end_) {
998- assert (inner_ == inner_end_ && " Inner iterators must be empty for end iterator." );
999- }
1000-
1001988 if (outer_ != outer_end_) {
1002989 init_inner ();
1003990 satisfy_invariant ();
1004991 }
1005992 }
1006993
1007- // -------------------------------------------------------------------------
1008- // Dereference
1009- // -------------------------------------------------------------------------
1010994 value_type operator *() const
1011995 {
1012- assert (players_ != nullptr );
1013- assert (!is_end () && " Dereferencing end iterator!" );
1014-
1015- // Check many possible UB causes
1016- assert (inner_ != inner_end_ && " Inner iterator invalid during dereference." );
1017- assert (valid_owner () &&
1018- " Iterator used after view destruction or copying from different view." );
1019-
1020- // Additional optional check: ensure GameInfoset is safe to construct
1021- // You can instrument your GameInfoset(value_type) here to assert its invariants.
1022-
1023- return *inner_;
996+ return GameInfoset (*inner_); // GameObjectPtr constructor
1024997 }
1025998
1026- value_type operator ->() const { return operator *( ); }
999+ value_type operator ->() const { return GameInfoset (*inner_ ); }
10271000
1028- // -------------------------------------------------------------------------
1029- // Increment
1030- // -------------------------------------------------------------------------
10311001 iterator &operator ++()
10321002 {
1033- assert (players_ != nullptr );
1034- assert (!is_end () && " Incrementing end iterator!" );
1035-
10361003 ++inner_;
10371004 satisfy_invariant ();
10381005 return *this ;
10391006 }
10401007
1041- // -------------------------------------------------------------------------
1042- // Equality / Inequality
1043- // -------------------------------------------------------------------------
10441008 bool operator ==(const iterator &other) const
10451009 {
1046- // Detect comparing iterators from different views
1047- if (owner_id_ != other.owner_id_ ) {
1048- assert (false && " Comparing iterators from different Infosets views!" );
1049- }
1050-
1051- // Both end iterators must compare equal
1052- if (is_end () && other.is_end ()) {
1010+ // Compare end iterators correctly
1011+ if (outer_ == outer_end_ && other.outer_ == other.outer_end_ ) {
10531012 return true ;
10541013 }
10551014
1056- // Detect illegal comparisons
1057- assert (players_ == other.players_ &&
1058- " Comparing iterators belonging to different container instances!" );
1059-
10601015 return outer_ == other.outer_ && inner_ == other.inner_ ;
10611016 }
10621017
10631018 bool operator !=(const iterator &other) const { return !(*this == other); }
10641019
10651020 private:
1066- // -------------------------------------------------------------------------
1067- // Helpers
1068- // -------------------------------------------------------------------------
10691021 bool is_end () const { return outer_ == outer_end_; }
10701022
1071- bool valid_owner () const { return players_ != nullptr && owner_id_ != 0 ; }
1072-
1073- // Initialize inner iter safely
10741023 void init_inner ()
10751024 {
1076- const auto &playerPtr = *outer_;
1077-
1078- // Check for null shared_ptr (VERY COMMON SOURCE OF UB)
1079- assert (playerPtr && " Null shared_ptr<GamePlayerRep> inside m_players!" );
1080-
1081- inner_ = playerPtr->m_infosets .begin ();
1082- inner_end_ = playerPtr->m_infosets .end ();
1025+ const auto &player = *outer_;
1026+ inner_ = player->m_infosets .begin ();
1027+ inner_end_ = player->m_infosets .end ();
10831028 }
10841029
1085- // Advance to next non-empty inner range
10861030 void satisfy_invariant ()
10871031 {
10881032 while (!is_end () && inner_ == inner_end_) {
@@ -1093,48 +1037,34 @@ class GameRep::Infosets {
10931037 }
10941038 }
10951039
1096- // -------------------------------------------------------------------------
1097- // Data members
1098- // -------------------------------------------------------------------------
1040+ // HOLD GAME ALIVE
1041+ std::shared_ptr<GameRep> game_;
1042+
10991043 outer_iter outer_{};
11001044 outer_iter outer_end_{};
11011045 inner_iter inner_{};
11021046 inner_iter inner_end_{};
1103-
1104- const std::vector<std::shared_ptr<GamePlayerRep>> *players_ = nullptr ;
1105-
1106- // Unique stamp to detect view lifetime/dangling iterator
1107- std::size_t owner_id_ = 0 ;
11081047 };
11091048
1110- // -------------------------------------------------------------------------
1111- // View interface
1112- // -------------------------------------------------------------------------
1113- iterator begin () const
1049+ // Construct a view storing a strong reference to the GameRep
1050+ explicit Infosets (std::shared_ptr<GameRep> game)
1051+ : game_(std::move(game)), players_(&game_->m_players)
11141052 {
1115- return iterator (players_->begin (), players_->end (), players_, owner_id_);
11161053 }
11171054
1118- iterator end () const { return iterator (players_->end (), players_->end (), players_, owner_id_ ); }
1055+ iterator begin () const { return iterator (game_, players_->begin (), players_->end ()); }
11191056
1120- explicit Infosets (const GameRep *game) : players_(&game->m_players)
1121- {
1122- assert (game != nullptr );
1123- owner_id_ = next_owner_id (); // unique ID for detecting illegal comparisons
1124- }
1057+ iterator end () const { return iterator (game_, players_->end (), players_->end ()); }
11251058
11261059private:
1060+ std::shared_ptr<GameRep> game_;
11271061 const std::vector<std::shared_ptr<GamePlayerRep>> *players_;
1128- std::size_t owner_id_;
1129-
1130- static std::size_t next_owner_id ()
1131- {
1132- static std::size_t id = 1 ;
1133- return id++;
1134- }
11351062};
11361063
1137- inline GameRep::Infosets GameRep::GetInfosets () const { return Infosets (this ); }
1064+ inline GameRep::Infosets GameRep::GetInfosets () const
1065+ {
1066+ return Infosets (std::const_pointer_cast<GameRep>(this ->shared_from_this ()));
1067+ }
11381068
11391069// =======================================================================
11401070// Inline members of game representation classes
0 commit comments