Skip to content

Weight System

Weight controls the probability of each option being selected in a "pick one from many" scenario. Higher weight = higher chance.

What is Weight

Say you have a loot box with three prize types:

PrizeWeight
Common70
Rare25
Legendary5

Total weight = 70 + 25 + 5 = 100

Probability of each prize = its weight ÷ total weight:

PrizeWeightProbability
Common7070 ÷ 100 = 70%
Rare2525 ÷ 100 = 25%
Legendary55 ÷ 100 = 5%

Key Point

Weights are relative, not percentages. 70:25:5 and 14:5:1 give the same result — only the ratio matters.

Formula

Probability of an item = that item's weight / sum of all weights

For example, Legendary's probability = 5 / (70 + 25 + 5) = 5%.

Selection Process

How Randoms.weightedRandom works:

  1. Sum up all weights into totalWeight (items with weight ≤ 0 are skipped)
  2. Roll a random number in [0, totalWeight)
  3. Walk through the list, accumulating weights
  4. When the accumulated value ≥ roll, return that item

Visualized as a number line:

|--- Common(70) ---|--- Rare(25) ---|-- Legend(5) --|
0                 70              95             100

roll = 82, falls in [70, 95] → "Rare" is selected

Usage

Forge Quality

EmakiForge's quality system uses weights to determine the quality tier of crafted items:

yaml
quality:
  tiers:
    - "Mediocre-60-1.0"    # name-weight-multiplier
    - "Fine-30-1.05"
    - "Flawed-10-0.95"
    - "Superior-5-1.1"
    - "Flawless-2-1.15"
    - "Perfect-1-1.2"

Total weight = 60 + 30 + 10 + 5 + 2 + 1 = 108

QualityWeightProbability
Mediocre60≈ 55.6%
Fine30≈ 27.8%
Flawed10≈ 9.3%
Superior5≈ 4.6%
Flawless2≈ 1.9%
Perfect1≈ 0.9%

Deterministic Selection

Forge quality selection is based on SHA-256 hashing instead of random numbers. The same material combination (rollKey) always yields the same quality, preventing re-rolling. The selection logic is the same as above, just with the random number replaced by a hash value.

General Weighted Random

CoreLib provides a generic weighted random utility that any module can use:

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);

Attribute Combat Power

EmakiAttribute's combat power calculation uses "scores" instead of "weights" — these are value coefficients, not probabilities:

yaml
# attribute_balance.yml
scores:
  physical_attack: 1.00
  physical_defense: 0.78
  health: 0.35
  speed: 0.45
  real_damage: 1.20
Combat Power = physical_attack × 1.00 + physical_defense × 0.78 + health × 0.35 + ...

Here, score means "how much combat power per point of that attribute" — nothing to do with probability.

Weight vs Chance vs Distribution

Three different randomness mechanisms — don't mix them up:

MechanismPurposeConfigNotes
WeightPick one from multiple optionsInteger or floatRelative probability, total doesn't need to be 100
ChanceWhether something happens or not0.0 ~ 1.0Absolute probability, 0.3 = 30%
DistributionGenerate a random numeric valueuniform / gaussian / triangle etc.Controls the shape of value distribution
yaml
# Weight: pick one drop from multiple options
drops:
  - item: "diamond"
    weight: 5
  - item: "gold"
    weight: 30
  - item: "iron"
    weight: 65

# Chance: 30% chance to trigger critical hit
crit_chance: 0.3

# Distribution: damage between 80~120, centered around 100
damage:
  type: gaussian
  mean: 100
  stddev: 10
  min: 80
  max: 120

For detailed distribution configuration, see Expression Engine.

Configuration Tips

  • Integer weights are easier to read: 60:30:10 over 0.6:0.3:0.1
  • Making the total 100 helps with mental math, but it's not required
  • Items with weight 0 or negative are skipped
  • If only one item has weight > 0, it's selected every time
  • For extremely rare results, give it a tiny weight (e.g., 1) and common results a large one (e.g., 100+)

Note

Weight values must be positive. If all items have weight ≤ 0, weightedRandom returns null.

Released under the GPL-3.0 License