8 个版本

0.4.1 2021 年 7 月 23 日
0.4.0 2021 年 7 月 23 日
0.3.0 2020 年 3 月 4 日
0.2.1 2020 年 2 月 4 日
0.1.2 2020 年 2 月 4 日

#605 in Game dev

28 每月下载量
storylets 中使用

MIT 许可证

190KB
5K SLoC

宝座

Crates.io Docs Status

原型设计和故事逻辑的游戏脚本语言

// Declare the initial state as 'phrases', with one phrase per line.
Mary is sister of David
Sarah is child of Mary
Tom is child of David

// Define rules with the format: INPUT = OUTPUT.
CHILD is child of PARENT . AUNT is sister of PARENT .
    COUSIN is child of AUNT = COUSIN is cousin of CHILD

// The final state will be:
//    Sarah is cousin of Tom

动机

宝座的灵感来源于用于编写交互式小说的语言,例如 Inform。如 这篇文章 所述,Inform 可以用来原型设计除了交互式小说之外的游戏类型。通过定义游戏规则,可以避免通用编程语言中的许多冗余。然而,Inform 和其他交互式小说创作系统在实时游戏循环的每一帧中执行其规则的速度太慢,并且难以嵌入现有引擎。

宝座允许通过规则定义游戏逻辑,因此提供了一些类似 Inform 这样的基于规则语言的优点,但执行速度快,且易于嵌入现有引擎。其语法受到 Ceptre 编程语言的影响。

参考

规则格式为 输入 = 输出,其中 输入输出 是使用点(.)作为项目之间分隔符的列表

  • 输入 是一个条件列表,必须通过这些条件才能执行规则。条件可以是必须存在的状态短语或必须评估为真的谓词(例如使用前缀表示法的 >)。任何匹配的状态短语在执行规则时将被规则消耗。
  • 输出 是一个状态短语列表,如果执行规则,将由规则生成。
  • 规则中使用全部大写字母的标识符(如上面片段中的 CHILDPARENTAUNTCOUSIN)是将在规则执行时分配的变量。

评估宝座脚本涉及执行任何匹配当前状态规则的规则,直到匹配规则的集合耗尽。规则以随机顺序执行,并且可能执行多次。

谓词

以下谓词可以用作规则输入列表中的一个项目

语法 效果 示例
+X Y Z XY 之和等于 Z 时匹配 + 健康 10 已修复
-X Y Z 当 Y 和 Z 的和等于 X 时匹配 - 健康 10 损坏
<X Y 当 X 小于 Y 时匹配 < 金钱 0
>X Y 当 X 大于 Y 时匹配 > 金钱 0
<=X Y 当 X 小于等于 Y 时匹配 <= 金钱 0
>=X Y 当 X 大于等于 Y 时匹配 >= 金钱 0
%X Y Z 当 X 与 Y 的模等于 Z 时匹配 % 360 REM
=X Y 当 X 等于 Y 时匹配 = 健康 100
!X 当 X 不存在于状态时匹配 !此不存在
^X 调用宿主应用程序并根据响应进行匹配 ^操作系统-时钟-小时12

当一个谓词接受两个输入变量时,这两个变量都必须为谓词指定一个值,谓词才能产生匹配。值可以通过直接编写常量或通过与其他规则输入共享变量来指定。当谓词接受三个输入变量且其中一个变量未分配时,它将被分配根据谓词的效果期望的值,例如在 A 将在 + 2 A 10 中分配值为 8

构建

存在特殊语法,以便更容易编写复杂规则,但最终这些结构将编译成引言中描述的简单形式。下表列出了可用的结构

语法 效果 示例 编译形式
$ 为前缀的输入短语 将输入短语复制到规则输出。 $foo =bar foo=bar.foo
INPUT: 前缀的括号内的规则集,其中 INPUT 是短语列表 INPUT 复制到每个规则输入。
foo . bar: {
hello = world
123 = 456
}
foo . bar . hello = world
foo . bar . 123 = 456
<<PHRASE . PHRASES,其中 PHRASE 是单个短语,而 PHRASES 是短语列表 <<PHRASE 替换为 PHRASES,无论它在规则输入列表中的位置如何。
<<arithmetic A B . + A 1 B
<<arithmetic A B . - A 1 B
foo . <<arithmetic X Y = Y
foo . + X 1 Y = Y
foo . - X 1 Y = Y

原子 ()

最后,() 是状态的缺失。当它在规则输出列表中存在时,它没有效果,除了使编写不产生输出的规则(例如 foo = ())成为可能。当它在规则输入列表中存在时,它具有在没有任何其他规则可以匹配时产生匹配的效果。例如,在以下脚本中,第一个规则将始终最后匹配

foo           // initial state
() . bar = () // matched last
foo = bar     // matched first

通过这种方式,() 可以用作控制流的形式,覆盖规则执行的常规随机顺序。

示例

  • blocks - 一个简单的拼图匹配游戏,通过 cargo run --example blocks 运行。
  • throne-playground - Throne 的一个基于网页的编辑器。
  • Urban Gift - 使用 Throne 进行游戏逻辑。

为 Wasm 构建

  1. 运行 cargo install wasm-pack 安装 wasm-pack
  2. 在此目录下运行 npm install ; npm start

依赖项

~5–7MB
~128K SLoC