Cattca 脚本语法文档
Cattca 是一门嵌入 Markdown 的轻量脚本语言,专为互动叙事(Interactive Fiction)设计。脚本在 <//> 命令块中编写控制逻辑,在块外书写 Markdown 正文,两者交替构成完整的互动故事。
基本结构
一个 Cattca 脚本由文本块和命令块交替组成:
Markdown 正文…
</命令1; 命令2; …/>
更多 Markdown 正文…
- 文本块:命令块之外的任何内容,支持标准 Markdown 语法,由浏览器端
marked.js渲染。 - 命令块:用
</和/>包裹,内部可包含多条命令,用分号;分隔。
命令块可以跨越多行,分号是命令分隔符而非换行符。
注释
使用 /* */ 在脚本任意位置书写注释,注释内容会被解析器完全忽略:
/* 这是一条注释,不会出现在输出中 */
你醒了。
</let hp = 100; /* 初始生命值 */ />
注释可以出现在文本块和命令块中,但不能嵌套。
命令参考
let — 声明变量
声明一个新变量,可选赋初值。变量必须先 let 声明,才能用 set 修改。
let 变量名
let 变量名 = 表达式
示例:
</let name = "莱莉菥";
let hp = 100;
let maxHp = 100;
let isAlive = true;/>
变量名必须以字母或下划线开头,由字母、数字、下划线组成。
set — 修改变量
修改已声明变量的值。若变量未声明,会抛出运行时错误。
set 变量名 = 表达式
示例:
</set hp = hp - 10;
set name = "受伤的莱莉菥";/>
apply — 行内输出
将表达式的值输出到文本流中。输出会与周围的 Markdown 文本拼接后统一渲染,不会产生多余的段落换行。
apply 表达式
示例:
你当前的生命值是 </apply hp /> 点。
剩余生命值百分比:</apply hp / maxHp * 100 />%。
apply 非常适合在句中将变量值自然嵌入。它等价于其他模板语言中的 {{ variable }}。
label — 定义标签
在当前位置定义一个命名标签,供 goto 跳转。
label 标签名
标签名区分大小写。label 语句本身不产生任何输出。
示例:
</label start;/>
goto — 跳转
将执行流程跳转到指定标签处。
goto 标签名
示例:
</goto start;/>
若跳转到不存在的标签,会在日志中输出警告,脚本继续执行(防止死循环)。
if — 条件判断
根据条件执行一条命令。
if 表达式 -> 命令
示例:
</if hp <= 0 -> goto gameOver;
if hasKey -> goto openDoor;/>
条件为真(truthy)时执行 -> 右侧的命令。右侧命令可以是任何单条命令(goto、set、exit 等)。
exit — 结束脚本
立即终止脚本执行。
exit
示例:
</exit/>
input case — 选项输入
向用户展示一组选项,等待用户点击选择。选择后执行对应的命令。
input case 变量名: '选项1文本' -> 命令1: '选项2文本' -> 命令2: ...
变量名:可选——如果提供,选中的选项文本会存入该变量- 选项之间用
:分隔 - 每个选项后跟
-> 命令,选择后执行对应命令
示例(带变量):
</input case choice:
'打开宝箱' -> goto treasure:
'继续前进' -> goto nextRoom:
'原路返回' -> exit;/>
示例(不带变量):
</input case:
'继续睡觉' -> goto sleep:
'起床' -> goto wakeUp;/>
input text — 文本输入
向用户展示一个文本输入框,将输入内容存入变量。
input text 变量名
示例:(变量必须先 let 声明,理由同 random)
</let playerName = "";
请输入你的名字:
</input text playerName;/>
欢迎,</apply playerName />!
log — 调试日志
向调试日志区域输出一条信息,对玩家不可见。
log 表达式
示例:
</log "进入了房间3,当前hp=" + hp;/>
日志面板默认显示在游戏运行区底部,适合开发调试。
random — 随机数
生成一个指定范围内的随机整数(含两端)。
random 变量名 = 最小值 最大值
示例:
</let dice = 0;
random dice = 1 6;/>
骰子点数:</apply dice />
变量必须先 let 声明。最小值和最大值可以是表达式(如 random atk = baseAtk baseAtk+10)。
表达式
表达式在 let、set、if、apply、log、random 的值位置中使用,支持以下类型和运算符。
字面量
| 类型 | 示例 |
|---|---|
| 数字 | 42、-3、3.14 |
| 字符串 | "hello"、'你好' |
| 布尔 | true、false |
| 空值 | null |
字符串支持转义:\n(换行)、\r(回车)、\t(制表符)。
运算符
支持标准 JavaScript 运算符子集:
| 类别 | 运算符 |
|---|---|
| 算术 | + - * / % |
| 比较 | == != > < >= <= |
| 逻辑 | && || ! |
| 三元 | 条件 ? 真值 : 假值 |
变量引用
直接使用变量名即可读取其值:
</let a = 10;
let b = a * 2; /* b = 20 */
apply a + b;/> /* 输出 30 */
完整示例
以下是一个完整的互动叙事脚本——"莱莉菥的早晨":
# 莱莉菥的早晨
你叫**莱莉菥**。
现在是早上六点,你醒了。
你躺在床上。
## 你要怎么做?
</let cntsleep = 0;
label 1;
input case:
'继续睡觉' -> goto 2:
'起床' -> goto 3;
/>
</label 2;
set cntsleep = cntsleep + 1;
if cntsleep > 3 ->goto 4/>
你睡不着。已经尝试了 </apply cntsleep /> 次。
### 状态
- 尝试睡觉次数:</apply cntsleep />
- 当前时间:早上</apply cntsleep+5/>点
</goto 1;/>
</label 3/>
# 结局一:起床
你成功起床了!
> 新的一天开始了,充满无限可能。
</exit/>
</label 4/>
# 结局二:睡觉
你又睡着了。
> 有时候,休息是最好的选择。
</exit/>
执行流程
- 显示开场叙事,声明变量
cntsleep = 0 - 进入
label 1,向玩家展示两个选项 - 选择"继续睡觉" →
cntsleep + 1,显示一段带变量的文本,若cntsleep > 3则跳转结局二,否则循环回label 1 - 选择"起床" → 跳转结局一
语法速查
| 命令 | 语法 | 说明 |
|---|---|---|
let |
let name = expr |
声明变量(可选赋值) |
set |
set name = expr |
修改已声明的变量 |
apply |
apply expr |
行内输出值到文本 |
label |
label name |
定义跳转标签 |
goto |
goto name |
跳转到标签 |
if |
if cond -> cmd |
条件执行命令 |
exit |
exit |
结束脚本 |
input case |
input case [var:] 'opt' -> cmd : ... |
选项输入 |
input text |
input text var |
文本输入 |
log |
log expr |
调试日志 |
random |
random var = min max |
随机整数 |