Skip to content

Instantly share code, notes, and snippets.

@Treeki
Last active October 29, 2025 10:41
Show Gist options
  • Save Treeki/85be14d297c80c8b3c0a76375743325b to your computer and use it in GitHub Desktop.
Save Treeki/85be14d297c80c8b3c0a76375743325b to your computer and use it in GitHub Desktop.

Revisions

  1. Treeki revised this gist Mar 30, 2020. 1 changed file with 42 additions and 32 deletions.
    74 changes: 42 additions & 32 deletions TurnipPrices.cpp
    Original file line number Diff line number Diff line change
    @@ -84,39 +84,44 @@ void Random::getContext(uint32_t *seed1, uint32_t *seed2, uint32_t *seed3, uint3
    }
    } // namespace sead

    uint32_t pf(float f) {
    return *((uint32_t *)&f);
    }
    struct TurnipPrices
    {
    int32_t basePrice;
    int32_t sellPrices[14];
    uint32_t whatPattern;
    int32_t tmp40;

    void calculate();

    // utility stuff for testing
    sead::Random rng;
    bool randbool()
    {
    return (int32_t)rng.getU32() < 0;
    return rng.getU32() & 0x80000000;
    }
    int randint(int min, int max)
    {
    return (((uint64_t)rng.getU32() * (uint64_t)(max - min + 1)) >> 32) + min;
    }
    float randfloat(float min, float max)
    float randfloat(float a, float b)
    {
    uint32_t val = 0x3F800000 | (rng.getU32() >> 9);
    float fval = *(float *)(&val);
    return (fval - 1.0) * (max - min) + min;
    return a + ((fval - 1.0f) * (b - a));
    }
    int intceil(float val)
    {
    return (int)(val + 0.99999999);
    return (int)(val + 0.99999f);
    }
    };

    void TurnipPrices::calculate()
    {
    basePrice = randint(90, 110);
    int chance = randint(0, 99);

    // select the next pattern
    int nextPattern;
    @@ -127,7 +132,6 @@ void TurnipPrices::calculate()
    }
    else
    {
    int chance = randint(0, 99);
    switch (whatPattern)
    {
    case 0:
    @@ -193,7 +197,7 @@ void TurnipPrices::calculate()
    {
    nextPattern = 1;
    }
    else if (chance < 75)
    else if (chance < 85)
    {
    nextPattern = 2;
    }
    @@ -236,7 +240,7 @@ void TurnipPrices::calculate()

    hiPhaseLen1 = randint(0, 6);
    hiPhaseLen2and3 = 7 - hiPhaseLen1;
    hiPhaseLen3 = randint(0, hiPhaseLen2and3);
    hiPhaseLen3 = randint(0, hiPhaseLen2and3 - 1);

    // high phase 1
    for (int i = 0; i < hiPhaseLen1; i++)
    @@ -245,11 +249,12 @@ void TurnipPrices::calculate()
    }

    // decreasing phase 1
    rate = randfloat(0.6, 0.8);
    rate = randfloat(0.8, 0.6);
    for (int i = 0; i < decPhaseLen1; i++)
    {
    sellPrices[work++] = intceil(rate * basePrice);
    rate -= randfloat(0.04, 0.10);
    rate -= 0.04;
    rate -= randfloat(0, 0.06);
    }

    // high phase 2
    @@ -259,11 +264,12 @@ void TurnipPrices::calculate()
    }

    // decreasing phase 2
    rate = randfloat(0.6, 0.8);
    rate = randfloat(0.8, 0.6);
    for (int i = 0; i < decPhaseLen2; i++)
    {
    sellPrices[work++] = intceil(rate * basePrice);
    rate -= randfloat(0.04, 0.10);
    rate -= 0.04;
    rate -= randfloat(0, 0.06);
    }

    // high phase 3
    @@ -275,13 +281,14 @@ void TurnipPrices::calculate()
    case 1:
    // PATTERN 1: decreasing middle, high spike, random low
    peakStart = randint(3, 9);
    rate = randfloat(0.85, 0.9);
    rate = randfloat(0.9, 0.85);
    for (work = 2; work < peakStart; work++)
    {
    sellPrices[work] = intceil(rate * basePrice);
    rate -= randfloat(0.03, 0.05);
    rate -= 0.03;
    rate -= randfloat(0, 0.02);
    }
    sellPrices[work] = intceil(randfloat(0.9, 1.4) * basePrice);
    sellPrices[work++] = intceil(randfloat(0.9, 1.4) * basePrice);
    sellPrices[work++] = intceil(randfloat(1.4, 2.0) * basePrice);
    sellPrices[work++] = intceil(randfloat(2.0, 6.0) * basePrice);
    sellPrices[work++] = intceil(randfloat(1.4, 2.0) * basePrice);
    @@ -293,30 +300,29 @@ void TurnipPrices::calculate()
    break;
    case 2:
    // PATTERN 2: consistently decreasing
    rate = randfloat(0.85, 0.9);
    for (int i = 2; i < 14; i++)
    rate = 0.9;
    rate -= randfloat(0, 0.05);
    for (work = 2; work < 14; work++)
    {
    sellPrices[i] = intceil(rate * basePrice);
    rate -= randfloat(0.03, 0.05);
    sellPrices[work] = intceil(rate * basePrice);
    rate -= 0.03;
    rate -= randfloat(0, 0.02);
    }
    break;
    case 3:
    // PATTERN 3: decreasing, spike, decreasing
    peakStart = randint(2, 9);
    work = 2;

    // decreasing phase before the peak
    if (peakStart > 2)
    rate = randfloat(0.9, 0.4);
    for (work = 2; work < peakStart; work++)
    {
    rate = randfloat(0.4, 0.9);
    for (; work < peakStart; work++)
    {
    sellPrices[work++] = intceil(rate * basePrice);
    rate -= randfloat(0.03, 0.05);
    }
    sellPrices[work] = intceil(rate * basePrice);
    rate -= 0.03;
    rate -= randfloat(0, 0.02);
    }

    sellPrices[work] = intceil(randfloat(0.9, 1.4) * basePrice);
    sellPrices[work++] = intceil(randfloat(0.9, 1.4) * (float)basePrice);
    sellPrices[work++] = intceil(randfloat(0.9, 1.4) * basePrice);
    rate = randfloat(1.4, 2.0);
    sellPrices[work++] = intceil(randfloat(1.4, rate) * basePrice) - 1;
    @@ -326,11 +332,12 @@ void TurnipPrices::calculate()
    // decreasing phase after the peak
    if (work < 14)
    {
    rate = randfloat(0.4, 0.9);
    rate = randfloat(0.9, 0.4);
    for (; work < 14; work++)
    {
    sellPrices[work] = intceil(rate * basePrice);
    rate -= randfloat(0.03, 0.05);
    rate -= 0.03;
    rate -= randfloat(0, 0.02);
    }
    }
    break;
    @@ -344,13 +351,15 @@ int main(int argc, char **argv)
    {
    TurnipPrices turnips;

    if (argc > 1)
    if (argc == 3)
    {
    turnips.rng.init(atoi(argv[1]));
    turnips.whatPattern = atoi(argv[1]);
    turnips.rng.init(atoi(argv[2]));
    }
    else
    {
    turnips.rng.init();
    printf("Usage: %s <pattern> <seed>\n", argv[0]);
    return 0;
    }

    turnips.calculate();
    @@ -363,5 +372,6 @@ int main(int argc, char **argv)
    printf(" %3d %3d %3d %3d %3d %3d\n",
    turnips.sellPrices[3], turnips.sellPrices[5], turnips.sellPrices[7],
    turnips.sellPrices[9], turnips.sellPrices[11], turnips.sellPrices[13]);

    return 0;
    }
  2. Treeki created this gist Mar 30, 2020.
    367 changes: 367 additions & 0 deletions TurnipPrices.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,367 @@
    #include <stdint.h>
    #include <stdio.h>
    #include <stdlib.h>

    // munged from https://github.com/simontime/Resead

    namespace sead
    {
    class Random
    {
    public:
    void init();
    void init(uint32_t seed);
    void init(uint32_t seed1, uint32_t seed2, uint32_t seed3, uint32_t seed4);
    uint32_t getU32();
    uint64_t getU64();
    void getContext(uint32_t *seed1, uint32_t *seed2, uint32_t *seed3, uint32_t *seed4) const;

    private:
    uint32_t mContext[4];
    };

    void Random::init()
    {
    init(42069);
    }

    void Random::init(uint32_t seed)
    {
    mContext[0] = 0x6C078965 * (seed ^ (seed >> 30)) + 1;
    mContext[1] = 0x6C078965 * (mContext[0] ^ (mContext[0] >> 30)) + 2;
    mContext[2] = 0x6C078965 * (mContext[1] ^ (mContext[1] >> 30)) + 3;
    mContext[3] = 0x6C078965 * (mContext[2] ^ (mContext[2] >> 30)) + 4;
    }

    void Random::init(uint32_t seed1, uint32_t seed2, uint32_t seed3, uint32_t seed4)
    {
    if ((seed1 | seed2 | seed3 | seed4) == 0) // seeds must not be all zero.
    {
    seed1 = 1;
    seed2 = 0x6C078967;
    seed3 = 0x714ACB41;
    seed4 = 0x48077044;
    }

    mContext[0] = seed1;
    mContext[1] = seed2;
    mContext[2] = seed3;
    mContext[3] = seed4;
    }

    uint32_t Random::getU32()
    {
    uint32_t n = mContext[0] ^ (mContext[0] << 11);

    mContext[0] = mContext[1];
    mContext[1] = mContext[2];
    mContext[2] = mContext[3];
    mContext[3] = n ^ (n >> 8) ^ mContext[3] ^ (mContext[3] >> 19);

    return mContext[3];
    }

    uint64_t Random::getU64()
    {
    uint32_t n1 = mContext[0] ^ (mContext[0] << 11);
    uint32_t n2 = mContext[1];
    uint32_t n3 = n1 ^ (n1 >> 8) ^ mContext[3];

    mContext[0] = mContext[2];
    mContext[1] = mContext[3];
    mContext[2] = n3 ^ (mContext[3] >> 19);
    mContext[3] = n2 ^ (n2 << 11) ^ ((n2 ^ (n2 << 11)) >> 8) ^ mContext[2] ^ (n3 >> 19);

    return ((uint64_t)mContext[2] << 32) | mContext[3];
    }

    void Random::getContext(uint32_t *seed1, uint32_t *seed2, uint32_t *seed3, uint32_t *seed4) const
    {
    *seed1 = mContext[0];
    *seed2 = mContext[1];
    *seed3 = mContext[2];
    *seed4 = mContext[3];
    }
    } // namespace sead

    struct TurnipPrices
    {
    int32_t basePrice;
    int32_t sellPrices[14];
    uint32_t whatPattern;

    void calculate();

    // utility stuff for testing
    sead::Random rng;
    bool randbool()
    {
    return (int32_t)rng.getU32() < 0;
    }
    int randint(int min, int max)
    {
    return (((uint64_t)rng.getU32() * (uint64_t)(max - min + 1)) >> 32) + min;
    }
    float randfloat(float min, float max)
    {
    uint32_t val = 0x3F800000 | (rng.getU32() >> 9);
    float fval = *(float *)(&val);
    return (fval - 1.0) * (max - min) + min;
    }
    int intceil(float val)
    {
    return (int)(val + 0.99999999);
    }
    };

    void TurnipPrices::calculate()
    {
    basePrice = randint(90, 110);

    // select the next pattern
    int nextPattern;

    if (whatPattern >= 4)
    {
    nextPattern = 2;
    }
    else
    {
    int chance = randint(0, 99);
    switch (whatPattern)
    {
    case 0:
    if (chance < 20)
    {
    nextPattern = 0;
    }
    else if (chance < 50)
    {
    nextPattern = 1;
    }
    else if (chance < 65)
    {
    nextPattern = 2;
    }
    else
    {
    nextPattern = 3;
    }
    break;
    case 1:
    if (chance < 50)
    {
    nextPattern = 0;
    }
    else if (chance < 55)
    {
    nextPattern = 1;
    }
    else if (chance < 75)
    {
    nextPattern = 2;
    }
    else
    {
    nextPattern = 3;
    }
    break;
    case 2:
    if (chance < 25)
    {
    nextPattern = 0;
    }
    else if (chance < 70)
    {
    nextPattern = 1;
    }
    else if (chance < 75)
    {
    nextPattern = 2;
    }
    else
    {
    nextPattern = 3;
    }
    break;
    case 3:
    if (chance < 45)
    {
    nextPattern = 0;
    }
    else if (chance < 70)
    {
    nextPattern = 1;
    }
    else if (chance < 75)
    {
    nextPattern = 2;
    }
    else
    {
    nextPattern = 3;
    }
    break;
    }
    }

    whatPattern = nextPattern;

    /*
    if (checkGlobalFlag("FirstKabuBuy")) {
    if (!checkGlobalFlag("FirstKabuPattern")) {
    setGlobalFlag("FirstKabuPattern", true);
    whatPattern = 3;
    }
    }
    */

    for (int i = 2; i < 14; i++)
    sellPrices[i] = 0;
    sellPrices[0] = basePrice;
    sellPrices[1] = basePrice;

    int work;
    int decPhaseLen1, decPhaseLen2, peakStart;
    int hiPhaseLen1, hiPhaseLen2and3, hiPhaseLen3;
    float rate;

    switch (whatPattern)
    {
    case 0:
    // PATTERN 0: high, decreasing, high, decreasing, high
    work = 2;
    decPhaseLen1 = randbool() ? 3 : 2;
    decPhaseLen2 = 5 - decPhaseLen1;

    hiPhaseLen1 = randint(0, 6);
    hiPhaseLen2and3 = 7 - hiPhaseLen1;
    hiPhaseLen3 = randint(0, hiPhaseLen2and3);

    // high phase 1
    for (int i = 0; i < hiPhaseLen1; i++)
    {
    sellPrices[work++] = intceil(randfloat(0.9, 1.4) * basePrice);
    }

    // decreasing phase 1
    rate = randfloat(0.6, 0.8);
    for (int i = 0; i < decPhaseLen1; i++)
    {
    sellPrices[work++] = intceil(rate * basePrice);
    rate -= randfloat(0.04, 0.10);
    }

    // high phase 2
    for (int i = 0; i < (hiPhaseLen2and3 - hiPhaseLen3); i++)
    {
    sellPrices[work++] = intceil(randfloat(0.9, 1.4) * basePrice);
    }

    // decreasing phase 2
    rate = randfloat(0.6, 0.8);
    for (int i = 0; i < decPhaseLen2; i++)
    {
    sellPrices[work++] = intceil(rate * basePrice);
    rate -= randfloat(0.04, 0.10);
    }

    // high phase 3
    for (int i = 0; i < hiPhaseLen3; i++)
    {
    sellPrices[work++] = intceil(randfloat(0.9, 1.4) * basePrice);
    }
    break;
    case 1:
    // PATTERN 1: decreasing middle, high spike, random low
    peakStart = randint(3, 9);
    rate = randfloat(0.85, 0.9);
    for (work = 2; work < peakStart; work++)
    {
    sellPrices[work] = intceil(rate * basePrice);
    rate -= randfloat(0.03, 0.05);
    }
    sellPrices[work] = intceil(randfloat(0.9, 1.4) * basePrice);
    sellPrices[work++] = intceil(randfloat(1.4, 2.0) * basePrice);
    sellPrices[work++] = intceil(randfloat(2.0, 6.0) * basePrice);
    sellPrices[work++] = intceil(randfloat(1.4, 2.0) * basePrice);
    sellPrices[work++] = intceil(randfloat(0.9, 1.4) * basePrice);
    for (; work < 14; work++)
    {
    sellPrices[work] = intceil(randfloat(0.4, 0.9) * basePrice);
    }
    break;
    case 2:
    // PATTERN 2: consistently decreasing
    rate = randfloat(0.85, 0.9);
    for (int i = 2; i < 14; i++)
    {
    sellPrices[i] = intceil(rate * basePrice);
    rate -= randfloat(0.03, 0.05);
    }
    break;
    case 3:
    // PATTERN 3: decreasing, spike, decreasing
    peakStart = randint(2, 9);
    work = 2;

    // decreasing phase before the peak
    if (peakStart > 2)
    {
    rate = randfloat(0.4, 0.9);
    for (; work < peakStart; work++)
    {
    sellPrices[work++] = intceil(rate * basePrice);
    rate -= randfloat(0.03, 0.05);
    }
    }

    sellPrices[work] = intceil(randfloat(0.9, 1.4) * basePrice);
    sellPrices[work++] = intceil(randfloat(0.9, 1.4) * basePrice);
    rate = randfloat(1.4, 2.0);
    sellPrices[work++] = intceil(randfloat(1.4, rate) * basePrice) - 1;
    sellPrices[work++] = intceil(rate * basePrice);
    sellPrices[work++] = intceil(randfloat(1.4, rate) * basePrice) - 1;

    // decreasing phase after the peak
    if (work < 14)
    {
    rate = randfloat(0.4, 0.9);
    for (; work < 14; work++)
    {
    sellPrices[work] = intceil(rate * basePrice);
    rate -= randfloat(0.03, 0.05);
    }
    }
    break;
    }

    sellPrices[0] = 0;
    sellPrices[1] = 0;
    }

    int main(int argc, char **argv)
    {
    TurnipPrices turnips;

    if (argc > 1)
    {
    turnips.rng.init(atoi(argv[1]));
    }
    else
    {
    turnips.rng.init();
    }

    turnips.calculate();
    printf("Pattern %d:\n", turnips.whatPattern);
    printf("Sun Mon Tue Wed Thu Fri Sat\n");
    printf("%3d %3d %3d %3d %3d %3d %3d\n",
    turnips.basePrice,
    turnips.sellPrices[2], turnips.sellPrices[4], turnips.sellPrices[6],
    turnips.sellPrices[8], turnips.sellPrices[10], turnips.sellPrices[12]);
    printf(" %3d %3d %3d %3d %3d %3d\n",
    turnips.sellPrices[3], turnips.sellPrices[5], turnips.sellPrices[7],
    turnips.sellPrices[9], turnips.sellPrices[11], turnips.sellPrices[13]);
    return 0;
    }