1313
1414
1515def main () -> None :
16- """Main CLI entry point for balatrollm."""
16+ """Main CLI entry point for balatrollm.
17+
18+ Parses command line arguments and executes the appropriate command.
19+ Supports both the main balatrollm command and benchmark subcommand.
20+ """
1721 parser = _create_argument_parser ()
1822 args = parser .parse_args ()
1923
@@ -30,7 +34,18 @@ def main() -> None:
3034
3135
3236async def cmd_balatrollm (args ) -> None :
33- """Run the balatrollm command."""
37+ """Run the balatrollm command.
38+
39+ Creates a bot configuration and runs the main game loop.
40+
41+ Args:
42+ args: Parsed command line arguments containing model, strategy,
43+ base_url, api_key, config file path, runs count, and other options.
44+ """
45+ # Validate runs argument
46+ if args .runs < 1 :
47+ print ("Error: --runs must be at least 1" )
48+ sys .exit (1 )
3449
3550 if args .config :
3651 config = Config .from_config_file (args .config )
@@ -48,13 +63,42 @@ async def cmd_balatrollm(args) -> None:
4863 print (model )
4964 return
5065
51- else :
52- with bot :
53- await bot .play_game ()
66+ # Run the bot multiple times
67+ for run_number in range (1 , args .runs + 1 ):
68+ if args .runs > 1 :
69+ print (f"\n === Run { run_number } /{ args .runs } ===" )
70+
71+ try :
72+ with bot :
73+ await bot .play_game (runs_dir = args .runs_dir )
74+ except KeyboardInterrupt :
75+ print (f"\n Interrupted after { run_number - 1 } completed runs" )
76+ break
77+ except Exception as e :
78+ print (f"Run { run_number } failed: { e } " )
79+ if args .runs > 1 :
80+ print ("Continuing to next run..." )
81+ else :
82+ raise
83+
84+ # Sleep between runs to prevent errors
85+ if run_number < args .runs :
86+ print ("Waiting 3 seconds before next run..." )
87+ await asyncio .sleep (3 )
5488
5589
5690def cmd_benchmark (args ) -> None :
57- """Run the benchmark command."""
91+ """Run the benchmark command.
92+
93+ Analyzes run data and generates comprehensive leaderboards.
94+
95+ Args:
96+ args: Parsed command line arguments containing runs_dir and output_dir.
97+
98+ Raises:
99+ FileNotFoundError: If the runs directory doesn't exist.
100+ Exception: If benchmark analysis fails for any other reason.
101+ """
58102 try :
59103 run_benchmark_analysis (args .runs_dir , args .output_dir )
60104 except FileNotFoundError as e :
@@ -66,7 +110,14 @@ def cmd_benchmark(args) -> None:
66110
67111
68112def _create_argument_parser () -> argparse .ArgumentParser :
69- """Create and configure argument parser."""
113+ """Create and configure argument parser.
114+
115+ Sets up command line argument parsing for both the main balatrollm
116+ command and the benchmark subcommand.
117+
118+ Returns:
119+ Configured ArgumentParser instance with all commands and options.
120+ """
70121 parser = argparse .ArgumentParser (
71122 description = "LLM-powered Balatro bot using LiteLLM proxy" ,
72123 formatter_class = argparse .RawDescriptionHelpFormatter ,
@@ -106,6 +157,18 @@ def _create_argument_parser() -> argparse.ArgumentParser:
106157 "--config" ,
107158 help = "Load configuration from a previous run's config.json file" ,
108159 )
160+ parser .add_argument (
161+ "--runs-dir" ,
162+ type = lambda p : Path (p ).resolve (),
163+ default = Path .cwd ().resolve (),
164+ help = "Base directory for storing run data (default: current directory)" ,
165+ )
166+ parser .add_argument (
167+ "--runs" ,
168+ type = int ,
169+ default = 1 ,
170+ help = "Number of times to run the bot with the same configuration (default: 1)" ,
171+ )
109172
110173 # Benchmark subcommand
111174 benchmark_parser = subparsers .add_parser (
@@ -115,8 +178,8 @@ def _create_argument_parser() -> argparse.ArgumentParser:
115178 )
116179 benchmark_parser .add_argument (
117180 "--runs-dir" ,
118- type = Path ,
119- default = Path ("runs" ),
181+ type = lambda p : Path ( p ). resolve () ,
182+ default = Path ("runs" ). resolve () ,
120183 help = "Directory containing run data (default: runs)" ,
121184 )
122185 benchmark_parser .add_argument (
0 commit comments