1+ import inspect
12from pathlib import Path
23from typing import Literal
34
@@ -37,6 +38,14 @@ def _extract_metadata_from_game(cls, game: Game) -> None:
3738 cls .title = game .title
3839 cls .num_players = len (game .players )
3940
41+ @classmethod
42+ def _extract_description_from_docstring (cls ) -> None :
43+ """Populate description from the class docstring."""
44+ if cls .__doc__ :
45+ cls .description = inspect .cleandoc (cls .__doc__ )
46+ else :
47+ cls .description = ""
48+
4049 def __init_subclass__ (cls , ** kwargs ):
4150 """Extract metadata when subclass is defined (if not a file-based game)."""
4251 super ().__init_subclass__ (** kwargs )
@@ -45,6 +54,9 @@ def __init_subclass__(cls, **kwargs):
4554 if cls .__name__ == "CatalogGameFromContrib" or issubclass (cls , CatalogGameFromContrib ):
4655 return
4756
57+ # Pull description from docstring
58+ cls ._extract_description_from_docstring ()
59+
4860 # For non-file-based games, create a temporary instance to extract metadata
4961 try :
5062 temp_game = cls ._game ()
@@ -94,6 +106,9 @@ def __init_subclass__(cls, **kwargs):
94106 if not hasattr (cls , "game_file" ) or cls .game_file is None :
95107 raise TypeError (f"{ cls .__name__ } must define 'game_file' class attribute" )
96108
109+ # Pull description from docstring
110+ cls ._extract_description_from_docstring ()
111+
97112 # Load game and extract metadata immediately when class is defined
98113 cls ._cached_game = cls ._load_game ()
99114 cls ._extract_metadata_from_game (cls ._cached_game )
@@ -143,14 +158,18 @@ def get_all_subclasses(cls):
143158
144159
145160class PrisonersDilemma (CatalogGameFromContrib ):
161+ """
162+ Prisoner's Dilemma game.
163+ """
146164 game_file = "pd.nfg"
147- description = "Prisoner's Dilemma game."
148165 citation = "Example citation for Prisoner's Dilemma."
149166
150167
151168class TwoStageMatchingPennies (CatalogGameFromContrib ):
169+ """
170+ Two-Stage Matching Pennies game.
171+ """
152172 game_file = "2smp.efg"
153- description = "Two-Stage Matching Pennies game."
154173 citation = "Example citation for Two-Stage Matching Pennies."
155174
156175
@@ -160,14 +179,14 @@ class TwoStageMatchingPennies(CatalogGameFromContrib):
160179
161180
162181class OneShotTrust (CatalogGame ):
163- game_type = "efg"
164- description = """
182+ """
165183 The unique_NE_variant makes Trust a dominant strategy, replacing the
166184 non-singleton equilibrium component from the standard version of the game
167185 where the Buyer plays "Not Trust" and the seller can play any mixture with
168186 < 0.5 probability on Honor with a unique NE where the Buyer plays Trust and
169187 the Seller plays Abuse.
170188 """
189+ game_type = "efg"
171190 citation = "Kreps (1990)"
172191
173192 @staticmethod
0 commit comments