File size: 3,018 Bytes
4be6a52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
"""Small CLI that keeps optional model dependencies out of the game path."""

import argparse
import json
from pathlib import Path


def main() -> None:
    parser = argparse.ArgumentParser(description="Stackcraft: play, replay, and measure decisions.")
    parser.add_argument("--version", action="version", version="stackcraft 0.1.0")
    commands = parser.add_subparsers(dest="command", required=True)
    serve = commands.add_parser("serve", help="Start the local game and replay service")
    serve.add_argument("--host", default="127.0.0.1")
    serve.add_argument("--port", type=int, default=8080)
    tournament = commands.add_parser("tournament", help="Run paired offline development baselines")
    tournament.add_argument("--seed-start", type=int, default=1000)
    tournament.add_argument("--episodes", type=int, default=20)
    tournament.add_argument("--max-pieces", type=int, default=100)
    tournament.add_argument("--output", type=Path, required=True)
    generate = commands.add_parser("generate-data", help="Generate and audit expert-labelled data")
    generate.add_argument("--output", type=Path, required=True)
    args = parser.parse_args()
    if args.command == "serve":
        import uvicorn

        uvicorn.run("stackcraft.server:create_app", factory=True, host=args.host, port=args.port)
    elif args.command == "tournament":
        from stackcraft.players import HeuristicPlayer, RandomPlayer
        from stackcraft.tournament import run_tournament

        if args.episodes < 1 or args.max_pieces < 1:
            parser.error("--episodes and --max-pieces must be positive")
        if args.output.exists():
            parser.error(f"output already exists: {args.output}; choose a new path")
        seeds = list(range(args.seed_start, args.seed_start + args.episodes))
        result = run_tournament(
            {"random": RandomPlayer, "heuristic": HeuristicPlayer}, seeds, args.max_pieces
        )
        args.output.parent.mkdir(parents=True, exist_ok=True)
        with args.output.open("x") as output:
            json.dump(result, output, indent=2, allow_nan=False)
            output.write("\n")
        print(f"Saved {args.episodes} paired development episodes to {args.output}")
    elif args.command == "generate-data":
        from stackcraft.data import DatasetConfig, generate_dataset, write_dataset
        from stackcraft.provenance import source_identity

        if args.output.exists():
            parser.error(f"output already exists: {args.output}; choose a new path")
        try:
            identity = source_identity(Path(__file__).resolve().parents[2])
        except ValueError as error:
            parser.error(str(error))
        commit = identity["source_commit"] + ("+working-tree" if identity["source_dirty"] else "")
        bundle = generate_dataset(DatasetConfig(), source_commit=commit)
        write_dataset(bundle, args.output)
        print(f"Saved expert dataset and manifest to {args.output}")


if __name__ == "__main__":
    main()