Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Worldsmith

一句自然语言实时改写天气、地形物理、敌人行为、战斗规则与任务的可玩 Canvas 世界。

GIF 占位:录制 让这里进入暴风雪,河面结冰,敌人改成怕火的冰狼 的完整 8 秒演示。

2 分钟上手

需要 Node.js 20.19+22.12+。下载 GitHub Release 源码包并解压,或克隆仓库后运行:

npm install
cp .env.example .env
# 在 .env 填 ANTHROPIC_API_KEY;留空也能使用完整的本地兜底演示
npm start

npm start 会先完成 TypeScript 检查与前端生产构建,再启动服务。默认打开 http://localhost:4173;若该端口已被占用,会自动使用后续空闲端口并在终端打印真实地址。开发时使用 npm run dev 启用热更新。

打开终端显示的地址,输入:

让这里进入暴风雪,河面结冰,敌人改成怕火的冰狼

使用 WASD 移动,J 近战挥击,K 发射自动瞄准最近敌人的投射物。数字键 16Tab 切换伤害元素(火/冰/雷/毒/圣/物理),近战与远程都继承当前元素,所以任何"怕雷的敌人"这类规则都能被真正玩出来。火把是有限燃料:连续挥击会耗尽并熄灭,熄灭后惧光敌人不再逃跑。生命归零不会卡死世界——玩家会短暂倒下并在安全地块重生,击杀数与任务进度保留。按反引号键打开技术面板。

已可结算的世界规则

规则不是文案,全部由本地确定性代码结算,并且玩家和敌人同样受影响:

规则 实际效果
damage_multiplier 六种元素各自独立结算,先乘倍率再扣抗性
stat_override 持续覆盖敌人的 hp / speed / damage,按比例保留当前血量
material_effect damage / heal / slow 同时作用于玩家与敌人
global_flag darkness 压暗画面并缩小敌人索敌范围,点火把会重新暴露自己
global_flag low_gravity 提高目标速度、降低加速度与摩擦,产生漂浮滑行
global_flag water_frozen 无需改写地形即让 water 可通行,敌人也能跟着过河
behavior_override 覆盖 AI 状态机分支
collect 目标 走过对应材质地块即消耗该格并推进任务

敌人会被不可通行地形逐轴阻挡、受材质伤害与减速影响,并在被完全困住时朝出生点回退,所以地形改写本身就是一种战术设计。生成点会自动推到最近的可通行地块,敌人不会被丢进岩浆里。

输入框会在提交前实时显示本地语义解析结果。增强理解器可以在一句话里同时提取天气、时间、地形、实体、数量、行为、元素弱点与任务,也能理解“再来五只”“再强一点”“让冰融化”这类基于当前世界的续写,以及“末日但没有敌人”“暴风雪但河流不要结冰”这类转折和否定。顶部工具提供完整世界快照的撤销、重做、重置与随机复合灵感;Ctrl/Cmd+Z 撤销,Ctrl/Cmd+Shift+Z 重做。

路演操作手册

开演前 5 分钟运行 npm run dev,等待终端出现 World cache warm: true。打开 /api/health,确认 okcacheWarm 均为 true。回到主页,按反引号关闭技术面板。优先使用底部四个安全预设:暴风雪展示地形物理与元素弱点;火山展示危险材质与抗性;深夜展示视野与惧光 AI;和平用于干净收尾。

断网时把地址改为 http://localhost:4173/?offline=1。此模式从 recordings/ 模糊匹配回放,全程不会请求 Claude,故意保留约 400ms 的自然“施法”节奏。评委即兴提问时可以引导:“请同时说一种天气、一种地形变化和敌人的弱点,这样能看到整条规则链。”

没有 API 密钥时 /api/healthmodelocal-fallback,缓存预热表示本地录制和预制补丁已装载。真实 Claude 提示缓存命中需要有效密钥;技术面板中的 CACHE READ 应大于 0。

架构

utterance
    │
    ▼
Claude structured output ──校验失败──► repair retry
    │                                      │
    │                               再失败/超时
    │                                      ▼
    ├──────────────────────────────► 8 preset patches ──无匹配──► visible weather fallback
    │
    ▼
WorldPatch JSON stream
    │  env → terrain → rules → entities → quests
    ▼
apply.ts (normalize + validate + idempotent apply + actual diff)
    ├──► palette / weather / tiles
    ├──► AI state machine
    ├──► combat calculator
    ├──► quest evaluator
    └──► verified rule log

Claude 只产生结构化 WorldPatch。渲染、物理、AI 和伤害结算完全由本地确定性代码从 WorldState 推导。规则面板使用 apply.ts 返回的实际 diff,再为成功变更匹配模型提供的 reason

WorldPatch 契约

顶层属性固定为:

属性 作用
env 天气、风、可见度、时间、温度、环境色;无变化为 null
terrain replace_materialfillscatter 操作;无变化为 null
rules 添加、移除或清空可结算规则;无变化为 null
entities 重定型、生成、移除、修改实体;无变化为 null
quests 添加或完成带可判定 objectives 的任务;无变化为 null
changes 字段、前值、后值和原因;只给实际 diff 提供解释
summary UI 最后一行总述

