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:
| Prize | Weight |
|---|---|
| Common | 70 |
| Rare | 25 |
| Legendary | 5 |
Total weight = 70 + 25 + 5 = 100
Probability of each prize = its weight ÷ total weight:
| Prize | Weight | Probability |
|---|---|---|
| Common | 70 | 70 ÷ 100 = 70% |
| Rare | 25 | 25 ÷ 100 = 25% |
| Legendary | 5 | 5 ÷ 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 weightsFor example, Legendary's probability = 5 / (70 + 25 + 5) = 5%.
Selection Process
How Randoms.weightedRandom works:
- Sum up all weights into
totalWeight(items with weight ≤ 0 are skipped) - Roll a random number in
[0, totalWeight) - Walk through the list, accumulating weights
- 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 selectedUsage
Forge Quality
EmakiForge's quality system uses weights to determine the quality tier of crafted items:
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
| Quality | Weight | Probability |
|---|---|---|
| Mediocre | 60 | ≈ 55.6% |
| Fine | 30 | ≈ 27.8% |
| Flawed | 10 | ≈ 9.3% |
| Superior | 5 | ≈ 4.6% |
| Flawless | 2 | ≈ 1.9% |
| Perfect | 1 | ≈ 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:
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:
# attribute_balance.yml
scores:
physical_attack: 1.00
physical_defense: 0.78
health: 0.35
speed: 0.45
real_damage: 1.20Combat 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:
| Mechanism | Purpose | Config | Notes |
|---|---|---|---|
| Weight | Pick one from multiple options | Integer or float | Relative probability, total doesn't need to be 100 |
| Chance | Whether something happens or not | 0.0 ~ 1.0 | Absolute probability, 0.3 = 30% |
| Distribution | Generate a random numeric value | uniform / gaussian / triangle etc. | Controls the shape of value distribution |
# 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: 120For detailed distribution configuration, see Expression Engine.
Configuration Tips
- Integer weights are easier to read:
60:30:10over0.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.