纸片化学社区版 · 数据格式

本文档定义数据源(远程服务器)提供的数据格式。游戏运行时通过 DownloadManagerGameManager.data_origin(数据源根 URL)下载数据,并加载到 GameManager 的各字典中。

本文档由 AI 生成,对应数据后端 0.1.1 版本。

目录结构(数据源服务器端)

<data_origin>/
├── index.json               # 数据源信息
├── card/list.json           # 卡牌索引
├── card/id/{id}             # 某张卡牌的详细定义(文本,JSON 格式)
├── reaction/list.json       # 反应索引
├── reaction/id/{id}         # 某条反应的详细定义
├── matter/list.json         # 物质索引
├── matter/id/{id}           # 某物质的详细定义
└── asset/list.json          # 图片与音频资源索引
    ├── asset/pic/{id}       # 图片文件
    └── asset/sound/{id}     # 音频文件

index.json

{
  "name": "数据源名称",
  "uuid": "c8f3b2a1-...(唯一标识,用于本地缓存目录名)"
}

list.json(三类通用结构)

cardreactionmatter 的 list.json 均为「id → 文件名」映射:

{
  "card-h": "H",
  "card-o": "O",
  "card-ignite": "点燃·升温"
}

客户端下载后按文件名保存为 cards/H.jsoncards/点燃·升温.json 等,load_resource() 会读取每个详细定义并以 id 为键存入对应字典。

asset/list.json

{
  "pics": {
    "pic-metal-fe": "fe.png"
  },
  "sounds": {
    "sound-hit": "hit.ogg"
  }
}

