日期:2026-08-02 | 项目:M-381 / P580 | 在线试:https://metazero-terminal.pages.dev/maptext/
外部那套方案和我这套,在最核心的判断上是一致的 —— 都认为地图必须拆成「布局层 / 模板层 / 规则层」,都认为不能让一个字符承担全部信息。两边独立走到同一个结论,这本身说明这个方向是对的。
但对方有三件事比我做得对,我确实缺:
| 缺口 | 对方怎么做 | 我现在怎么样 | 严重程度 |
|---|---|---|---|
| 一栋楼可以占多格 | 2×3 格、5×8 格 | ❌ 每栋楼死死占 1 格 | 🔴 最大结构缺陷 |
| 随机表达式统一成结构化写法 | {"int":[4,12]} {"weighted":{...}} | ⚠️ 我是紧凑写法 60..180 tree*4?.5 | 🟡 AI 生成友好度 |
| 规则要能表达「约束」而不只是「动作」 | forbid: overlap [road,building] / require: distance_to_road max 1 | ❌ 我只有 条件 => 动作 | 🟠 随机合理性的地基 |
我有两件事他们那份文档里没有:
@grid(画出来)和 @zones/@rules(写规则)是可叠加的两层 —— 小图全画、大图全写规则、主城手画+郊区规则。他们的最小版是纯 grid,扩到 8000×8000 时会撞墙。city_preview.png),是"看图";我这边是第一人称走在里面,走远了窗口自动重建,8000×8000 可以一直走。| 判断 | 对方 | 我 |
|---|---|---|
| 一个字符只回答"这是什么大类型" | B=住宅 S=商店 ==道路 | A=tower b=low .=road |
| 颜色/高度/屋顶放模板不放地图 | tiles 字典 | @legend |
| 世界尺寸 / 逻辑格子分开 | world_size + cell_size | size + cell |
| 同种子必须完全复现 | stable_rng(seed, x, y, obj) | hash(seed, x, z, 用途) |
| 区块种子 = hash(世界种子, 区块坐标) | chunk_seed | 我按格算,更细,等价 |
| 分层:地形→道路→街区→建筑→组件→装饰 | 8 层 | 6 层(缺地形层、表面细节层) |
双方独立得出同一套骨架,这是这次对照最有价值的信息 —— 说明这条路不是拍脑袋。
① 一栋楼可以占多格(最重要)
他们明确写了「不要使用一个像素点等于一栋楼」,理由是:绑死之后就没法加入道路、院子、停车场和建筑轮廓。
这一条我确实踩了。 我现在每栋楼死死占一格,后果已经在画面上看得出来:
升级方案:@legend 加 span=2x3,build() 里把占位的格子标记为"被 XX 占用",跳过重复生成。这是 v0.4 的头号任务。
② 随机表达式该统一成结构化写法
我现在是紧凑写法:h=60..180、deco=tree*4,lamp?.5、weight=3。
他们是结构化:{"int":[4,12]}、{"weighted":{"flat":5,"garden":1}}、{"chance":0.3}。
谁更好,看给谁写:
h=60..180 vs 一坨 JSON).. * ? 三种符号,AI 容易混)正确答案是两个都要:紧凑写法当人写的糖,结构化写法当 AI 写的正规形式,解析器两边都吃。这样"让 AI 生成一段文本粘进来"的成功率才高。
③ 规则要能表达"约束",不只是"动作"
他们的规则里有三个动词是我没有的:
`
forbid: overlap: [road, building] # 树不许长在楼里/路上
require: distance_to_road: max 1 # 商店必须挨着路
set: entrance_direction: toward_road # 楼门必须朝街
`
我现在只有 条件 => 动作(near(park,2) => deco+=tree*2)。"动作"能加东西,但拦不住不合理的东西。 他们列的五种荒唐结果——大楼压在路中间、商店没有入口、树长在建筑内部、道路互不相连、高楼出现在荒郊——正是缺约束的后果。
我在知识城市那边是用代码硬修的(街区红线、车撞墙掉头)。但那是写死在引擎里,换个地图就没了。正确做法是把它变成语言的一部分,写在 @rules 里,任何地图都能用。
① 画与规则可叠加
他们的 MapSpec 最小版是纯 layout 网格。文档第六节确实提到了大地图要"按顺序生成",但没有给出"手画区和规则区怎么共存"的机制。
我这边 @grid(画了的以画的为准)和 @zones/@rules(没画的按规则长)是同一份文件里的两层,可以混着来。这正是他们文档结尾"第一阶段/第二阶段"想解决的问题。
② 能走进去,而且窗口跟着人走
他们的最小实现是 Python + matplotlib,输出 city_preview.png + city_objects.json,然后说"可以进一步交给 Godot / Unity / Three.js"。那一步没做。
我这边这一步做完了:第一人称走在里面、楼和地面有真碰撞、走远了渲染窗口自动重建。这也是这次主席指出的那个点——"只能看,人进不去"和"能走进去"是两回事。
| 主席点名 | 做法 |
|---|---|
| 🎨 材质基本等于没有 | 根因是全用了不吃光的 MeshBasicMaterial + 几何体没有法线,所以一个面永远是一块死平的纯色。现在补了 computeVertexNormals() + 半球光/平行光/环境光,做了 7 套渲染风格可当场切换对比 |
| 🗺️ 要小地图 | 2D 俯瞰平面图:楼(越高越亮)、街、公园、水;11 个编号兴趣点(地标/广场/公园/港湾);绿箭头就是你,箭头方向就是你在看的方向;点任意一个点直接走过去 |
| 🎲 随机出现在地图任何地方 | 在整张图(不只当前窗口)随机抽格,只落在能站人的地面上,落点触发窗口重建 |
| 📈 FPS 显示 | 近 30 帧滑动平均,进两处 HUD(俯瞰的统计行 + 第一人称的信息条),>45 绿 / >24 黄 / 否则红 |
| 📝 文本换世界 + 多种预设风格 | 从 4 套扩到 7 套:8×8手画 / 赛博朋克大城 / 复古英伦古城 / 迷宫 / 废土残城 / 荒郊野外 / 小镇 |
新增的楼型特点(主席说"要把相应的楼房特点做出来"):
gable 双坡(老城民居)、pyramid 四坡、onion 洋葱顶(钟楼/教堂)chimney 烟囱、clock 钟面、banner 旗幡、column 柱廊、lantern 挂灯、awning 雨棚well 水井、fountain 喷泉、stall 集市摊、cart 板车、gaslamp 煤气路灯、crate 木箱迷宫是真跑递归回溯算法生成的,不是规则长出来的 —— 这恰好证明了"画格子"那一层不能省:规则长不出连通的迷宫。
1. 多格建筑 span=2x3 —— 头号缺陷,做完城市形态立刻不一样
2. 约束型规则 forbid / require —— 让随机生成不再出荒唐结果
3. 结构化随机表达式与紧凑写法并存 —— 提高 AI 生成成功率
4. 地形层 @terrain height=noise(...) —— 地面有山有坡有河谷(现在是平板)
5. 真道路图(外部方案 D)—— 环路/放射路/弯道,替掉棋盘
6. Chunk streaming —— 现在是"走远了整块重建",会有一次卡顿;改成按 64×64 区块加载/卸载,走到哪加载哪,真正无缝
7. 世界状态 + 任务状态机 + 对话树 + NPC 记忆 —— 这正是主席之前说的"讲故事、看电视"模式。知识城市那边已经有对话引擎(一幕=一串步骤,步骤可以是带选项的岔路口),把它抽出来变成 StorySpec 就能接上
建议顺序不要跳:多格建筑 → 约束规则 → 地形 → 道路图 → 区块流式 → 剧情。跳过前两条直接做剧情,会在一个"棋盘格、楼压在路上"的世界里讲故事。
最强反对:「多格建筑是最大缺陷」可能是错的。
一格一楼的棋盘感,也可能不是"格子绑死"造成的,而是建筑外形种类太少(8 种体块 × 9 种屋顶)+ 高度分布太均匀造成的。如果是后者,做多格建筑不会解决问题,只会让工程量翻倍。
回应:两者都会贡献,但多格是结构性的(不做就永远做不出"一整个街区是一栋楼"和院子/停车场),外形种类是可加的。所以先做结构、再加种类。
可证伪锚:v0.4 做完多格建筑后,如果主席看了截图仍然说"还是很棋盘",那说明我判断错了,真正的瓶颈是外形种类和高度分布,应该转去做那两样。这一条到时能被主席一句话检验。
已知缺口(诚实列出):
*支撑文件:web/terminal/maptext/maptext.js(语言 + 7 套模板 + 迷宫生成器)· web/terminal/maptext/index.html(渲染器 + 7 套材质 + 小地图 + 第一人称)*