#!/usr/bin/env python3 """World generator CLI (see README.md). A world is a folder with config/, sketch/ (and optional masks/); builds go to its out/.""" import argparse import os import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent)) from mapgen import config as C # noqa: E402 from mapgen import pipeline as P # noqa: E402 def main(argv=None, root: Path | None = None) -> int: ap = argparse.ArgumentParser(prog="mapgen.py") ap.add_argument("--world", help="the world's folder (its config/, sketch/, out/); default: the current folder") sub = ap.add_subparsers(dest="cmd", required=True) nw = sub.add_parser("new-world", help="random sketch/ + config/tectonics.toml + config/eras.toml") nw.add_argument("--seed", type=int, required=True) nw.add_argument("--continents", type=int, default=6) nw.add_argument("--land", type=float, default=0.27, help="land share of the sketch") nw.add_argument("--toward", type=float, nargs=2, metavar=("LAT", "LON"), help="gather the land toward this point") nw.add_argument("--mountains", type=float, default=0.86, help="ridge threshold (lower: more ranges)") nw.add_argument("--force", action="store_true") for name in ("build", "check", "era", "compare"): s = sub.add_parser(name) s.add_argument("--res", type=int) s.add_argument("--final", action="store_true") s.add_argument("--low-memory", action="store_true", help="slower, lower memory peak; same results (or set WORLDGEN_LOW_MEMORY=1)") if name == "compare": s.add_argument("--old", required=True, help="an earlier cells.npz of the same resolution") if name == "era": s.add_argument("name", help="an era from config/eras.toml") if name == "build": s.add_argument("--from", dest="start", choices=P.STAGES) s.add_argument("--stop", choices=P.STAGES) a = ap.parse_args(argv) if a.world: root = Path(a.world).resolve() elif root is None: root = Path.cwd() try: if a.cmd == "new-world": from mapgen import newworld newworld.make(root, a.seed, a.continents, a.land, a.toward, a.mountains, a.force) return 0 cfg, _ = C.load(root) low = bool(getattr(a, "low_memory", False)) or os.environ.get("WORLDGEN_LOW_MEMORY", "") not in ("", "0") res = a.res if a.res is not None else int(cfg["build"]["res_final" if a.final else "res_dev"]) if a.cmd == "build": ctx = P.build(root, res, a.start, a.stop, low_memory=low) if a.stop is None: # every era with events, from the fresh base from mapgen import eras eras.build_all(root, res, base=ctx, low_memory=low) return 0 if a.cmd == "era": from mapgen import eras eras.build_era(root, res, a.name, low_memory=low) return 0 if a.cmd == "compare": # base vs an earlier build, outside the edited areas from mapgen import check return check.compare_report(root, res, Path(a.old)) from mapgen import check ctx = P.build(root, res, stop="fields", log=lambda m: None) return check.report(ctx) except (C.ConfigError, P.StageError) as e: print(f"error: {e}", file=sys.stderr) return 2 if __name__ == "__main__": sys.exit(main())