卡牌定义(card/*.json)

{
  "id": "card-h",
  "name": "H",
  "name_en": "Hydrogen",
  "type": "atom",
  "category": "nonmetal",
  "count": 4,
  "pic": "pic-metal-fe",
  "effects": ["IGNITE", "HEAT"]
}
字段类型必填说明
idstring卡牌唯一标识
namestring牌面名称(中文)
name_enstring英文名称
typestringatom 原子牌 / group 原子团牌 / condition 条件牌 / sequence 定序牌 / electron 电子层牌 / count 计数牌
categorystringmetal 金属 / nonmetal 非金属 / group 原子团
countint单局单种卡牌数量上限:整局游戏中该卡牌在「牌堆+手牌+反应区+元素区+弃牌堆」的总张数上限(即放入牌堆的张数),默认 4;设为 0 或负数表示本局不使用该卡牌
picstring对应 asset/list.jsonpics 的键
elementstring元素符号(如 HOFe),条件牌可省略
effectsstring[]条件牌效果,见下方「条件效果枚举」
condition_effectint条件牌主效果数值(与 effects[0] 等价,供 _get_condition_effect 读取)

单局单种卡牌数量上限(count

count 字段定义某张卡牌在一局游戏中的总张数上限。引擎在开局初始化牌堆时,每种卡牌恰好放入 count 张;此后所有操作(发牌、摸牌、调度、O2、结晶、提取、增益、攻击者/队友补牌等)只在不同区域间移动卡牌,总量守恒,因此任意时刻该卡牌在「牌堆+手牌+反应区+元素区+弃牌堆」中的总张数都不会超过 count

  • 默认值:4
  • count <= 0:该卡牌本局不进入牌堆(不参与游戏)。
  • 引擎提供 GameLoopManager.get_card_count_limit(card_id)(单种上限)与 GameLoopManager.get_card_global_count(card_id)(当前整局总张数)查询接口;若数据异常导致某卡牌整局总张数超过上限,引擎会剔除该张并打印告警(见 _draw_from_deck)。

条件效果枚举(effects 合法值)

对应 GameLoopManager.ConditionEffect说明
IGNITE0点燃:作为反应条件或否决降温,默认自带氧气
HEAT1升温:作为反应条件或否决降温
DISSOLVE2溶解:自带水,使与水反应的物质发生反应
COOL3降温:否决升温/点燃
FILTER4过滤:除去自己反应区内固体类一般伤害物
COLLECT_GAS5集气:除去自己反应区内所有气体
EXTRACT6提取:取走他人区域中一种非生成物物质或元素
CRYSTALLIZE7结晶:从弃牌堆取牌组成晶体加入手牌

物质定义(matter/*.json)

物质定义驱动「伤害自动分类」,是结算阶段的唯一数据依据。

{
  "id": "matter-h2so4",
  "formula": "H2SO4",
  "composition": ["H", "H", "S", "O", "O", "O", "O"],
  "state": "liquid",
  "solubility": "soluble",
  "categories": ["strong_acid", "corrosive"],
  "damage_type": "CORROSION",
  "corrosion_strength": "strong",
  "is_illegal_attack": false,
  "is_harmless_gas": false,
  "is_generated_water": false,
  "special": []
}
字段类型必填说明
idstring物质唯一标识
formulastring化学式(与 substance 的 formula 字段匹配)
compositionstring[]组成该物质的元素/原子团牌名列表(供 UI 组合提示)
statestringsolid / liquid / gas(常温常压物态)
solubilitystringsoluble(可/易/微溶) / insoluble(难溶)
categoriesstring[]分类标签,见下方「物质分类标签」
damage_typestring显式指定伤害类型:CORROSION / POISONING / GENERAL;省略则由 categories 自动推导
corrosion_strengthstring腐蚀物强度:strong(强酸/强碱,结算扣 2n)/ weak(可溶性弱酸/弱碱,扣 n)
is_illegal_attackbool是否是非法进攻物质(金属碳化物、金属氢化物、金属氧化物、金属硅化物、固体单质、有机物、配合物、混盐等),不可直接进攻打出
is_harmless_gasbool是否是无害气体(结算二后进入弃牌堆)
is_generated_waterbool是否是生成的水(结算二后进入弃牌堆)
specialstring[]特殊物质标签:O2(可回复/摸牌)、H2(生成使攻击来源摸一张牌)等

物质分类标签(categories 合法值)

标签推导出的伤害类型结算规则
strong_acidCORROSION强酸,结算阶段扣 2n 层电子
strong_baseCORROSION强碱,结算阶段扣 2n 层电子
weak_acid(可溶性弱酸)CORROSION扣 n 层电子
weak_base(可溶性弱碱)CORROSION扣 n 层电子
toxic_gasPOISONING毒气,扣 n 层电子
toxic_liquidPOISONING有毒纯液体,扣 n 层电子
cyanidePOISONING氰化物,扣 n 层电子
insoluble_salt_baseGENERAL难溶性酸碱盐,扣 n 层电子
complete_hydrolysis_solidGENERAL广义完全水解固体,扣 n 层电子
solid_elementGENERAL固体单质,扣 n 层电子
solid_oxideGENERAL固体氧化物,扣 n 层电子

分类重复规则:一个物质可同时属于多个分类(如 Zn(CN)₂ 既是 cyanide 又是 insoluble_salt_base),但伤害不叠加,按「最早的结算时机」结算:

  1. GENERAL(结算阶段一)优先于 POISONING / CORROSION(结算阶段二)
  2. POISONING 优先于 CORROSION

引擎在 _auto_classify_damage() 中按此优先级自动推导 damage_type;若定义中显式写了 damage_type,则以其为准。

已配平产物与无伤害物质:不包含上述任何 categories 的物质的 damage_typenull(非伤害物),可用于暗攻、反应中间体等。


反应定义(reaction/*.json)

反应定义驱动「自动反应引擎」。引擎在反应区内为每个玩家的物质自动匹配反应,遵循规则「反应区内能反应物质之间会立即发生反应」。

{
  "id": "reaction-h2so4-naoh",
  "reactants": ["matter-h2so4", "matter-naoh"],
  "products": ["matter-na2so4", "matter-h2o"],
  "conditions": [],
  "priority": 0
}
{
  "id": "reaction-mg-ignite",
  "reactants": ["matter-mg", "matter-o2"],
  "products": ["matter-mgo"],
  "conditions": ["IGNITE"],
  "priority": 1
}
字段类型必填说明
idstring反应唯一标识
reactantsstring[]反应物 matter id 数组;引擎在反应区内按顺序各匹配一个
productsstring[]生成物 matter id 数组;全新 substance 会写入反应区(进攻)或直接弃置(防御)
conditionsstring[]必需的条件效果(IGNITE / HEAT / DISSOLVE 等);需反应区中有物质携带对应 condition_effects 才可触发
priorityint匹配优先级,数值大者优先匹配,默认 0

反应语义

  • 进攻 / 辅助 / 暗攻 / 补伤触发:反应物被消耗(其卡片组合进生成物),生成物留在反应区,参与伤害结算;自动完成伤害分类。
  • 防御触发:反应物被消耗,生成物直接进入弃牌堆,视为防御成功。
  • 条件消耗:反应要求 conditions 时,参与反应的条件效果视为被该反应消耗,条件牌随反应物一并进入弃牌堆。
  • 递归触发:生成物可能继续与反应区其他物质反应,引擎会反复匹配直到无反应可发生(最多 32 轮,防止死循环)。
  • 产物的 source_player_id:取参与反应物中 timestamp 最大者(即「最后补全的人」),保证伤害来源正确。

客户端加载结果(GameManager 字典)

DownloadManager.load_resource() 加载后:

字典结构
GameManager.card_list{ "card-h": { ...卡牌定义... }, ... }
GameManager.matter_list{ "matter-h2so4": { ...物质定义... }, ... }
GameManager.reaction_list{ "reaction-h2so4-naoh": { ...反应定义... }, ... }
GameManager.pic_list{ "pic-metal-fe": "fe.png", ... }
GameManager.sound_list{ "sound-hit": "hit.ogg", ... }

兼容性:若某个详细定义文件不存在(旧版数据源),对应键保留 list.json 中的原始文件名字符串,游戏逻辑可通过 is Dictionary 判断。


物质实例(substance_data)字段约定

引擎在 create_substance_data() 基础上补充/修正以下字段,供 UI 与结算读取:

字段类型说明
matter_idstring关联的物质定义 id(由 _auto_classify_damage()formula 匹配填充)
damage_typeint伤害类型(GameLoopManager.DamageType),由物质分类自动推导
is_strong_acid_basebool强酸碱标记(影响腐蚀结算扣 2n)
is_harmfulbool是否为伤害性物质(damage_type != null 且非生成水/无害气体)
is_illegal_attackbool非法进攻标记(不可直接进攻打出)
is_gas / is_harmless_gasbool气体 / 无害气体标记(集气、结算二清除用)
is_generated_waterbool生成的水标记(结算二清除用)
is_productbool是否为反应生成物(提取/结晶限制用)
is_dark_attackbool是否暗攻产物
source_player_idint伤害来源玩家
timestampint打出时间戳(后置先发结算顺序用)
condition_card_idsstring[]附加条件牌 id
condition_effectsint[]附加条件效果(ConditionEffect 枚举值)