Skip to content

Commit 85ae34d

Browse files
new implementation of old concept for chaos mod
1 parent 919f768 commit 85ae34d

File tree

1 file changed

+37
-217
lines changed

1 file changed

+37
-217
lines changed

src/Etterna/Globals/MinaCalc.cpp

+37-217
Original file line numberDiff line numberDiff line change
@@ -3779,61 +3779,28 @@ struct ChaosMod
37793779
const std::string name = "ChaosMod";
37803780

37813781
#pragma region params
3782-
float itv_window = 1;
3782+
float window = 6;
37833783

37843784
float min_mod = 0.5f;
37853785
float max_mod = 1.0f;
3786-
float mod_pool = 1.25f;
3787-
3788-
float moving_cv_init = 0.5f;
3789-
float roll_cv_cutoff = 0.4f;
3786+
float penalty = 0.1f;
37903787

37913788
const vector<pair<std::string, float*>> _params{
3792-
{ "itv_window", &itv_window },
3789+
{ "window", &window },
37933790

37943791
{ "min_mod", &min_mod },
37953792
{ "max_mod", &max_mod },
3796-
{ "mod_pool", &mod_pool },
3797-
3798-
{ "moving_cv_init", &moving_cv_init },
3799-
{ "roll_cv_cutoff", &roll_cv_cutoff },
3793+
{ "penalty", &penalty },
38003794
};
38013795
#pragma endregion params and param map
38023796

3803-
// window is currently 1 for local mod
3804-
// taps for this hand only, we don't want to include offhand taps in
3805-
// determining whether this hand is a roll
3806-
deque<int> window_itv_hand_taps;
3807-
deque<vector<int>> window_itv_rolls;
3808-
3809-
// each element is a discrete roll formation with this many taps
3810-
// (technically it has this many taps + 4 because it requires 1212 or
3811-
// 2121 to start counting, but that's fine, that's what we want and if
3812-
// it seems better to add later we can do that
3813-
vector<int> itv_rolls;
3814-
3815-
// unlike ccacc, which has a half baked implementation for chains of
3816-
// 122112211221, we will actually be responsible and sequence both the
3817-
// number of rolls and the notes contained therein
3818-
bool rolling = false;
3819-
bool is_transition = false;
3820-
int consecutive_roll_counter = 0;
3797+
moving_window_interval_float _u;
3798+
moving_window_interval_float _wot;
3799+
moving_window_interval_float _m8;
3800+
moving_window_interval_float _hekk;
38213801

3822-
int window_hand_taps = 0;
3823-
// for now we will be lazy and just add up the number of roll taps in any
3824-
// roll, if we leave out the initialization taps (the 4 required to identify
3825-
// the start) we will greatly reduce the effect of short roll bursts, not
3826-
// sure if this is desired behavior
3827-
int window_roll_taps = 0;
38283802
float pmod = min_mod;
38293803

3830-
vector<float> seq_ms = { 0.f, 0.f, 0.f };
3831-
// uhhh lazy way out of tracking all the floats i think
3832-
float moving_cv = moving_cv_init;
3833-
3834-
// non-empty (cc_type is now always non-empty)
3835-
cc_type last_seen_cc = cc_init;
3836-
cc_type last_last_seen_cc = cc_init;
38373804
#pragma region generic functions
38383805
inline void setup(vector<float> doot[], const int& size)
38393806
{
@@ -3866,209 +3833,61 @@ struct ChaosMod
38663833
}
38673834
#pragma endregion
38683835

