Some checks failed
Build Simulation and Test / Run All Tests (push) Failing after 14m52s
200 lines
6.8 KiB
Python
200 lines
6.8 KiB
Python
#!/usr/bin/env python3
|
|
"""Headless simulation entry point - runs simulations without UI."""
|
|
|
|
import sys
|
|
import argparse
|
|
from pathlib import Path
|
|
|
|
# Add project root to path
|
|
project_root = Path(__file__).parent.parent
|
|
sys.path.insert(0, str(project_root))
|
|
|
|
from config import ConfigLoader, HeadlessConfig
|
|
from engines import HeadlessSimulationEngine, HeadlessConfig as EngineHeadlessConfig
|
|
|
|
|
|
def main():
|
|
"""Main entry point for headless simulation."""
|
|
parser = argparse.ArgumentParser(description="Run headless simulation")
|
|
parser.add_argument(
|
|
"--config", "-c",
|
|
type=str,
|
|
help="Path to configuration file (JSON/YAML)",
|
|
default=None
|
|
)
|
|
parser.add_argument(
|
|
"--output-dir", "-o",
|
|
type=str,
|
|
help="Output directory for simulation data",
|
|
default="simulation_output"
|
|
)
|
|
parser.add_argument(
|
|
"--max-ticks", "-t",
|
|
type=int,
|
|
help="Maximum number of ticks to run",
|
|
default=None
|
|
)
|
|
parser.add_argument(
|
|
"--max-duration", "-d",
|
|
type=float,
|
|
help="Maximum duration in seconds",
|
|
default=None
|
|
)
|
|
parser.add_argument(
|
|
"--tps",
|
|
type=float,
|
|
help="Target TPS for simulation (default: unlimited speed)",
|
|
default=None
|
|
)
|
|
parser.add_argument(
|
|
"--real-time",
|
|
action="store_true",
|
|
help="Run in real-time mode (instead of as fast as possible)"
|
|
)
|
|
parser.add_argument(
|
|
"--collect-metrics",
|
|
action="store_true",
|
|
help="Enable metrics data collection"
|
|
)
|
|
parser.add_argument(
|
|
"--collect-entities",
|
|
action="store_true",
|
|
help="Enable entity data collection"
|
|
)
|
|
parser.add_argument(
|
|
"--collect-evolution",
|
|
action="store_true",
|
|
help="Enable evolution data collection"
|
|
)
|
|
parser.add_argument(
|
|
"--collect-all",
|
|
action="store_true",
|
|
help="Enable all data collection (metrics, entities, evolution)"
|
|
)
|
|
parser.add_argument(
|
|
"--collect-every-tick",
|
|
action="store_true",
|
|
help="Collect data on every tick instead of at intervals"
|
|
)
|
|
parser.add_argument(
|
|
"--create-sample-configs",
|
|
action="store_true",
|
|
help="Create sample configuration files and exit"
|
|
)
|
|
parser.add_argument(
|
|
"--early-stop",
|
|
action="store_true",
|
|
help="Stop simulation when there are 0 cells remaining"
|
|
)
|
|
|
|
args = parser.parse_args()
|
|
|
|
# Create sample configs if requested
|
|
if args.create_sample_configs:
|
|
ConfigLoader.create_sample_configs()
|
|
return
|
|
|
|
# Load configuration
|
|
try:
|
|
if args.config:
|
|
headless_config = ConfigLoader.load_headless_config(args.config)
|
|
else:
|
|
headless_config = ConfigLoader.get_default_headless_config()
|
|
|
|
# Override config with command line arguments
|
|
if args.max_ticks:
|
|
headless_config.max_ticks = args.max_ticks
|
|
if args.max_duration:
|
|
headless_config.max_duration = args.max_duration
|
|
if args.tps is not None:
|
|
headless_config.simulation.default_tps = args.tps
|
|
else:
|
|
# No TPS specified - run at maximum speed
|
|
headless_config.simulation.default_tps = 999999999.0
|
|
if args.output_dir:
|
|
headless_config.output.directory = args.output_dir
|
|
if args.real_time:
|
|
headless_config.output.real_time = True
|
|
# Handle data collection arguments - only enable if explicitly requested
|
|
# Start with all disabled (default)
|
|
headless_config.output.collect_metrics = False
|
|
headless_config.output.collect_entities = False
|
|
headless_config.output.collect_evolution = False
|
|
|
|
if args.collect_all:
|
|
# Enable all collection
|
|
headless_config.output.collect_metrics = True
|
|
headless_config.output.collect_entities = True
|
|
headless_config.output.collect_evolution = True
|
|
else:
|
|
# Enable specific collection types
|
|
if args.collect_metrics:
|
|
headless_config.output.collect_metrics = True
|
|
if args.collect_entities:
|
|
headless_config.output.collect_entities = True
|
|
if args.collect_evolution:
|
|
headless_config.output.collect_evolution = True
|
|
|
|
if args.collect_every_tick:
|
|
# Set all collection intervals to 1 for every-tick collection
|
|
headless_config.output.metrics_interval = 1
|
|
headless_config.output.entities_interval = 1
|
|
headless_config.output.evolution_interval = 1
|
|
# Also enable all collection if using --collect-every-tick (backward compatibility)
|
|
headless_config.output.collect_metrics = True
|
|
headless_config.output.collect_entities = True
|
|
headless_config.output.collect_evolution = True
|
|
|
|
# Set early stopping flag
|
|
if args.early_stop:
|
|
headless_config.early_stop = True
|
|
|
|
except Exception as e:
|
|
print(f"Error loading configuration: {e}")
|
|
sys.exit(1)
|
|
|
|
# Create engine configuration
|
|
engine_config = EngineHeadlessConfig(
|
|
simulation=headless_config.simulation,
|
|
max_ticks=headless_config.max_ticks,
|
|
max_duration=headless_config.max_duration,
|
|
output_dir=headless_config.output.directory,
|
|
enable_metrics=headless_config.output.collect_metrics,
|
|
enable_entities=headless_config.output.collect_entities,
|
|
enable_evolution=headless_config.output.collect_evolution,
|
|
metrics_interval=headless_config.output.metrics_interval,
|
|
entities_interval=headless_config.output.entities_interval,
|
|
evolution_interval=headless_config.output.evolution_interval,
|
|
output_formats=headless_config.output.formats,
|
|
real_time=headless_config.output.real_time,
|
|
early_stop=headless_config.early_stop
|
|
)
|
|
|
|
# Create and run simulation
|
|
try:
|
|
print("Starting headless simulation...")
|
|
engine = HeadlessSimulationEngine(engine_config)
|
|
summary = engine.run()
|
|
|
|
# Print summary
|
|
print("\n" + "="*50)
|
|
print("SIMULATION SUMMARY")
|
|
print("="*50)
|
|
print(f"Total ticks: {summary['runtime']['total_ticks']}")
|
|
print(f"Duration: {summary['runtime']['duration_seconds']:.2f} seconds")
|
|
print(f"Average TPS: {summary['runtime']['average_tps']:.2f}")
|
|
print(f"Final entity counts: {summary['final_state']['entity_counts']}")
|
|
print(f"Output directory: {summary['data_collection']['output_directory']}")
|
|
|
|
except KeyboardInterrupt:
|
|
print("\nSimulation interrupted by user")
|
|
sys.exit(0)
|
|
except Exception as e:
|
|
print(f"Simulation error: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
sys.exit(1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main() |