RUN_DESIGN 文本格式指南
本指南描述一种简洁、便于人手编辑的交互故事文本格式(RUN_DESIGN)
RUN_DESIGN 文本格式指南
本指南描述一种简洁、便于人手编辑的交互故事文本格式(RUN_DESIGN)。同时支持可逆转换:JSON → RUN_DESIGN → JSON,在支持的字段范围内不会有语义流失。
目标
简单、可读、利于版本控管的文本格式
能编译成 JSON 的故事结构
能将 JSON 无语义差异地导出回文本
文件编码
UTF-8
空白与注解(Whitespace & Comments)
允许空白行。
以
//开头的单行为注解,编译时会被忽略。请另开新行。
顶层元数据(Metadata)
[meta] title "<Title>"设置故事标题[meta] author "<Author>"设置作者(必填;导入/更新时若缺少会被拒绝)[intro] <text>追加一行故事导言(可重复多行),在剧本开始时会显示。
显示行为:
在
.st list中:指定 alias 时,会完整显示该故事的导言(若有)。
列出所有可启动剧本时,会在每列标题下显示导言第一行的预览(最多 80 字)。
在
.st mylist中:每项剧本会显示导言第一行的预览(最多 80 字)。
在启动游戏后且玩家变量尚未完成设置时:
角色设置提示前会先显示【简介】区块,内容为导言全文。
范例:
玩家变量(Player Variables)
[player_var] <key> "<prompt>" ["<placeholder>"]key:识别字,例如
cat_nameprompt:显示给玩家的提问
placeholder:可选的提示文本
范例:
游戏属性(Game Stats)
[stat_def] <key> <min> <max> ["<label>"]初始化:未被明确设置时,首次开始时以
min~max随机整数初始化。锁定:若该属性曾被内容内的
[set]明确指定,之后将不再被随机初始化覆写。
范例:
变量(Variables)
[var_def] <key> <min> <max> ["<label>"]
范例:
页面(Pages)
故事由多个页面组成。
定义页面标签(ID):
[label] <id>限制:页面 ID 只能使用数字(如
0,1,2,10等)开点页面:
[label] 0为故事的起始页面,游戏开始时会自动加载此页面其他页面可使用任意数字作为 ID,建议使用连续数字以保持可读性
可选页面标题:
[title] <text>页面内容(不限行数):
[text] <content>[text|if=<expr>] <content>条件显示[text|else] <content>与前一或多个连续的[text|if=...]形成条件链,只会显示第一个符合条件的项目;若皆不符合则显示else。也支持于结局区块中使用。[text|ifs=<expr>] <content>独立条件显示:只要命中就显示,不会与上下邻近的[text|if=...]/[text|else]形成条件链。[text|speaker=<key>] <content>指定说话者[text|speaker=<key>,if=<expr>] <content>指定说话者且具条件[random] <percent>%仅影响「下一行」的[text](例如 30%),percent为 0~100 的整数。[set] <key>=<expr>在渲染时设置值:若key属于已定义的stat_def,则写入stats;否则写入variables。<expr>支持基本表达式(见下文)。任一属性一旦被
[set]明确设置,之后将不再由随机初始化覆写。
文本内可直接掷骰:
{xDy}会在显示时掷骰并以总和取代,例如{1D100}、{2d20}、{3d6}。
结局标记:
[ending]之后的[text]行视为结局文本,会使用第一个符合条件的结局支持条件链:可使用多行
[text|if=...]后接一行[text|else]作为后备要求:一个有效的 RUN_DESIGN 必须至少包含一个带有
[ending]标记的页面;若未定义结局,上传/更新将被拒绝。
选项区块:
[choice]开始定义选项列表-> <text> | <页面代号> [| if=<expr>] [| stat=a+1,b-2]<页面代号>必须为数字页面 ID,或使用带字母尾码的变体(例如2a、2b、2c);或特殊值END。新功能:支持
2a,2b,2c等格式,其中数字部分(如2)为实际跳转的页面,字母部分(如a,b,c)仅用于区分不同的加成或描述变体(实际跳转到2)。<页面代号>为END时,接口会提供「.st end」按钮以结束游戏。stat=仅支持整数加减,并在成功前往该选项之目标页面时套用(例:Cuteness+1,Energy-2)。
新功能:多选项同页面跳转
使用 2a, 2b, 2c 等格式可以让多个选项都跳转到同一个页面(如页面 2),但每个选项可以有不同的加成效果:
当玩家使用 .st goto 2a、.st goto 2b、.st goto 2c 时:
都会跳转到页面
2但会分别获得不同的加成:淘气度+1、萌度+1、活力+1
表达式(Expressions)
条件以小型、类 JS 的子集合为语法,运行于 scope(
variables+stats+playerVariables)支持操作符:
&& || ! < <= > >= == === != !== + - * / % ()安全限制:不允许任何函数调用;不可访问
globalThis、global、process、this、Function、constructor、require等识别字。范例:
if=Cuteness>=8 && Energy>3
支持一元否定
!expr(可搭配括号以控制优先级)。范例:
if=(Strength>5) && !(Agility>5)
掷骰(Dice)
在条件与赋值表达式中,可直接使用
xDy字面量,会在运算前掷骰并以总和值替换,例如:if=2d20>25[set] luck=3d6+2允许的范围:
x1100、y110000;超出将被夹在此范围内。
条件赋值(Conditional Set)
支持在
[set]上使用条件选项:[set|if=<expr>] key=<expr>。结合掷骰,可实作常见的检定流程。
范例:
范例页面(Example Page)
结局页(Ending Page)
占位符(Placeholders)
在
[text]内使用{key}会依序从playerVariables、stats、variables取值并套入(优先级如前,后者可覆盖前者)。若找不到对应键,将保留原样(例如
{unknown_key}会原样输出)。
注:兼容性与限制补充
目前不支持以纯字符串作为页面 ID;请使用数字页面 ID(例如
0,1,2)。[set]行允许在值的后方加上行尾//注解,导入时该注解会被忽略,不影响赋值内容。
往返转换(Round Trip)
导入文本(于 Discord 夹带文件):发送
.st import <alias> [title]并附上.txt(RUN_DESIGN)或.json文件更新既有剧本:
.st update <alias> [title]并附上新文件导出文本:
.st exportfile <alias>(机器人将以私讯发送文本档)验证可逆:
.st verify <alias>
范式(Normalization)
编译器会将紧邻的
[random]与其后的第一行[text]合并解释为「几率显示」。导出时,若页面是结局页,
[ending]会紧跟在该页[label]之下,以维持可逆性。
惯例(Conventions)
开点页面:
[label] 0为故事的起始页面,游戏开始时会自动加载此页面。若需要可在编译后的 JSON 再行设置。页面 ID 限制:只能使用数字作为页面 ID。
说话者为可选;示例采用纯文本。
若需在内文中加入随机性,请于欲影响的
[text]之前「紧贴」放置[random] <percent>%(percent 为整数)。若需在选项上改变属性值,使用
stat=a+1,b-2(仅支持整数加减)。若需多个选项跳转到同一页面但有不同的加成效果,使用
2a,2b,2c等格式。
最佳实务(Best Practices)
为可读性建议使用数字且连续的 ID
条件判断尽量简单并以已定义的键为基础
避免过长的行;可拆分成多个
[text]确保每个结局页面都提供重新开始或结束的选项
善用
2a,2b,2c格式来创建有不同加成的选项
限制(Limits)
最多页数:400
每段文本(每一行
[text],包含结局文本)最长 500 字至少需包含一个带有
[ending]的页面导入/更新之附件大小上限:约 1 MB
页面 ID 只能使用数字
更多范例(More Examples)
说话者(Speakers)与条件链
说话者为可选字段,渲染时仅作为数据字段保存,不影响文本输出。
随机显示(Random)
[random] <percent>% 仅作用于其后第一行 [text],编译器在导出时会保持可逆性。
内嵌掷骰(Dice)与条件检定
在表达式中可使用 xDy 字面量;在文本中可用 {xDy} 直接内嵌掷骰,显示总和。
条件赋值(Conditional Set)与字符串值
RHS 以引号包装时会被视为字符串常值;否则会尝试以表达式求值。
多个选项同页面跳转(带加成)
玩家输入 .st goto 2a/2b/2c 皆会抵达页面 2,但各自套用不同的加成。
独立条件显示(ifs)
使用 ifs 的 [text] 不会与相邻的 if/else 形成条件链,命中就显示,可同时出现多行。
结局区块的条件链
结局的多行 [text|if=...] 与一行 [text|else] 形成条件链,仅显示第一个符合条件者;可在其上方书写无条件前言文本。
占位符的优先级与嵌套
{key} 查找顺序为 playerVariables → stats → variables。字符串值内若再包含 {...},会进行一次嵌套展开。
最后更新于