Skip to content

权重系统 (Weight)

权重用来控制"多选一"时各选项被选中的概率。权重越大,被选中的概率越高。

什么是权重

假设有一个抽奖箱,里面有三种奖品:

奖品权重
普通奖品70
稀有奖品25
传说奖品5

权重总和 = 70 + 25 + 5 = 100

每种奖品被抽中的概率 = 自身权重 ÷ 权重总和:

奖品权重概率
普通奖品7070 ÷ 100 = 70%
稀有奖品2525 ÷ 100 = 25%
传说奖品55 ÷ 100 = 5%

关键点

权重是相对值,不是百分比。70:25:514:5:1 效果完全一样——只有比例关系决定概率。

计算公式

某项的概率 = 该项的权重 / 所有项的权重之和

比如传说奖品的概率 = 5 / (70 + 25 + 5) = 5%。

选取流程

Randoms.weightedRandom 的工作方式:

  1. 算出所有项的权重总和 totalWeight(权重 ≤ 0 的项跳过)
  2. [0, totalWeight) 范围内掷一个随机数 roll
  3. 从头到尾遍历列表,逐项累加权重
  4. 累加值 ≥ 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:100.6:0.3:0.1 好读
  • 权重总和凑成 100 方便心算概率,但不是必须的
  • 权重为 0 或负数的项会被跳过,不参与抽取
  • 只有一个项权重 > 0 时,它 100% 被选中
  • 想做极稀有结果,给它一个很小的权重(如 1),常见结果给大权重(如 100+)

注意

权重值必须是正数。所有项权重都 ≤ 0 时,weightedRandom 返回 null

Released under the GPL-3.0 License