3869-
// should rename as it resets or completes a sequence... maybe should go
3870-
// look at rm_sequencing again and make roll_sequencing.. idk
3871-
inline void reset_sequence()
3872-
{
3873-
// only need to do this if rolling, otherwise values are false/0 anyway
3874-
if (rolling) {
3875-
itv_rolls.push_back(consecutive_roll_counter);
3876-
rolling = false;
3877-
consecutive_roll_counter = 0;
3878-
}
3879-
3880-
last_seen_cc = cc_init;
3881-
last_last_seen_cc = cc_init;
3882-
for (auto& v : seq_ms)
3883-
v = 0.f;
3884-
}
3885-
3886-
// copied from wrjt, definitely needs to be tracked in metanoteinfo
3887-
inline bool detecc_ccacc(const metaHandInfo& now)
3888-
{
3889-
if (now.cc == cc_single_single)
3890-
return false;
3891-
3892-
if (invert_cc(now.cc) == last_last_seen_cc)
3893-
return true;
3894-
3895-
return false;
3896-
}
3897-
3898-
// should maybe move this into metanoteinfo and do the counting there, since
3899-
// oht will need this as well, or we could be lazy and do it twice just this
3900-
// once
3901-
inline bool detecc_roll(const metaHandInfo& now)
3836+
inline void advance_sequencing(const metaHandInfo& now)
39023837
{
3903-
// we allow this through up to here due to transition checks
3904-
if (now.cc == cc_single_single)
3905-
return false;
3838+
_u(now.cc_ms_any);
39063839

3907-
// if we're here the following are true, we have a full sequence of 3 cc
3908-
// taps, they are non-empty, there are no jumps and no anchors. this
3909-
// means they are all either cc_left_right, cc_right_left
3840+
float high = _u[4];
3841+
float low = now.cc_ms_any;
39103842

3911-
// now we know we have cc_left_right or cc_right_left, so, xy, we are
3912-
// looking for xyx, meaning last would be the inverion of now
3913-
if (invert_cc(now.cc) == last_seen_cc)
3914-
// now make sure that last_last is the same as now
3915-
if (now.cc == last_last_seen_cc)
3916-
// we now have 1212 or 2121
3917-
return true;
3918-
return false;
3919-
}
3920-
3921-
inline bool handle_roll_timing_check()
3922-
{
3923-
// see ccacc timing check in wrjt for explanations, it's basically the
3924-
// same but we have to invert the multiplication depending on which
3925-
// value is higher between seq_ms[0] and seq_ms[1] (easiest to dummy up
3926-
// a roll in an editor to see why)
3927-
3928-
// multiply seq_ms[1] by 3 for the cv check, then put it back so it
3929-
// doesn't interfere with the next round
3930-
if (seq_ms[0] > seq_ms[1]) {
3931-
seq_ms[1] *= 3.f;
3932-
moving_cv = (moving_cv + cv(seq_ms)) / 2.f;
3933-
seq_ms[1] /= 3.f;
3934-
return moving_cv < roll_cv_cutoff;
3935-
} else {
3936-
// same thing but divide
3937-
seq_ms[1] /= 3.f;
3938-
moving_cv = (moving_cv + cv(seq_ms)) / 2.f;
3939-
seq_ms[1] *= 3.f;
3940-
return moving_cv < roll_cv_cutoff;
3843+
if (high == 0.f || low == 0.f || high == low) {
3844+
_wot(1.f);
3845+
_m8(_wot.get_mean_of_window(window));
3846+
return;
39413847
}
3942-
}
39433848

3944-
inline void update_seq_ms(const metaHandInfo& now)
3945-
{
3946-
seq_ms[0] = seq_ms[1]; // last_last
3947-
seq_ms[1] = seq_ms[2]; // last
3849+
if (low > high)
3850+
std::swap(high, low);
39483851

3949-
// update now, we have no anchors, so always use cc_ms_any (although we
3950-
// want to move this to cc_ms_no_jumps when that gets implemented, since
3951-
// a separate jump inclusive mod should be made to handle those cases
3952-
seq_ms[2] = now.cc_ms_any;
3953-
}
3852+
float prop = high / low;
3853+
int mop = static_cast<int>(prop);
3854+
float flop = prop - static_cast<float>(mop);
39543855

3955-
inline void advance_sequencing(const metaHandInfo& now)
3956-
{
3957-
// do nothing for offhand taps
3958-
if (now.col == col_empty)
3959-
return;
3856+
if (flop == 0.f) {
3857+
flop = 1.f;
3858+
} else if (flop >= 0.5f) {
3859+
flop = abs(flop - 1.f) + 1.f;
39603860

3961-
// only let these cases through, since we use invert_cc, anchors are
3962-
// screened out later, reset otherwise
3963-
if (now.cc != cc_left_right && now.cc != cc_right_left) {
3964-
reset_sequence();
3965-
return;
3861+
} else if (flop < 0.5f) {
3862+
flop += 1.f;
39663863
}
39673864

3968-
// update timing stuff
3969-
update_seq_ms(now);
3970-
3971-
// check for a complete sequence
3972-
if (last_last_seen_cc != cc_init)
3973-
// check for rolls (cc -> inverted(cc) -> cc)
3974-
// now.mt == meta_oht (works in trill idk wtf, but it isn't working
3975-
// here?)
3976-
if (detecc_roll(now) && handle_roll_timing_check()) {
3977-
if (rolling) {
3978-
// these should always be mutually exclusive
3979-
++consecutive_roll_counter;
3980-
} else {
3981-
// we could increase the roll counter here, but really
3982-
// all we have now is a minitrill, so lets see if it
3983-
// extends to at least 5 notes before doing anything
3984-
rolling = true;
3985-
}
3986-
// only reset here if this fails and a transition wasn't
3987-
// detected, if we reset here we have to assign seq_ms[2] again,
3988-
// yes this is asofgasfjasofdj messy
3989-
}
3990-
3991-
// update sequence
3992-
last_last_seen_cc = last_seen_cc;
3993-
last_seen_cc = now.cc;
3865+
_wot(flop);
3866+
_m8(_wot.get_mean_of_window(window));
39943867
}
39953868

3996-
inline bool handle_case_optimizations(vector<float> doot[], const int& i)
3869+
inline bool handle_case_optimizations(const ItvInfo& itvi,
3870+
vector<float> doot[],
3871+
const int& i)
39973872
{
3998-
// no taps, no rolls
3999-
if (window_hand_taps == 0 || window_roll_taps == 0) {
3873+
if (itvi.total_taps == 0) {
40003874
neutral_set(_pmod, doot, i);
40013875
return true;
40023876
}
40033877

4004-
// full roll
4005-
if (window_hand_taps == window_roll_taps) {
4006-
mod_set(_pmod, doot, i, min_mod);
4007-
return true;
4008-
}
4009-
40103878
return false;
40113879
}
40123880

40133881
inline void operator()(const ItvHandInfo& itvh,
40143882
vector<float> doot[],
40153883
const int& i)
40163884
{
4017-
neutral_set(_pmod, doot, i);
4018-
return;
4019-
4020-
// drop the oldest interval values if we have reached full
4021-
// size
4022-
if (window_itv_hand_taps.size() == itv_window) {
4023-
window_itv_hand_taps.pop_front();
4024-
window_itv_rolls.pop_front();
4025-
}
4026-
4027-
// this is slightly hacky buuut if we have a roll that doesn't complete
4028-
// by the end of the interval, it should count for that interval, but we
4029-
// don't want the value to double up so we will reset the counter on
4030-
// interval end but _not_ reset the rolling bool, so it won't interfere
4031-
// with the detection as the sequencing passes into the next interval,
4032-
// and won't double up values
4033-
if (consecutive_roll_counter > 0) {
4034-
itv_rolls.push_back(consecutive_roll_counter);
4035-
consecutive_roll_counter = 0;
4036-
}
4037-
4038-
window_itv_hand_taps.push_back(itvh.hand_taps);
4039-
window_itv_rolls.push_back(itv_rolls);
3885+
_hekk(_m8.get_mean_of_window(6));
40403886

4041-
window_hand_taps = 0;
4042-
for (auto& n : window_itv_hand_taps)
4043-
window_hand_taps += n;
4044-
4045-
window_roll_taps = 0;
4046-
// for now just add everything up
4047-
for (auto& n : window_itv_rolls)
4048-
for (auto& v : n)
4049-
window_roll_taps += v;
4050-
4051-
if (handle_case_optimizations(doot, i)) {
4052-
interval_reset();
4053-
return;
4054-
}
4055-
4056-
pmod = max_mod;
4057-
if (window_roll_taps > 0 && window_hand_taps > 0)
4058-
pmod = mod_pool - (static_cast<float>(window_roll_taps) /
4059-
static_cast<float>(window_hand_taps));
4060-
4061-
pmod = CalcClamp(pmod, min_mod, max_mod);
3887+
float zmod = _hekk.get_mean_of_window(window);
3888+
pmod = _m8.get_mean_of_window(6) - penalty;
40623889
doot[_pmod][i] = pmod;
4063-
4064-
interval_reset();
40653890
}
4066-
4067-
// may be unneeded for this function but it's probably good practice to have
4068-
// this and always reset anything that needs to be on handling case
4069-
// optimizations, even if the case optimizations don't require us to reset
4070-
// anything
4071-
inline void interval_reset() { itv_rolls.clear(); }
40723891
};
40733892

40743893
struct RM_Sequencing
@@ -6265,6 +6084,7 @@ struct TheGreatBazoinkazoinkInTheSky
62656084
_rm.advance_sequencing(*_mhi);
62666085
_wrr.advance_sequencing(*_mhi);
62676086
_wrjt.advance_sequencing(*_mhi);
6087+
_ch.advance_sequencing(*_mhi);
62686088
}
62696089

62706090
inline void setup_dependent_mods(vector<float> _doot[])

0 commit comments

Comments
 (0)