戦闘後に表示される3枚のカード報酬。
「レアは3%」という話はよく知られていますが、実際の抽選はもっと複雑です。
この記事では、デコンパイルで確認したコードをもとに、
- レア確率補正(rareOffset)の仕組み
- 3枚が同時抽選かどうか
- 同じカードが重複しない理由
を整理します。
結論:3枚は同時抽選ではなく、左から1枚ずつ処理される
まず前提として、戦闘後カード報酬の初期(1枚目)のレアリティ確率は、
以下の「基本テーブル」からスタートします。
- Rare:3%
- Uncommon:37%
- Common:60%
この確率は1枚目の抽選時点では固定です。
しかし、ここから先は毎回同じ確率で抽選されるわけではありません。
- 3枚は順番に生成される
- 各抽選ごとにrareOffsetが更新される
- その結果、2枚目・3枚目のレア確率は1枚目と同じとは限らない
つまり、1枚目の結果が2枚目・3枚目に影響するという仕組みです。
どこを見れば抽選ロジックが確認できる?
PC版 Slay the Spire では、デコンパイルにより内部ロジックを確認できます。
🔎 重要クラス
- AbstractDungeon
- CardRewardScreen
- RewardItem
- CardLibrary
特に重要なのは:
AbstractDungeon.getCardRarity()
ここに「レア確率補正(rareOffset)」の処理があります。
実際のロジック(概念コード)
デコンパイルすると、概念的には次のようなコードになっています。
public static AbstractCard.CardRarity getCardRarity() {
int roll = cardRandomRng.random(99);
if (roll < 3 + rareOffset) {
rareOffset = -5;
return AbstractCard.CardRarity.RARE;
} else if (roll < 40) {
return AbstractCard.CardRarity.UNCOMMON;
} else {
rareOffset++;
return AbstractCard.CardRarity.COMMON;
}
}
※実際のコードはもう少し分岐がありますが、本質はこの構造です。
補正の仕組み(コード上の事実)
初期値
rareOffset = 0;
// つまり3%
Rareが出た場合
rareOffset = -5;
// つまり3 - 5 => -2% => 0%
Commonが出た場合
rareOffset++;
// ++は 1加算するということ
上限処理
rareOffset = Math.min(rareOffset, 37);
rareOffsetの最大値は37。
基礎3% + 37% = Rare最大40%になります。
3枚はどう生成されるのか?(イメージ)
報酬生成は概ね次のようなループ構造です。
const rewardCards = [];
let rareOffset = 0;
for (let i = 0; i < 3; i++) {
const rarity = getCardRarity(); // rareOffsetを参照
const card = pickCardByRarity(rarity);
rewardCards.push(card);
}
重要なのは:
- getCardRarity() が3回呼ばれる
- 呼ばれるたびにrareOffsetが更新される
つまり、3枚は同じ確率で同時抽選されるわけではありません。
同じカードは重複しないのか?
これもコード上で確認できます。
カード生成は以下の処理内で行われます:
- CardLibrary.getAnyColorCard(…)
- AbstractDungeon.getRewardCards()
内部では:
- ArrayList<AbstractCard> rewardCards
- 既に選ばれたカードを除外
という処理が入っています。
つまり:
✅ 同一ドロップ内で同じカードは選ばれない
注意点(重要)
- Switch / PS / モバイル版はビルドが異なる可能性あり
- アップデートで微修正が入る可能性あり
- Mod環境ではロジックが上書きされる場合がある
レアが増加した場合の他の数値は?
レア確率がrareOffsetによって増加した場合、他のレアリティはどうなるのでしょうか?
内部ロジックを見ると、Uncommon(アンコモン)の確率は固定で、Common(コモン)が調整役になっています。
基本構造
- Rare:3% + rareOffset
- Uncommon:37%(固定)
- Common:残り(100% − Rare − 37%)
つまり、Rareが増えた分だけCommonが減少する仕組みです。
具体例
① 初期状態(rareOffset = 0)
- Rare:3%
- Uncommon:37%
- Common:60%
② コモンが続いてrareOffset = +2 の場合
- Rare:5%
- Uncommon:37%
- Common:58%
Rareが2%増えた分、Commonが2%減っています。
③ Rare最大(40%)まで上昇した場合
- Rare:40%
- Uncommon:37%
- Common:23%
Rareが大きく増えると、Commonは大きく圧縮されます。
エリートを倒した時の確率は?
エリート戦のカード報酬は、通常戦闘(ザコ戦)とは異なり、レア確率にボーナス補正が入ります。
基本の違い
- 通常戦闘:Rare 3%
- エリート戦:Rare 3% + 10%
つまり、エリート戦では初期レア確率が13%からスタートします。
エリート戦のレアリティ抽選構造
エリート戦では、rareOffsetとは別に+10%のボーナスが加算されます。
概念的には次のような構造になります。
public static AbstractCard.CardRarity getCardRarityElite() {
int roll = cardRandomRng.random(99);
// 通常の3%にエリートボーナス+10%
if (roll < 13 + rareOffset) {
rareOffset = -5;
return AbstractCard.CardRarity.RARE;
} else if (roll < 50) {
// 13% + 37% = 50%
return AbstractCard.CardRarity.UNCOMMON;
} else {
rareOffset++;
return AbstractCard.CardRarity.COMMON;
}
}
※実際のコードは内部で条件分岐されていますが、確率構造はこの形です。
エリート戦の確率テーブル(初期状態)
- Rare:13%
- Uncommon:37%
- Common:50%
通常戦闘(3 / 37 / 60)と比べると、
Rareが+10%され、その分Commonが減少しています。
補正込みの最大値
rareOffsetの最大は+37(Rare最大40%)ですが、
エリート戦では初期が13%なので、
- Rare最大:50%
- Uncommon:37%
- Common最小:13%
まで上昇する可能性があります。
重要ポイント
- エリート戦でも3枚は順番に抽選
- rareOffsetは共有される
- Rareが出ると補正はリセット
つまり、エリート戦は
「レアが出やすい初期状態から始まる通常抽選」
と理解すると分かりやすいです。
補足:各色カードのレアリティ、分類の種類数は?
| キャラクター | Common | Uncommon | Rare |
|---|---|---|---|
| アイアンクラッド(赤) | 20 | 36 | 16 |
| サイレント(緑) | 19 | 33 | 19 |
| ディフェクト(青) | 18 | 36 | 17 |
| ウォッチャー(紫) | 19 | 35 | 17 |
まとめ
- レア確率は固定3%ではない
- rareOffsetにより確率は変動する
- 3枚は同時抽選ではなく、左から順番に抽選
- 同一カードは同一ドロップ内では重複しない
- Rareが増えると、その分だけCommonが減る
- Uncommonは常に37%で固定
- Rare最大40%時、Commonは最小23%


コメント