权重系统 (Weight)
权重用来控制"多选一"时各选项被选中的概率。权重越大,被选中的概率越高。
什么是权重
假设有一个抽奖箱,里面有三种奖品:
| 奖品 | 权重 |
|---|---|
| 普通奖品 | 70 |
| 稀有奖品 | 25 |
| 传说奖品 | 5 |
权重总和 = 70 + 25 + 5 = 100
每种奖品被抽中的概率 = 自身权重 ÷ 权重总和:
| 奖品 | 权重 | 概率 |
|---|---|---|
| 普通奖品 | 70 | 70 ÷ 100 = 70% |
| 稀有奖品 | 25 | 25 ÷ 100 = 25% |
| 传说奖品 | 5 | 5 ÷ 100 = 5% |
关键点
权重是相对值,不是百分比。70:25:5 和 14:5:1 效果完全一样——只有比例关系决定概率。
计算公式
某项的概率 = 该项的权重 / 所有项的权重之和比如传说奖品的概率 = 5 / (70 + 25 + 5) = 5%。
选取流程
Randoms.weightedRandom 的工作方式:
- 算出所有项的权重总和
totalWeight(权重 ≤ 0 的项跳过) - 在
[0, totalWeight)范围内掷一个随机数roll - 从头到尾遍历列表,逐项累加权重
- 累加值 ≥
roll时,返回当前项
用数轴来理解:
|--- 普通(70) ---|--- 稀有(25) ---|-- 传说(5) --|
0 70 95 100
roll = 82,落在 [70, 95] 区间 → 选中"稀有"使用场景
锻造品质
EmakiForge 的品质系统用权重决定锻造产物的品质等级:
yaml
quality:
tiers:
- "平庸-60-1.0" # 名称-权重-倍率
- "精良-30-1.05"
- "有缺-10-0.95"
- "优质-5-1.1"
- "无暇-2-1.15"
- "完美-1-1.2"权重总和 = 60 + 30 + 10 + 5 + 2 + 1 = 108
| 品质 | 权重 | 概率 |
|---|---|---|
| 平庸 | 60 | ≈ 55.6% |
| 精良 | 30 | ≈ 27.8% |
| 有缺 | 10 | ≈ 9.3% |
| 优质 | 5 | ≈ 4.6% |
| 无暇 | 2 | ≈ 1.9% |
| 完美 | 1 | ≈ 0.9% |
确定性抽取
锻造品质的抽取基于 SHA-256 哈希而不是随机数。相同的材料组合(rollKey)永远产出相同品质,防止反复刷取。选取逻辑和上面一样,只是把随机数换成了哈希值。
通用加权随机
CoreLib 提供了通用的加权随机工具,各模块都能直接用:
java
import emaki.jiuwu.craft.corelib.math.Randoms;
import emaki.jiuwu.craft.corelib.math.Randoms.Weighted;
List<Weighted<String>> pool = List.of(
new Weighted<>("common_drop", 70.0),
new Weighted<>("rare_drop", 25.0),
new Weighted<>("legendary_drop", 5.0)
);
String result = Randoms.weightedRandom(pool);属性战斗力
EmakiAttribute 的战斗力计算用到了"分数"(score)而不是"权重"——这里是价值系数,不是概率:
yaml
# attribute_balance.yml
scores:
physical_attack: 1.00
physical_defense: 0.78
health: 0.35
speed: 0.45
real_damage: 1.20战斗力 = 物理攻击 × 1.00 + 物理防御 × 0.78 + 生命值 × 0.35 + ...这里的分数表示"每一点属性值换算多少战斗力",和概率没关系。
权重 vs 概率 vs 随机分布
三种不同的随机机制,别搞混:
| 机制 | 用途 | 配置方式 | 说明 |
|---|---|---|---|
| 权重 (weight) | 从多个选项中选一个 | 整数或浮点数 | 相对概率,总和不需要是 100 |
| 概率 (chance) | 判断某件事是否发生 | 0.0 ~ 1.0 | 绝对概率,0.3 = 30% 几率 |
| 随机分布 (distribution) | 生成一个随机数值 | uniform / gaussian / triangle 等 | 控制数值的分布形状 |
yaml
# 权重:从多个掉落物中选一个
drops:
- item: "diamond"
weight: 5
- item: "gold"
weight: 30
- item: "iron"
weight: 65
# 概率:30% 几率触发暴击
crit_chance: 0.3
# 随机分布:伤害在 80~120 之间,集中在 100 附近
damage:
type: gaussian
mean: 100
stddev: 10
min: 80
max: 120随机分布的详细配置见 表达式引擎。
配置建议
- 用整数权重更直观,
60:30:10比0.6:0.3:0.1好读 - 权重总和凑成 100 方便心算概率,但不是必须的
- 权重为 0 或负数的项会被跳过,不参与抽取
- 只有一个项权重 > 0 时,它 100% 被选中
- 想做极稀有结果,给它一个很小的权重(如 1),常见结果给大权重(如 100+)
注意
权重值必须是正数。所有项权重都 ≤ 0 时,weightedRandom 返回 null。