Add a map renderer

This commit is contained in:
Jared Miller 2026-02-07 13:38:32 -05:00
parent 25bb565091
commit 9cdc1c48e4
Signed by: shmup
GPG key ID: 22B5C6D66A38B06C
3 changed files with 100 additions and 0 deletions

1
.gitignore vendored
View file

@ -1,2 +1,3 @@
__pycache__
repos
build

View file

@ -15,3 +15,6 @@ run:
debug:
uv run python -m mudlib --debug
render:
uv run python scripts/render_map.py

96
scripts/render_map.py Normal file
View file

@ -0,0 +1,96 @@
#!/usr/bin/env python
"""Render the full world map as an HTML page."""
import sys
import tomllib
import webbrowser
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent / "src"))
from mudlib.world.terrain import World
ROOT = Path(__file__).parent.parent
def main():
config_path = ROOT / "worlds" / "earth" / "config.toml"
with open(config_path, "rb") as f:
config = tomllib.load(f)
seed = config["world"]["seed"]
width = config["world"]["width"]
height = config["world"]["height"]
name = config["world"]["name"]
print(f"generating {name} ({width}x{height}, seed={seed})...")
world = World(seed=seed, width=width, height=height)
# encode terrain as compact string, one char per tile
rows = ["".join(row) for row in world.terrain]
terrain_data = "\\n".join(rows)
html = f"""<!doctype html>
<html>
<head>
<title>{name}</title>
<style>
body {{
margin: 0;
background: #111;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}}
canvas {{
image-rendering: pixelated;
max-width: 100vmin;
max-height: 100vmin;
width: 100vmin;
height: 100vmin;
}}
</style>
</head>
<body>
<canvas id="map" width="{width}" height="{height}"></canvas>
<script>
const W = {width}, H = {height};
const terrain = "{terrain_data}";
const colors = {{
'~': [34, 68, 170],
':': [194, 178, 128],
'.': [34, 139, 34],
'T': [10, 95, 10],
'^': [102, 102, 102],
}};
const canvas = document.getElementById('map');
const ctx = canvas.getContext('2d');
const img = ctx.createImageData(W, H);
const d = img.data;
const rows = terrain.split('\\n');
for (let y = 0; y < H; y++) {{
const row = rows[y];
for (let x = 0; x < W; x++) {{
const c = colors[row[x]] || [255, 0, 255];
const i = (y * W + x) * 4;
d[i] = c[0];
d[i+1] = c[1];
d[i+2] = c[2];
d[i+3] = 255;
}}
}}
ctx.putImageData(img, 0, 0);
</script>
</body>
</html>"""
out_path = ROOT / "build" / "map.html"
out_path.parent.mkdir(exist_ok=True)
out_path.write_text(html)
print(f"wrote {out_path}")
webbrowser.open(f"file://{out_path.resolve()}")
if __name__ == "__main__":
main()