#!/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())