worldgen

git clone https://git.godosa.eu/worldgen

master

raw ยท 3496 bytes

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