mirror of
https://github.com/ACreTeam/ac-decomp
synced 2026-06-04 10:26:19 -04:00
246 lines
8.6 KiB
C
246 lines
8.6 KiB
C
#include "m_kabu_manager.h"
|
|
|
|
#include "lb_rtc.h"
|
|
#include "m_common_data.h"
|
|
#include "libc64/qrand.h"
|
|
|
|
#define TRADE_MARKET_ODDS_NUM (Kabu_TRADE_MARKET_TYPE_NUM - 1)
|
|
|
|
/**
|
|
* @brief Set Stalk Market update time to current day at 00:00.
|
|
**/
|
|
static void Kabu_set_schedule_day() {
|
|
lbRTC_time_c* kabu_update_time = Save_GetPointer(kabu_price_schedule.update_time);
|
|
|
|
/* copy current date-time */
|
|
lbRTC_TimeCopy(kabu_update_time, Common_GetPointer(time.rtc_time));
|
|
|
|
/* set time to beginning of day */
|
|
kabu_update_time->hour = 0;
|
|
kabu_update_time->min = 0;
|
|
kabu_update_time->sec = 0;
|
|
|
|
/* back-track to the last Sunday */
|
|
lbRTC_Sub_DD(kabu_update_time, kabu_update_time->weekday);
|
|
kabu_update_time->weekday = lbRTC_SUNDAY;
|
|
}
|
|
|
|
/**
|
|
* @brief Decide a new Stalk Market trend using the last trend for % odds.
|
|
**/
|
|
static void Kabu_decide_trade_market() {
|
|
static f32 next_trade_market_typeA[TRADE_MARKET_ODDS_NUM] = {
|
|
0.5f, /* Type A (50%) */
|
|
0.3f /* Type B (30%) */
|
|
//0.2f /* Type C (20%) */
|
|
};
|
|
|
|
static f32 next_trade_market_typeB[TRADE_MARKET_ODDS_NUM] = {
|
|
0.6f, /* Type A (60%) */
|
|
0.2f /* Type B (20%) */
|
|
//0.1f /* Type C (20%) */
|
|
};
|
|
|
|
static f32 next_trade_market_typeC[TRADE_MARKET_ODDS_NUM] = {
|
|
0.6f, /* Type A (60%) */
|
|
0.3f /* Type B (30%) */
|
|
//0.1f /* Type C (10%) */
|
|
};
|
|
|
|
static f32* next_trade_market[Kabu_TRADE_MARKET_TYPE_NUM] = {
|
|
next_trade_market_typeA, next_trade_market_typeB, next_trade_market_typeC
|
|
};
|
|
|
|
f32* next_type_market = next_trade_market[Save_Get(kabu_price_schedule.trade_market)];
|
|
f32 chosen = fqrand(); /* [0.0f, 1.0f) */
|
|
int i;
|
|
|
|
/* Subtract odds from chosen until we're below the current odds, or reach the last market type */
|
|
for (i = 0; i < TRADE_MARKET_ODDS_NUM; i++) {
|
|
if (chosen < *next_type_market) {
|
|
break;
|
|
}
|
|
|
|
chosen -= *next_type_market;
|
|
next_type_market++;
|
|
}
|
|
|
|
if (i < Kabu_TRADE_MARKET_TYPE_START || i >= Kabu_TRADE_MARKET_TYPE_NUM) {
|
|
i = 0;
|
|
}
|
|
|
|
Save_Set(kabu_price_schedule.trade_market, i);
|
|
}
|
|
|
|
/* Predeclare schedule function defs */
|
|
static void Kabu_decide_price_schedule_typeA();
|
|
static void Kabu_decide_price_schedule_typeB();
|
|
static void Kabu_decide_price_schedule_typeC();
|
|
|
|
#define TRADE_MARKET_A_SPIKE_DAYS 5
|
|
#define TRADE_MARKET_A_SPIKE_DAY_BEGIN lbRTC_MONDAY
|
|
#define TRADE_MARKET_A_SPIKE_MULTIPLIER 8.0f
|
|
|
|
/**
|
|
* @brief Generate weekly Stalk Market prices in a 'random' trend. With one huge spike.
|
|
*
|
|
* The spike day will be [Monday, Friday], and will always be 8 times the Sunday buy price.
|
|
**/
|
|
static void Kabu_decide_price_schedule_typeA() {
|
|
f32 spike_price;
|
|
int spike_day;
|
|
|
|
Kabu_decide_price_schedule_typeB(); /* start with a 'random' trend */
|
|
|
|
/* determine spike price & spike day */
|
|
spike_price = Save_Get(kabu_price_schedule.daily_price[lbRTC_SUNDAY]) * TRADE_MARKET_A_SPIKE_MULTIPLIER;
|
|
spike_day = fqrand() * TRADE_MARKET_A_SPIKE_DAYS;
|
|
spike_day += lbRTC_MONDAY;
|
|
Save_Set(kabu_price_schedule.daily_price[spike_day], spike_price);
|
|
}
|
|
|
|
#define TRADE_MARKET_B_SUNDAY_PRICE_MULT 0.8f /* 0.8x (80%) minimum possible price */
|
|
#define TRADE_MARKET_B_PRICE_INCREASE_START 1.05f /* 1.05x (105%) initial increase rate */
|
|
#define TRADE_MARKET_B_PRICE_DECREASE_RATE 0.7f /* 0.7x (70%) static decrease rate */
|
|
#define TRADE_MARKET_B_PRICE_INCREASE_RATE 0.01f /* 1% linear increase percent rate */
|
|
#define TRADE_MARKET_B_PRICE_DECREASE_ODDS_START 0.1f /* 10% initial decrease chance */
|
|
#define TRADE_MARKET_B_PRICE_DECREASE_ODDS_RATE 0.14f /* 14% decrease percentage increase rate */
|
|
#define TRADE_MARKET_B_PRICE_DECREASE_LOWER_RATE 0.3f /* 30% decrease percentage decrease rate */
|
|
|
|
/**
|
|
* @brief Generate weekly Stalk Market prices in a 'random' trend.
|
|
**/
|
|
static void Kabu_decide_price_schedule_typeB() {
|
|
u16* prices = Save_GetPointer(kabu_price_schedule.daily_price[lbRTC_MONDAY]);
|
|
f32 current_price_mult = TRADE_MARKET_B_PRICE_INCREASE_START;
|
|
f32 price_decrease_percent = TRADE_MARKET_B_PRICE_DECREASE_ODDS_START;
|
|
f32 current_price = (f32)Save_Get(kabu_price_schedule.daily_price[lbRTC_SUNDAY]);
|
|
f32 min_price = (f32)Save_Get(kabu_price_schedule.daily_price[lbRTC_SUNDAY]) * TRADE_MARKET_B_SUNDAY_PRICE_MULT;
|
|
int day;
|
|
|
|
for (day = lbRTC_MONDAY; day <= lbRTC_SATURDAY; day++) {
|
|
/* check if rng roll is less than our decrease chance */
|
|
if (fqrand() < price_decrease_percent) {
|
|
current_price *= TRADE_MARKET_B_PRICE_DECREASE_RATE; /* decrease price */
|
|
if (current_price > min_price) {
|
|
/* if decreased price is greater than the minimum decrease price, clamp it */
|
|
current_price = min_price;
|
|
}
|
|
|
|
/* lower decrease chance, and clamp it to <= initial decrease odds */
|
|
price_decrease_percent *= TRADE_MARKET_B_PRICE_DECREASE_LOWER_RATE;
|
|
if (price_decrease_percent > TRADE_MARKET_B_PRICE_DECREASE_ODDS_START) {
|
|
price_decrease_percent = TRADE_MARKET_B_PRICE_DECREASE_ODDS_START;
|
|
}
|
|
}
|
|
else {
|
|
/* increase increase multiplier & price, but also increase decrease chance */
|
|
current_price *= current_price_mult;
|
|
current_price_mult += TRADE_MARKET_B_PRICE_INCREASE_RATE;
|
|
price_decrease_percent += TRADE_MARKET_B_PRICE_DECREASE_ODDS_RATE;
|
|
}
|
|
|
|
*prices++ = current_price; /* move to next day save slot */
|
|
}
|
|
}
|
|
|
|
#define TRADE_MARKET_C_ADJUST_MULT_SPREAD 0.14999998f /* mwcc doesn't generate the same */ //0.15f
|
|
#define TRADE_MARKET_C_ADJUST_MULT_BASE 0.8f
|
|
|
|
/**
|
|
* @brief Generate weekly Stalk Market prices in a 'falling' trend.
|
|
**/
|
|
static void Kabu_decide_price_schedule_typeC() {
|
|
u16* price = Save_GetPointer(kabu_price_schedule.daily_price[lbRTC_MONDAY]);
|
|
f32 current_price = Save_Get(kabu_price_schedule.daily_price[lbRTC_SUNDAY]);
|
|
int day;
|
|
|
|
for (day = lbRTC_MONDAY; day <= lbRTC_SATURDAY; day++) {
|
|
current_price *= (TRADE_MARKET_C_ADJUST_MULT_BASE + TRADE_MARKET_C_ADJUST_MULT_SPREAD * fqrand()); /* [80%, 95%) */
|
|
*price++ = current_price;
|
|
}
|
|
}
|
|
|
|
#define TRADE_MARKET_SUNDAY_BASE_PRICE 100.0f
|
|
|
|
/**
|
|
* @brief Generate Sunday Stalk Market buy price.
|
|
*
|
|
* Prices will always been in the range of [70, 129] bells.
|
|
**/
|
|
static void Kabu_decide_price_sunday() {
|
|
f32 price = 1.0f + (fqrand() - 0.5f) * 0.6f;
|
|
Save_Set(kabu_price_schedule.daily_price[lbRTC_SUNDAY], price * TRADE_MARKET_SUNDAY_BASE_PRICE); /* [0.7, 1.3) * 100.0f = [70, 130) bells */
|
|
}
|
|
|
|
/**
|
|
* @brief Run the set Stalk Market trend algorithm.
|
|
**/
|
|
static void Kabu_decide_price_without_sunday() {
|
|
static void (*process[])(void) = { Kabu_decide_price_schedule_typeA, Kabu_decide_price_schedule_typeB, Kabu_decide_price_schedule_typeC };
|
|
(*process[Save_Get(kabu_price_schedule.trade_market)])();
|
|
}
|
|
|
|
/**
|
|
* @brief Picks a new Stalk Market trend, generates new sell prices, & sets the update time.
|
|
**/
|
|
static void Kabu_decide_price_schedule_without_sunday() {
|
|
Kabu_decide_trade_market();
|
|
Kabu_decide_price_without_sunday();
|
|
Kabu_set_schedule_day();
|
|
}
|
|
|
|
/**
|
|
* @brief Generates a new Stalk Market Sunday buy price, Stalk Market trend, sell prices, & sets the update time.
|
|
**/
|
|
extern void Kabu_decide_price_schedule() {
|
|
Kabu_decide_price_sunday();
|
|
Kabu_decide_price_schedule_without_sunday();
|
|
}
|
|
|
|
/**
|
|
* @brief Retrieves the current day's Stalk Market price.
|
|
**/
|
|
extern u16 Kabu_get_price() {
|
|
return Save_Get(kabu_price_schedule.daily_price[Common_Get(time.rtc_time.weekday)]);
|
|
}
|
|
|
|
/**
|
|
* @brief Checks if the Stalk Market should be re-rolled based on the current date
|
|
*
|
|
* It will re-roll the Stalk Market Trend & sell prices if called on Sunday
|
|
* after the Stalk Market has already been set for the week.
|
|
*
|
|
* It will completely re-roll Stalk Market if the date is greater than one week
|
|
* from the last Stalk Market update.
|
|
**/
|
|
extern void Kabu_manager() {
|
|
lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time);
|
|
lbRTC_time_c* kabu_update_time = Save_GetPointer(kabu_price_schedule.update_time);
|
|
|
|
/* Check if being called on the Sunday where the Stalk Market has already been set */
|
|
if (lbRTC_IsEqualDate(
|
|
rtc_time->year, rtc_time->month, rtc_time->day,
|
|
kabu_update_time->year, kabu_update_time->month, kabu_update_time->day
|
|
) == lbRTC_EQUAL
|
|
) {
|
|
Kabu_decide_price_schedule_without_sunday(); /* reset non-sunday prices & the trend type */
|
|
}
|
|
else {
|
|
lbRTC_time_c week_ahead;
|
|
lbRTC_time_c week_behind;
|
|
|
|
lbRTC_TimeCopy(&week_ahead, kabu_update_time);
|
|
lbRTC_Add_DD(&week_ahead, lbRTC_WEEK);
|
|
|
|
lbRTC_TimeCopy(&week_behind, kabu_update_time);
|
|
lbRTC_Sub_DD(&week_behind, lbRTC_WEEK);
|
|
|
|
if (lbRTC_IsOverTime(&week_ahead, Common_GetPointer(time.rtc_time)) == lbRTC_OVER ||
|
|
lbRTC_IsOverTime(&week_behind, Common_GetPointer(time.rtc_time)) == lbRTC_LESS
|
|
) {
|
|
Kabu_decide_price_schedule(); /* greater than one week has passed, reset entire schedule */
|
|
}
|
|
}
|
|
}
|