阿瓦隆游戏插件

由机器人担任主持人的阿瓦隆游戏插件,支持角色分配、任务投票、刺杀与湖中仙女等完整规则。
作者: 蜥蜴


背景

阿瓦隆(Avalon)是一款经典的推理与欺骗类桌游,规则上接近狼人杀,但对信息管理与逻辑推演的要求更高。线下进行时需要一位主持人完成以下工作:

  1. 分配身份,向每位玩家单独告知其角色与可见信息
  2. 逐轮指定发车人、记录任务成员
  3. 收集投票并公布结果
  4. 处理刺杀、湖中仙女等特殊机制

若由玩家兼任主持人,则主持人需提前知晓全部身份,可能影响游戏公平。koishi-plugin-avalon-lizard 将上述流程交由机器人执行,玩家可以完整地参与游戏本身。


工具定位

koishi-plugin-avalon-lizard 是一款由机器人驱动的阿瓦隆游戏插件,主要能力如下:

能力 说明
自动化角色分配 按玩家人数从固定角色池中分配正义/邪恶角色
私密身份通知 通过私聊向每位玩家发送角色、阵营与可见信息
任务与投票管理 记录任务成员、统计投票并公布结果
特殊机制支持 刺杀、湖中仙女查验
角色与规则查询 提供角色信息与完整规则的查询指令

当前版本为 2.1.0,依赖 Koishi ^4.18.11。


游戏基础

阵营与目标

阵营 包含角色 胜利条件
正义阵营 梅林、派西维尔、忠臣、好兰斯洛特 成功完成 3 次任务
邪恶阵营 莫甘娜、刺客、爪牙、莫德雷德、奥伯伦、坏兰斯洛特 使 3 次任务失败,或刺杀梅林成功

角色一览

角色 阵营 任务 投票权限 可见信息
梅林 正义 隐藏身份取得胜利 仅可投成功 除莫德雷德外的全部邪恶阵营
派西维尔 正义 保护梅林 仅可投成功 梅林与莫甘娜(不区分)
忠臣 正义 保护梅林 仅可投成功 无
好兰斯洛特 正义 保护梅林 仅可投成功 坏兰斯洛特
莫甘娜 邪恶 破坏任务 可投成功或失败 除奥伯伦外的邪恶阵营
刺客 邪恶 破坏任务或刺杀梅林 可投成功或失败 除奥伯伦外的邪恶阵营
爪牙 邪恶 破坏任务 可投成功或失败 除奥伯伦外的邪恶阵营
莫德雷德 邪恶 破坏任务 可投成功或失败 除奥伯伦外的邪恶阵营
奥伯伦 邪恶 破坏任务 可投成功或失败 无(独立)
坏兰斯洛特 邪恶 破坏任务 可投成功或失败 好兰斯洛特

安装

前置条件

  • 已搭建并可正常运行的 Koishi 项目(koishi-app)
  • 已启用 Koishi 的数据库服务(插件声明 inject: ['database'])
  • 机器人具备向玩家发送私聊消息的权限

