@@ -92,160 +92,160 @@ def __init_subclass__(cls, **kwargs):
9292 cls ._extract_description (cls .game )
9393
9494
95- def games (
96- num_actions : int | None = None ,
97- num_contingencies : int | None = None ,
98- num_infosets : int | None = None ,
99- is_const_sum : bool | None = None ,
100- is_perfect_recall : bool | None = None ,
101- is_tree : bool | None = None ,
102- num_nodes : int | None = None ,
103- num_outcomes : int | None = None ,
104- num_players : int | None = None ,
105- num_strategies : int | None = None ,
106- ** metadata_filters ,
107- ) -> list [str ]:
108- """
109- Return a list of catalog game class names.
110-
111- Parameters
112- ----------
113- num_actions : int | None, default None
114- If specified, only return games with the given number of actions.
115- num_contingencies : int | None, default None
116- If specified, only return games with the given number of contingencies.
117- num_infosets : int | None, default None
118- If specified, only return games with the given number of information sets.
119- is_const_sum : bool | None, default None
120- If specified, only return games that are (or are not) constant-sum.
121- is_perfect_recall : bool | None, default None
122- If specified, only return games that have (or do not have) perfect recall.
123- is_tree : bool | None, default None
124- If specified, only return games that are (or are not) extensive-form.
125- num_nodes : int | None, default None
126- If specified, only return games with the given number of nodes.
127- num_outcomes : int | None, default None
128- If specified, only return games with the given number of outcomes.
129- num_strategies : int | None, default None
130- If specified, only return games with the given number of strategies.
131- num_players : int | None, default None
132- If specified, only return games with the given number of players.
133- **metadata_filters
134- Additional keyword arguments to filter by catalog.yml metadata fields.
135- For example, `x=1` filters for games with `x: 1` in metadata.
136-
137- Returns
138- -------
139- list[str]
140- List of game class names matching the specified filters.
141-
142- Examples
143- --------
144- >>> games(x=1) # Games with a custom metadata field 'x' equal to 1
145- >>> games(is_tree=True, num_players=2) # 2-player extensive-form games
146- """
147- # Import manually coded games to ensure they are registered in the catalog
148- # _load_coded_games()
149-
150- # Filter by extensive-form if filtering by tree-specific attributes
151- if (
152- num_actions is not None or
153- num_infosets is not None or
154- num_nodes is not None
155- ):
156- is_tree = True
157-
158- def get_all_subclasses (cls ):
159- """Recursively get all subclasses."""
160- all_subclasses = []
161- for subclass in cls .__subclasses__ ():
162-
163- # Don't include CatalogGameFromContrib in result
164- if subclass .__name__ in ["CatalogGameFromContrib" ]:
165- all_subclasses .extend (get_all_subclasses (subclass ))
166- continue
167-
168- if is_tree is not None and is_tree != subclass .game .is_tree :
169- all_subclasses .extend (get_all_subclasses (subclass ))
170- continue
171-
172- if num_actions is not None :
173- if not getattr (subclass .game , "is_tree" , False ):
174- all_subclasses .extend (get_all_subclasses (subclass ))
175- continue
176- if num_actions != len (getattr (subclass .game , "actions" , [])):
177- all_subclasses .extend (get_all_subclasses (subclass ))
178- continue
179-
180- if num_infosets is not None :
181- if not getattr (subclass .game , "is_tree" , False ):
182- all_subclasses .extend (get_all_subclasses (subclass ))
183- continue
184- if num_infosets != len (subclass .game .infosets ):
185- all_subclasses .extend (get_all_subclasses (subclass ))
186- continue
187-
188- if num_nodes is not None :
189- if not getattr (subclass .game , "is_tree" , False ):
190- all_subclasses .extend (get_all_subclasses (subclass ))
191- continue
192- if num_nodes != len (subclass .game .nodes ):
193- all_subclasses .extend (get_all_subclasses (subclass ))
194- continue
195-
196- if (
197- num_contingencies is not None
198- and num_contingencies != len (subclass .game .contingencies )
199- ):
200- all_subclasses .extend (get_all_subclasses (subclass ))
201- continue
202-
203- if is_const_sum is not None and is_const_sum != subclass .game .is_const_sum :
204- all_subclasses .extend (get_all_subclasses (subclass ))
205- continue
206-
207- if (
208- is_perfect_recall is not None
209- and is_perfect_recall != subclass .game .is_perfect_recall
210- ):
211- all_subclasses .extend (get_all_subclasses (subclass ))
212- continue
213-
214- if (
215- num_outcomes is not None
216- and num_outcomes != len (subclass .game .outcomes )
217- ):
218- all_subclasses .extend (get_all_subclasses (subclass ))
219- continue
220-
221- if (
222- num_strategies is not None
223- and num_strategies != len (subclass .game .strategies )
224- ):
225- all_subclasses .extend (get_all_subclasses (subclass ))
226- continue
227-
228- if (
229- num_players is not None
230- and num_players != len (subclass .game .players )
231- ):
232- all_subclasses .extend (get_all_subclasses (subclass ))
233- continue
234-
235- # Check metadata filters
236- metadata_match = True
237- for key , value in metadata_filters .items ():
238- if not hasattr (subclass , key ) or getattr (subclass , key ) != value :
239- metadata_match = False
240- break
241-
242- if metadata_match :
243- all_subclasses .append (subclass .__name__ )
244-
245- all_subclasses .extend (get_all_subclasses (subclass ))
246- return all_subclasses
247- # Sort alphabetically for consistency
248- return sorted (get_all_subclasses (CatalogGame ))
95+ # def games(
96+ # num_actions: int | None = None,
97+ # num_contingencies: int | None = None,
98+ # num_infosets: int | None = None,
99+ # is_const_sum: bool | None = None,
100+ # is_perfect_recall: bool | None = None,
101+ # is_tree: bool | None = None,
102+ # num_nodes: int | None = None,
103+ # num_outcomes: int | None = None,
104+ # num_players: int | None = None,
105+ # num_strategies: int | None = None,
106+ # **metadata_filters,
107+ # ) -> list[str]:
108+ # """
109+ # Return a list of catalog game class names.
110+
111+ # Parameters
112+ # ----------
113+ # num_actions : int | None, default None
114+ # If specified, only return games with the given number of actions.
115+ # num_contingencies : int | None, default None
116+ # If specified, only return games with the given number of contingencies.
117+ # num_infosets : int | None, default None
118+ # If specified, only return games with the given number of information sets.
119+ # is_const_sum : bool | None, default None
120+ # If specified, only return games that are (or are not) constant-sum.
121+ # is_perfect_recall : bool | None, default None
122+ # If specified, only return games that have (or do not have) perfect recall.
123+ # is_tree : bool | None, default None
124+ # If specified, only return games that are (or are not) extensive-form.
125+ # num_nodes : int | None, default None
126+ # If specified, only return games with the given number of nodes.
127+ # num_outcomes : int | None, default None
128+ # If specified, only return games with the given number of outcomes.
129+ # num_strategies : int | None, default None
130+ # If specified, only return games with the given number of strategies.
131+ # num_players : int | None, default None
132+ # If specified, only return games with the given number of players.
133+ # **metadata_filters
134+ # Additional keyword arguments to filter by catalog.yml metadata fields.
135+ # For example, `x=1` filters for games with `x: 1` in metadata.
136+
137+ # Returns
138+ # -------
139+ # list[str]
140+ # List of game class names matching the specified filters.
141+
142+ # Examples
143+ # --------
144+ # >>> games(x=1) # Games with a custom metadata field 'x' equal to 1
145+ # >>> games(is_tree=True, num_players=2) # 2-player extensive-form games
146+ # """
147+ # # Import manually coded games to ensure they are registered in the catalog
148+ # # _load_coded_games()
149+
150+ # # Filter by extensive-form if filtering by tree-specific attributes
151+ # if (
152+ # num_actions is not None or
153+ # num_infosets is not None or
154+ # num_nodes is not None
155+ # ):
156+ # is_tree = True
157+
158+ # def get_all_subclasses(cls):
159+ # """Recursively get all subclasses."""
160+ # all_subclasses = []
161+ # for subclass in cls.__subclasses__():
162+
163+ # # Don't include CatalogGameFromContrib in result
164+ # if subclass.__name__ in ["CatalogGameFromContrib"]:
165+ # all_subclasses.extend(get_all_subclasses(subclass))
166+ # continue
167+
168+ # if is_tree is not None and is_tree != subclass.game.is_tree:
169+ # all_subclasses.extend(get_all_subclasses(subclass))
170+ # continue
171+
172+ # if num_actions is not None:
173+ # if not getattr(subclass.game, "is_tree", False):
174+ # all_subclasses.extend(get_all_subclasses(subclass))
175+ # continue
176+ # if num_actions != len(getattr(subclass.game, "actions", [])):
177+ # all_subclasses.extend(get_all_subclasses(subclass))
178+ # continue
179+
180+ # if num_infosets is not None:
181+ # if not getattr(subclass.game, "is_tree", False):
182+ # all_subclasses.extend(get_all_subclasses(subclass))
183+ # continue
184+ # if num_infosets != len(subclass.game.infosets):
185+ # all_subclasses.extend(get_all_subclasses(subclass))
186+ # continue
187+
188+ # if num_nodes is not None:
189+ # if not getattr(subclass.game, "is_tree", False):
190+ # all_subclasses.extend(get_all_subclasses(subclass))
191+ # continue
192+ # if num_nodes != len(subclass.game.nodes):
193+ # all_subclasses.extend(get_all_subclasses(subclass))
194+ # continue
195+
196+ # if (
197+ # num_contingencies is not None
198+ # and num_contingencies != len(subclass.game.contingencies)
199+ # ):
200+ # all_subclasses.extend(get_all_subclasses(subclass))
201+ # continue
202+
203+ # if is_const_sum is not None and is_const_sum != subclass.game.is_const_sum:
204+ # all_subclasses.extend(get_all_subclasses(subclass))
205+ # continue
206+
207+ # if (
208+ # is_perfect_recall is not None
209+ # and is_perfect_recall != subclass.game.is_perfect_recall
210+ # ):
211+ # all_subclasses.extend(get_all_subclasses(subclass))
212+ # continue
213+
214+ # if (
215+ # num_outcomes is not None
216+ # and num_outcomes != len(subclass.game.outcomes)
217+ # ):
218+ # all_subclasses.extend(get_all_subclasses(subclass))
219+ # continue
220+
221+ # if (
222+ # num_strategies is not None
223+ # and num_strategies != len(subclass.game.strategies)
224+ # ):
225+ # all_subclasses.extend(get_all_subclasses(subclass))
226+ # continue
227+
228+ # if (
229+ # num_players is not None
230+ # and num_players != len(subclass.game.players)
231+ # ):
232+ # all_subclasses.extend(get_all_subclasses(subclass))
233+ # continue
234+
235+ # # Check metadata filters
236+ # metadata_match = True
237+ # for key, value in metadata_filters.items():
238+ # if not hasattr(subclass, key) or getattr(subclass, key) != value:
239+ # metadata_match = False
240+ # break
241+
242+ # if metadata_match:
243+ # all_subclasses.append(subclass.__name__)
244+
245+ # all_subclasses.extend(get_all_subclasses(subclass))
246+ # return all_subclasses
247+ # # Sort alphabetically for consistency
248+ # return sorted(get_all_subclasses(CatalogGame))
249249
250250
251251# _CATALOG_YAML = Path(__file__).parent / "catalog.yml"
0 commit comments