规则类型包括元素伤害倍率、数值覆盖、行为覆盖、材质效果与全局标志。目标选择器只能按原型、阵营或全部实体。区域只能是全图、矩形或圆形。完整示例:

{
  "env": {
    "weather": "blizzard",
    "intensity": 0.92,
    "wind": { "dir": 5.85, "speed": 0.94 },
    "visibility": 0.46,
    "time": null,
    "temperature": -18,
    "ambient": { "hue": 197, "sat": 58, "light": 72 }
  },
  "terrain": [
    { "op": "replace_material", "from": "water", "to": "ice", "region": { "type": "all" } }
  ],
  "rules": [
    {
      "op": "add",
      "rule": {
        "id": "ice-wolf-fire-weakness",
        "kind": "damage_multiplier",
        "target": { "by": "archetype", "value": "ice_wolf" },
        "element": "fire",
        "value": 2.5
      }
    }
  ],
  "entities": [
    {
      "op": "retype",
      "target": { "by": "archetype", "value": "wolf" },
      "to": "ice_wolf",
      "overrides": null
    }
  ],
  "quests": [
    {
      "op": "add",
      "quest": {
        "id": "survive-whiteout",
        "title": "白幕中的火种",
        "description": "穿过冻结的河面,用火焰击退冰狼。",
        "objectives": [
          { "type": "kill_count", "target": "ice_wolf", "goal": 3, "progress": 0 }
        ]
      }
    }
  ],
  "changes": [
    { "field": "env.weather", "before": "clear", "after": "blizzard", "reason": "暴风雪会立刻压低能见度并改变风场。" },
    { "field": "terrain.replace_material", "before": "water", "after": "ice", "reason": "低温冻结河面,使其可通行且具有滑行惯性。" },
    { "field": "rules.ice-wolf-fire-weakness", "before": "", "after": "fire ×2.5 vs ice_wolf", "reason": "冰狼的寒冰躯体会被火元素快速瓦解。" }
  ],
  "summary": "暴风雪封锁了荒原;河流已经冻结,火焰成了活下去的唯一答案。"
}

Zod 是唯一 schema 来源,服务端通过 zod-to-json-schema 生成 Claude 的 JSON Schema。结构化输出中的可选段以必需但可空的字段表达,所有对象均为 strict。

模型与延迟

默认模型为 claude-opus-4-8,使用低 effort、关闭 thinking、8192 max tokens 和流式结构化输出。WORLDSMITH_MODEL 可切换为 claude-sonnet-5claude-haiku-4-5;代码始终显式关闭 thinking。WORLDSMITH_FAST=1 对 Opus 4.8 启用 Fast Mode,429 时自动回到标准通道。SDK 超时为 20 秒,最多一次 SDK 重试。

静态 system prompt 保持逐字节固定并超过 4096-token 缓存门槛,动态世界摘要只放在 user 消息。服务启动发送完整预热请求,随后每 4 分钟保活。调试面板显示首字节、端到端延迟、输入输出 token、cache read、来源、兜底状态、警告、活动规则和原始补丁。

使用 WORLDSMITH_FAULT=invalid-once 注入一次非法输出并观察修复重试;使用 WORLDSMITH_FAULT=always-invalid 验证连续失败后的预制补丁。

扩展词汇表

增加材质时在 shared/vocab.tsMATERIALMATERIAL_PROPS 加枚举和完整物理属性,再在 client/render/tiles.ts 加程序化纹理;schema 会自动继承枚举。增加原型时在 ARCHETYPEARCHETYPE_TEMPLATES 加模板,再按需在 render/entities.ts 调整符号表现。增加规则时在 shared/schema.ts 扩展 RuleSchema,在 client/sim/rules.ts 实现求值(该模块是规则求值的唯一入口,ai.tsplayer.tscombat.ts 都从这里读取),并为 client/apply.ts 保留真实 diff。新机制务必同步 client/interpreter.ts,否则无 API key 时离线演示看不到它。

测试与已知局限

npm test 不调用真实 API,覆盖预制补丁、所有 apply 操作、幂等性、未知枚举、分片 JSON、三层兜底、伤害公式、材质物理、世界压缩,以及规则求值(stat_override、三个全局标志、slow/heal 聚合)、六元素伤害与抗性、收集任务、地形感知敌人、火把燃料与黑暗、死亡重生。npm run build 同时执行 TypeScript 检查和生产构建。

当前模型偶尔会误解复杂空间关系;世界内容只能来自闭合词汇表;没有存档系统;玩法为单人本地;录制文件在单机文件系统持久化,面向本地路演。玩家的元素选择与火把燃料属于会话状态,不写入 WorldState,因此不会被撤销/重做回滚。敌人使用逐轴阻挡而非寻路,遇到复杂凹形地形时会贴边而不会绕远路。

About

Speak the world into being — a natural-language real-time game world compiler.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages