交互式解谜游戏插件,修改自锈湖桌游

一款交互式解谜游戏插件,玩家以第一人称视角探索神秘房间,通过收集物品、解锁谜题逐步揭开真相。
作者: 蜥蜴


背景

线下组织解谜类桌游时,通常需要一位主持人负责描述房间环境、判定玩家操作、记录物品与进度。随着房间与谜题数量增加,主持人的负担会显著上升,玩家也难以在中途暂停后继续。

koishi-plugin-rusty-lake-lizard 将房间探索、物品收集与谜题判定交由机器人执行,并自动保存游戏进度,玩家可在群聊或私聊中完成完整的解谜流程。


工具定位

koishi-plugin-rusty-lake-lizard 是一款基于 Koishi 框架的交互式解谜游戏插件。游戏内容修改自锈湖桌游,主要能力如下:

能力 说明
多人房间 支持创建、加入与删除游戏房间
房间探索 逐房间探索,查看环境描述与图片
物品收集 收集并使用物品推动解谜流程
场景移动 在已访问过的房间之间移动
进度保存 游戏进度自动存入数据库
交互判定 根据输入触发对应的谜题与机关

当前版本为 1.0.2,依赖 Koishi ^4.18.10,需搭配数据库服务使用。


安装

前置条件

  • 已搭建并可正常运行的 Koishi 项目(koishi-app)
  • 已启用 Koishi 的数据库服务(插件声明 inject: ['database'],游戏进度依赖数据库持久化)

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

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

方式二:通过 npm 安装

在 Koishi 项目根目录执行:

1
npm install koishi-plugin-rusty-lake-lizard

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

1
2
3
plugins:
rusty-lake-lizard:
timeout: 15000

方式三:通过 yarn / pnpm 安装

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

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

# pnpm
pnpm add koishi-plugin-rusty-lake-lizard

启用数据库

游戏进度依赖数据库持久化。若项目尚未配置,可在控制台「插件配置」中找到 database-sqlite 并启用:

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

保存配置后重启 Koishi 项目,即可正常使用。

验证安装

在任意已接入机器人的聊天窗口输入:

1
锈湖 说明

若能返回玩法介绍文本,则说明安装成功。


配置

配置项

参数 类型 默认值 取值范围 说明
timeout number 15000 ≤ 60000 交互等待超时时长,单位为毫秒

配置示例

1
2
3
plugins:
rusty-lake-lizard:
timeout: 15000

timeout 控制各交互环节的等待时长,例如房间选择、物品选择和谜题输入。默认 15000 毫秒(15 秒),最大 60000 毫秒。


游戏玩法

规则概述

  • 玩家以第一人称视角探索一个神秘房间系统
  • 每个房间都有独特的描述、物品与谜题
  • 需要通过逻辑推理与物品交互解锁通往其他房间的通路
  • 游戏记录会自动保存,可随时中断并继续
  • 同一房间可容纳多名玩家,进度在房间成员之间同步

房间与物品

游戏包含若干可探索的房间,例如卧室、走廊、厨房、化学实验室、电气室、办公室与隐藏房间。玩家在探索过程中可收集纸条、钥匙、烧杯、保险丝等物品,并在合适的场景中使用以推进解谜。

解谜线索分布在不同房间,需要跨房间收集与推理。


使用流程

指令为 锈湖,别名 rl。

指令列表

指令 说明
锈湖 说明 查看玩法介绍
锈湖 新建 新建游戏房间
锈湖 加入 加入已有游戏房间
锈湖 删除 清除游戏房间
锈湖 房间 查看已访问的房间
锈湖 移动 移动到其他房间
锈湖 物品 查看已拥有的物品
锈湖 查看 <目标> 探索场景或物品

流程一:新建房间

步骤 1:新建游戏房间

1
锈湖 新建

若当前用户已加入某个房间,插件返回「你已经加入了一个房间,无法重复创建。」

步骤 2:输入房间名称

按提示输入房间名称:

1
我的锈湖房间

若名称为空或超时,插件返回「输入超时或名称为空。」;若已存在同名房间,返回「已经存在同名的房间。」

步骤 3:开始游戏

创建成功后插件自动将创建者加入房间,并返回当前场景名、提示与房间配图:

1
2
3
成功创建房间:我的锈湖房间,已自动为您加入
当前所在场景:卧室
使用"锈湖 查看"指令查看当前场景。例如:"锈湖 查看 监控"

此时已进入初始房间「卧室」。


流程二:加入房间

步骤 1:加入已有房间

1
锈湖 加入

若当前用户已加入某个房间,插件返回「你已经加入了一个房间,无法重复加入。」;若无任何房间,返回「当前没有任何房间可以加入。」

步骤 2:选择房间

按提示输入房间序号。加入成功后插件返回房间名与当前场景,并附带配图。房间成员之间共享同一份进度。


流程三:探索与解谜

步骤 1:查看当前场景

1
锈湖 查看 床

锈湖 查看 <目标> 是探索的核心指令,可用的「目标」取决于当前所在房间。例如在卧室中可尝试:

1
2
3
4
锈湖 查看 床
锈湖 查看 抽屉
锈湖 查看 地毯
锈湖 查看 门

不同房间支持的目标各不相同,例如厨房可查看水槽、咖啡机、垃圾桶;办公室可查看电脑、书架、海报等。若目标无法识别,插件返回「你观察了一会,并没有什么特别的发现。」

步骤 2:收集物品

探索过程中会获得物品,插件会返回对应描述,并提示可在物品指令中查看:

1
2
你在床铺的垫子下发现了半张纸条。
(可在物品指令中查看)

步骤 3:查看已有物品

1
锈湖 物品

若拥有物品,插件返回带序号的物品列表:

1
2
3
4
5
6
你拥有的物品有:
1: 半张纸条a
2: 手电筒
3: 上锁的盒子

请输入物品编号查看详情,输入 0 取消。

输入编号后返回物品详情与配图;输入 0 取消操作。

步骤 4:移动房间

1
锈湖 移动

插件列出可前往的房间:

1
2
3
你可以前往以下房间,请输入序号选择:
1: 走廊
2: 厨房

输入序号后移动到目标房间,返回该房间的描述与配图。若没有可前往的房间,插件返回「你无处可去,只能在这里活动。」。

步骤 5:查看已访问的房间

1
锈湖 房间

插件返回当前所在房间、配图与已访问的房间列表。输入房间编号可回顾该房间的环境信息。

步骤 6:触发谜题

部分目标需要进一步交互,例如输入密码、选择道具、确认操作(「是/否」)。插件会按提示等待输入,超出 timeout 时长则视为取消或超时。


流程四:删除房间

步骤 1:发送删除指令

1
锈湖 删除

步骤 2:选择要删除的房间

插件列出所有房间:

1
2
3
4
5
输入序号选择要删除的房间:
1: 我的锈湖房间
2: 其他房间

输入 0 删除所有房间

输入序号删除对应房间及其成员记录;输入 0 删除全部房间。删除操作会一并清除该房间的所有成员记录,请谨慎操作。


使用场景

场景一:多人协作解谜

多名玩家加入同一房间后共享进度,可在群聊中协作分头探索不同房间,再汇总线索。

场景二:单人独自游玩

单人也可创建房间独自游玩,适合在私聊中逐步推进解谜流程。

场景三:中途存档继续

进度自动保存至数据库,可随时中断,之后通过 锈湖 房间、锈湖 物品 继续之前的流程。


技术实现

技术栈

技术 用途
Koishi 机器人框架
TypeScript 开发语言
数据库服务 保存房间与玩家进度
静态资源 房间与物品配图

数据表结构

插件通过 ctx.model.extend 扩展了两张表。

rusty_lake_games 表存储房间状态:

字段 类型 说明
id string 主键
gameId string 房间标识
gameName string 房间名称
currentRoom string 当前所在房间
inventory json 已拥有的物品
visitedRooms json 已访问的房间
doneTasks json 已完成的任务

rusty_lake_players 表存储玩家与房间的关联:

字段 类型 说明
id string 主键
gameId string 房间标识
userId string 用户 ID

核心设计

状态读取

玩家的房间状态通过玩家记录与房间记录关联获取:

1
2
const player = await ctx.database.get('rusty_lake_players', { userId: session.userId });
const game = await ctx.database.get('rusty_lake_games', { gameId: player[0].gameId });

若玩家未加入任何房间,抛出「你还未加入任何游戏。」。

房间与物品数据

房间、物品的描述与图片集中在 data.ts 中管理。图片以 base64 形式内联,随消息一起发送:

1
2
3
4
function loadImage(file: string) {
const buffer = fs.readFileSync(file);
return `data:image/png;base64,${buffer.toString('base64')}`;
}

场景探索

锈湖 查看 <目标> 通过 handleRoomPoint 分发到各房间的处理函数,每个房间根据目标关键词匹配并返回结果。未匹配到时统一返回「你观察了一会,并没有什么特别的发现。」。

物品与任务更新

物品的增删与任务的完成通过 gamestate.ts 中的辅助函数写入数据库,例如:

1
2
3
4
5
export async function addItemToInventory(ctx: Context, session: Session, item: string) {
const state = await getState(ctx, session);
const newInventory = [...state.inventory, item];
await ctx.database.upsert('rusty_lake_games', [{ ...state, inventory: newInventory }]);
}

房间移动

移动时从已访问的房间中筛除当前房间,作为可选项:

1
2
3
const availableRooms = rooms.filter(room =>
state.visitedRooms.includes(room.id) && room.id !== state.currentRoom
);

交互等待

各交互环节通过 session.prompt(Config.timeout) 等待用户输入。超时后返回相应提示,例如「选择超时。」「输入超时。」


注意事项

1. 数据库依赖

插件声明了 inject: ['database'],房间与进度均依赖数据库持久化。若未启用数据库服务,指令将不可用。

2. 加入后进度同步

加入房间后进度在房间成员之间同步,请谨慎选择房间。同一用户不能同时加入多个房间。

3. 删除不可撤销

删除房间会一并删除该房间所有成员的游戏记录,操作不可撤销。删除前插件会列出所有房间供选择。

4. 交互超时

各交互环节存在等待时长(默认为 15 秒)。超时后会取消当前操作,需重新发起。

5. 文本线索

游戏中的文本描述包含重要的解谜线索,建议仔细阅读,避免遗漏关键信息。


常见问题

Q1:输入指令无响应?

依次检查以下项:

  • 插件是否已在控制台启用
  • 数据库服务是否已启用
  • 机器人是否已成功连接至目标平台
  • 指令是否完整输入

Q2:提示「你还未加入任何游戏」?

说明当前用户尚未加入任何房间。可通过 锈湖 新建 创建房间,或 锈湖 加入 加入已有房间。

Q3:无法重复创建或加入房间?

同一用户不能同时加入多个房间。若已加入,需先由房间管理员通过 锈湖 删除 清理,或使用其他账号。

Q4:可以中途退出再继续吗?

可以。游戏进度会自动保存,之后通过 锈湖 房间、锈湖 物品 等指令继续推进。

Q5:多名玩家可以同时探索吗?

可以。同一房间的成员共享同一份进度,可在群聊中协作分头探索不同房间。

Q6:某个「查看」目标没有反应?

说明该目标在当前房间中不存在,或尚未满足触发条件。插件会返回「你观察了一会,并没有什么特别的发现。」。建议先收集线索与物品后再尝试。

Q7:删除房间会影响到其他房间吗?

不会。除「输入 0 删除所有房间」外,删除操作仅作用于所选房间及其成员记录。


获取工具