方式一:通过插件市场安装(推荐)

  1. 启动 Koishi 项目,打开控制台(默认地址 http://localhost:5140)。
  2. 进入左侧「插件市场」。
  3. 在搜索框中输入 avalon-lizard。
  4. 找到插件后点击「添加」,Koishi 会自动完成依赖安装与配置写入。

方式二:通过 npm 安装

在 Koishi 项目根目录执行:

1
npm install koishi-plugin-avalon-lizard

随后在 koishi.yml 中手动添加配置:

1
2
plugins:
avalon-lizard: {}

方式三:通过 yarn / pnpm 安装

若项目使用 yarn 或 pnpm,可执行:

1
2
3
4
5
# yarn
yarn add koishi-plugin-avalon-lizard

# pnpm
pnpm add koishi-plugin-avalon-lizard

启用数据库

插件声明了 inject: ['database'],需确保 Koishi 中已启用数据库服务。若尚未配置,可在控制台「插件配置」中启用 database-sqlite:

1
2
3
plugins:
database-sqlite:
path: data/koishi.db

保存配置后重启 Koishi 项目。

资源文件

插件包含角色头像图片(位于 assets/ 目录),会随 npm 包一同安装。若图片缺失,角色信息仍会以文字形式正常显示。

验证安装

在任意已接入机器人的群聊中输入:

1
阿瓦隆 规则

若能返回完整规则文本,则说明安装成功。


配置

当前版本无需额外配置,安装并启用即可使用:

1
2
plugins:
avalon-lizard: {}

使用流程

父指令为 阿瓦隆,别名 avalon。

完整指令列表

指令 说明 使用位置
阿瓦隆 开始 开始新一局游戏 群聊
阿瓦隆 加入 加入当前游戏 群聊
阿瓦隆 分配 分配角色(5-11 人) 群聊
阿瓦隆 发车 <玩家名> 选择任务成员 群聊(发车人)
阿瓦隆 投票 <成功/失败> 任务投票 私聊(任务成员)
阿瓦隆 刺杀 <玩家名> 刺客刺杀梅林 群聊(刺客)
阿瓦隆 查验 <玩家名> 湖中仙女查验 私聊(车长)
阿瓦隆 角色 <角色名> 查看单个角色信息 群聊 / 私聊
阿瓦隆 规则 查看完整规则 群聊 / 私聊
阿瓦隆 结束 结束当前游戏 群聊

流程一:开局与角色分配

步骤 1:创建游戏

由任意玩家在群聊中发起:

1
阿瓦隆 开始

机器人返回「阿瓦隆游戏开始,输入”阿瓦隆 加入”加入游戏。」,并将该群聊锁定为本局游戏频道。同一时间仅支持一个游戏频道。

步骤 2:玩家加入

每位玩家在群聊中输入:

1
阿瓦隆 加入

每成功加入一次,机器人返回「<玩家名> 已加入!当前 N 人」。重复加入会被提示「你已经加入了游戏。」。

支持人数为 5 至 11 人。

步骤 3:分配角色

人数满足要求后,由任意玩家在群聊中输入:

1
阿瓦隆 分配

机器人随机打乱玩家顺序,按人数对应的角色配置进行分配,并通过私聊向每位玩家发送:

  • 角色头像
  • 角色名称与阵营
  • 该角色的任务说明
  • 投票权限说明
  • 该角色可见的其他玩家(视角色而定)

随后在群聊中公布第 1 轮任务的发车人与所需人数。


流程二:任务阶段(逐轮重复)

步骤 1:发车

被随机指定的发车人在群聊中选择本轮任务成员:

1
阿瓦隆 发车 玩家A,玩家B

注意事项:

  • 玩家名之间使用英文逗号或中文逗号分隔,均支持
  • 玩家名需与游戏内显示名称完全一致(含大小写)
  • 成员数量必须与当前轮次要求的人数一致,否则机器人会提示所需人数
  • 仅当前发车人可执行该指令

步骤 2:私聊投票

被选中的玩家通过私聊进行投票:

1
2
阿瓦隆 投票 成功
阿瓦隆 投票 失败

规则约束:

  • 每位任务成员仅可投票一次
  • 正义阵营角色仅可投「成功」,邪恶阵营角色可投「成功」或「失败」
  • 机器人不会对「正义阵营投失败」做出拦截,需要玩家自觉遵守角色规则

投票完成后,机器人会在群聊中广播「<玩家名> 已投票。」,待全部成员投票完毕后公布结果。

步骤 3:公布任务结果

机器人公布投票统计与任务结果:

1
票数:成功 X / 失败 Y。任务成功!/ 任务失败!

判定规则:

  • 默认情况下,只要出现 1 票失败即判定任务失败
  • 第 4 轮任务且玩家人数为 7 至 11 人 时,需出现 2 票及以上失败才判定任务失败

步骤 4:进入下一轮

若未达到胜负条件,机器人自动推进至下一轮,并指定新的发车人、公布所需人数。


流程三:胜负判定与刺杀

步骤 1:胜负条件

  • 正义阵营任务成功次数达到 3 次 → 进入刺杀环节
  • 邪恶阵营任务失败次数达到 3 次 → 邪恶阵营直接胜利,游戏结束

步骤 2:刺客发动刺杀

当正义阵营即将达到 3 次成功时,机器人会在群聊中提示:

1
2
正义阵营即将胜利!
刺客 <玩家名>,请刺杀梅林:阿瓦隆 刺杀 玩家名

刺客在群聊中执行:

1
阿瓦隆 刺杀 玩家A

结果:

  • 目标为梅林:刺杀成功,邪恶阵营胜利
  • 目标非梅林:刺杀失败,正义阵营胜利

刺杀成功或失败后,游戏立即结束。


流程四:湖中仙女(8-11 人局)

在 8-11 人局中,第 2、3、4 轮任务发车前,车长可以通过私聊查验一名玩家的阵营:

1
阿瓦隆 查验 玩家A

执行条件:

  • 玩家人数在 8 至 11 之间
  • 当前轮次为第 2、3 或 4 轮
  • 执行者须为当前轮次的车长
  • 当前轮次尚未使用过查验

查验后,机器人私聊告知执行者目标玩家的阵营,并在群聊中广播「车长查验了 <玩家名> 的身份。」。每轮仅可使用一次查验。


流程五:查询角色与规则

查看完整规则:

1
阿瓦隆 规则

查看某个角色的详细信息(仅支持代码中已定义的角色名):

1
2
阿瓦隆 角色 梅林
阿瓦隆 角色 刺客

若输入未定义的角色名,机器人将返回全部支持的角色列表。


流程六:结束游戏

任何时候均可提前结束当前游戏:

1
阿瓦隆 结束

机器人返回「游戏已结束。」,并解除对当前频道的占用。


角色配置与任务人数

各人数角色分配

人数 正义阵营 邪恶阵营
5 梅林、派西维尔、忠臣 莫甘娜、刺客
6 梅林、派西维尔、忠臣 ×2 莫甘娜、刺客
7 梅林、派西维尔、忠臣 ×2 莫甘娜、刺客、爪牙
8 梅林、派西维尔、忠臣 ×3 莫甘娜、刺客、爪牙
9 梅林、派西维尔、忠臣 ×3 莫甘娜、刺客、奥伯伦、莫德雷德
10 梅林、派西维尔、忠臣 ×4 莫甘娜、刺客、奥伯伦、莫德雷德
11 梅林、派西维尔、忠臣 ×3、好兰斯洛特 莫甘娜、刺客、奥伯伦、莫德雷德、坏兰斯洛特

各人数任务人数

人数 第 1 轮 第 2 轮 第 3 轮 第 4 轮 第 5 轮
5 2 3 2 3 3
6 2 3 4 3 4
7 2 3 3 4 4
8 3 4 4 5 5
9 3 4 4 5 5
10 3 4 4 5 5
11 3 4 5 6 6

完整对局示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
[群聊] 玩家A:阿瓦隆 开始
[机器人] 阿瓦隆游戏开始,输入"阿瓦隆 加入"加入游戏。

[群聊] 玩家A:阿瓦隆 加入
[机器人] 玩家A 已加入!当前 1 人

[群聊] 玩家B:阿瓦隆 加入
[机器人] 玩家B 已加入!当前 2 人

(其余玩家依次加入)

[群聊] 玩家A:阿瓦隆 分配
[机器人] 角色已分配!第 1 轮需要 2 人。发车人:玩家A

[私聊] 玩家A ← 机器人:[角色头像]
你的角色是:梅林,你是正义阵营。
隐藏身份,避免被刺杀。只能投成功。
邪恶阵营(除莫德雷德):玩家C, 玩家E

[私聊] 玩家C ← 机器人:[角色头像]
你的角色是:刺客,你是邪恶阵营。
破坏任务。可投成功或失败。
邪恶阵营(除奥伯伦):玩家E

[群聊] 玩家A:阿瓦隆 发车 玩家A,玩家B
[机器人] 成员:玩家A, 玩家B。请投票。

[私聊] 玩家A → 机器人:阿瓦隆 投票 成功
[机器人] 投票成功。

[群聊] 机器人:玩家A 已投票。
[群聊] 机器人:玩家B 已投票。
[群聊] 机器人:票数:成功 2 / 失败 0。任务成功!

[群聊] 机器人:下一轮发车人:玩家B。需要 3 人。

(后续轮次省略)

[群聊] 机器人:正义阵营即将胜利!
刺客 玩家C,请刺杀梅林:阿瓦隆 刺杀 玩家名

[群聊] 玩家C:阿瓦隆 刺杀 玩家A
[机器人] 刺杀成功!邪恶阵营胜利!

技术实现

技术栈

技术 用途
Koishi 机器人框架
TypeScript 开发语言
私聊 API 向玩家秘密发送角色信息

核心设计

全局游戏状态

游戏状态保存在 apply 函数内的局部变量中:

1
2
let game: Game = { players: [], missionResults: [], round: 0, started: false, ... };
let fixedChannelId: string | undefined;

fixedChannelId 记录本局游戏锁定的群聊,用于统一广播。游戏未开始时该值为 undefined,因此同一时间仅支持一个游戏频道。

角色分配

按玩家人数从 roleDistribution 中取出正义与邪恶角色列表,将玩家随机打乱后依次填充:

1
2
3
4
5
6
const dist = roleDistribution[num];
const shuffled = [...game.players].sort(() => Math.random() - 0.5);
shuffled.forEach((p, i) => {
p.role = i < dist.good.length ? dist.good[i] : dist.evil[i - dist.good.length];
p.team = i < dist.good.length ? 'good' : 'evil';
});

私密通知

角色信息通过 Koishi 的私聊接口发送:

1
2
const whisper = async (s: any, uid: string, msg: string) =>
s.bot.sendPrivateMessage(uid, msg);

每位玩家收到的信息包含角色头像与角色/阵营/可见信息等文本内容,由角色名称通过 switch 分支分别构造。

任务判定

投票完成后统计成功与失败票数,并根据轮次与人数决定判定规则:

1
2
const need2Fail = game.round === 4 && [7, 8, 9, 10, 11].includes(game.players.length);
const success = need2Fail ? fail < 2 : fail === 0;

发车人与轮次推进

发车人在玩家数组中按顺序轮转:

1
game.currentLeaderIndex = (game.currentLeaderIndex + 1) % game.players.length;

查验次数控制

湖中仙女查验通过复用玩家的 voted 标记限制每轮仅一次:

1
game.players[game.currentLeaderIndex]!.voted = true;

注意事项

1. 昵称设置

发车指令按玩家名精确匹配,建议玩家在开局前使用简洁昵称(如「小明」「小红」),避免使用特殊符号或表情,便于其他玩家输入。

2. 私聊权限

机器人的角色分配、投票与查验均依赖私聊。请确保:

  • 机器人未被玩家屏蔽
  • 玩家未开启「禁止陌生人私聊」
  • 机器人所在平台支持私聊消息

3. 单频道限制

插件同时仅支持一个频道进行游戏。若在多个群聊同时使用,可能出现频道广播混乱。

4. 游戏状态不持久化

游戏状态保存在内存中,机器人重启后数据会丢失。已进行中的对局需要重新开始。

5. 投票需全员参与

任务投票需要全部任务成员完成,任一玩家长时间不投票会导致游戏停滞。开局前建议确认所有玩家均可及时响应。

6. 第 4 轮特殊规则

在 7-11 人局中,第 4 轮任务需出现 2 票及以上失败才判定失败。这一规则与常规轮次不同,玩家需注意。


常见问题

Q1:为什么收到的角色信息没有头像图片?

角色头像通过 assets/ 目录下的本地图片以文件 URL 形式发送。若图片缺失,机器人会自动降级为纯文字发送角色信息,不影响游戏进行。

Q2:发车时提示「未找到部分玩家」?

说明所填玩家名与游戏内显示名不完全一致。请核对大小写与前后空格,建议开局前统一使用简洁昵称。

Q3:私聊没有收到角色信息?

可能原因包括:

  • 机器人被玩家屏蔽
  • 玩家开启了「禁止陌生人私聊」
  • 机器人所在平台不支持私聊消息

建议确认上述条件后重新开始游戏。

Q4:游戏进行中卡住怎么办?

任务投票需要全部任务成员完成。可在群聊中提醒未投票的玩家;若长时间无法继续,可由任意玩家执行 阿瓦隆 结束 强制结束本局。

Q5:为什么我的投票被判为无效?

可能原因包括:

  • 你不在本轮任务成员列表中
  • 你已投过票
  • 投票参数不是「成功」或「失败」

Q6:刺杀指令由谁执行?

刺杀由持有刺客角色的玩家执行,在正义阵营完成 3 次任务后由机器人在群聊中提示。

Q7:8 人以上局如何触发湖中仙女?

湖中仙女在 8-11 人局自动生效,无需额外开启。第 2、3、4 轮任务发车前,由当轮车长私聊执行 阿瓦隆 查验 玩家名,每轮限一次。

Q8:安装后指令无响应?

依次检查以下项:

  • 插件是否已在控制台启用
  • 数据库服务是否已启用
  • 机器人是否已连接目标平台
  • 指令是否完整输入(父指令与子指令之间以空格分隔)

开发计划

  • 支持多频道同时进行游戏
  • 增加游戏状态持久化
  • 支持自定义角色配置
  • 增加游戏日志记录
  • 优化湖中仙女交互方式

获取工具