While watching this overexplained replay, the player commented on how he chose a particular path with the belief that 'spreading out' elite fights in betwixt your normal enemies would increase the chance of finding more rare card(s).

Slay the spire pulls its card picks by first rolling for a type (common, uncommon, or rare) and then by pulling a random card from said type, with each type member having equal probability. The type roll is weighted random, in the following way:

There's a hidden variable c, the common counter. Probabilities of cards start at P = [-2%, 37%, 63%] for rare, uncommon, common cards respectively. Whenever a common card is rolled, in pseudocode:

if(P[0] < 43%) P[0] += 1%; 
if(P[0] > 0% && P[0] < 43%) P[2] -= 1%;

Whenever a rare card is rolled, the probabilities reset to the base values of P = [-2%, 37%, 63%] again. On elite fights, the rare chance is modified: it is instead P[0] + 10% while the common chance is P[2] - 10%. In shops, it is P[0] + 6% and P[2] - 6%

The chart below illustrates the mechanic very insightfully:

![Graph of rare card chance

At the start of each Act, the chance of finding a Rare card is also reset, due to bosses always dropping a choice between 3 rares.


At the start of the act, the player will typically decide which path to take through the act, which to start from. When planning ahead, it may be insightful to know whether or not the specific sequence of enemies will impact the expected number of rare cards received.

We want to maximize the above. Does a sequence like rrrErrrE "spreading out the elite fights" compare favourably to one such as rrrEErrr "bunching them up"?

  • 1
    That's some good probability theory question for a sites like mathematics. Finding bugs in your simulation code posted on Arqade? Thanks, but no. – Sinatr Jul 20 at 14:31

The short answer: No. The opposite is true.


I wrote a little console program to test this, simulating 108 times and outputting the no. of rare cards you expect to see. (Takes about a minute to run on a modern CPU). It allows any act path as input and outputs the number of rare cards seen in card rewardsnote. Here is the result:

Simulate rare chance. Input a string formatted like rrresrrre. r = regular, e =
elite, s = shop.
It is assumed shop rares are not bought
Input: rrrerrre
Result: 2.4346
Input: rrreerrr
Result: 2.5110
Input: rrrerre
Result: 2.0444
Input: rrreerr
Result: 2.1136
Input: rrrere
Result: 1.6491
Input: rrreer
Result: 1.6962

Note: Due to the law of large numbers, the outputs above are accurate to 4 decimal places, and very accurate to 3 decimal places. (Increasing the simulation count will make the results more accurate, at the cost of linearly more time).

We can see there is a significant disadvantage in the number of rares seen to the method suggested in the video and thus actually doing the opposite of said technique has merit! On average, an act with 3 fights, one elite, 3 fights, one elite will see 0.076 less rare cards than one where 3 fights, two elites, 3 fights are chosen as the path. With 3-2, we see a difference of 0.069, and with 3-1, there's a difference of 0.047 rares.

Note: simulating events and modifying card rewards with certain relics left as an exercise to the reader. My hypothesis is that the underlying result is unlikely to change: only the magnitude of the effect may vary.

Source code (C#) below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace raresExpected {

class Program {
    static void Main(string[] args) {
        string input;
        System.Console.WriteLine("Simulate rare chance. Input a string formatted like rrresrrre. r = regular, e = elite, s = shop.");
        System.Console.WriteLine("It is assumed shop rares are not bought");
        do {
            System.Console.Write("Input: ");
            input = System.Console.ReadLine();
            double result = estimate(input.ToLowerInvariant());
            System.Console.WriteLine("Result: " + result.ToString("N4"));
        while (input != "" && input != "exit");
    static double estimate(string input) {
        int simulations = 100000000;
        double total = 0;
        Random rand = new Random();
        char[] ca = input.ToCharArray();
        for (int i = 0; i < simulations; ++i) {
            // Ok not to use Kahan: the numbers will be close.
            total += runSimulation(ca, rand);
        return total / simulations;
    static int runSimulation(char[] input, Random rand) {
        int cards;
        int rares = 0;
        int p = -2; // Probability
        int mod = 0;
        int q = 0; // Modified probability
        int r = 0; // Running total
        foreach (char c in input) {
            if (c == 'r') {
                mod = 10;
                cards = 3;
            } else if (c == 'e') {
                mod = 0;
                cards = 3;
            } else if (c == 's') {
                mod = 6;
                cards = 7;
            } else {
                cards = 0;
            for (int i = 0; i < cards; ++i) {
                q = p + mod;
                r = rand.Next() % 100;
                if (r < q) {
                    if (c != 's') {
                    p = -2;
                } else  if (r > q + 0.37) {
                    // Common card is rolled. 
        return rares;
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.