Added costs for "slow" bracketing (to prioritize jumps), twisted backwards foot.
Removed costs for JUMP, CROWDED_BRACKET, and OTHER Added cutoffs for counting footswitches and doublesteps below a certain speed as tech
This commit is contained in:
+95
-42
@@ -91,7 +91,7 @@ float* StepParityCost::getActionCost(State * initialState, State * resultState,
|
|||||||
|
|
||||||
costs[COST_HOLDSWITCH] += calcHoldSwitchCost( initialState, resultState, row, combinedColumns, columnCount);
|
costs[COST_HOLDSWITCH] += calcHoldSwitchCost( initialState, resultState, row, combinedColumns, columnCount);
|
||||||
costs[COST_BRACKETTAP] += calcBracketTapCost( initialState, resultState, row, leftHeel, leftToe, rightHeel, rightToe, elapsedTime, columnCount);
|
costs[COST_BRACKETTAP] += calcBracketTapCost( initialState, resultState, row, leftHeel, leftToe, rightHeel, rightToe, elapsedTime, columnCount);
|
||||||
costs[COST_OTHER] += calcMovingFootWhileOtherIsntOnPadCost( initialState, resultState, columnCount);
|
// costs[COST_OTHER] += calcMovingFootWhileOtherIsntOnPadCost( initialState, resultState, columnCount);
|
||||||
|
|
||||||
bool movedLeft =
|
bool movedLeft =
|
||||||
resultState->didTheFootMove[LEFT_HEEL] ||
|
resultState->didTheFootMove[LEFT_HEEL] ||
|
||||||
@@ -121,20 +121,17 @@ float* StepParityCost::getActionCost(State * initialState, State * resultState,
|
|||||||
|
|
||||||
costs[COST_BRACKETJACK] += calcBracketJackCost( initialState, resultState, rows, rowIndex, movedLeft, movedRight, jackedLeft, jackedRight, didJump, columnCount);
|
costs[COST_BRACKETJACK] += calcBracketJackCost( initialState, resultState, rows, rowIndex, movedLeft, movedRight, jackedLeft, jackedRight, didJump, columnCount);
|
||||||
costs[COST_DOUBLESTEP] += calcDoublestepCost(initialState, resultState, rows, rowIndex, movedLeft, movedRight, jackedLeft, jackedRight, didJump, columnCount);
|
costs[COST_DOUBLESTEP] += calcDoublestepCost(initialState, resultState, rows, rowIndex, movedLeft, movedRight, jackedLeft, jackedRight, didJump, columnCount);
|
||||||
costs[COST_JUMP] += calcJumpCost( row, movedLeft, movedRight, elapsedTime, columnCount);
|
// costs[COST_JUMP] += calcJumpCost( row, movedLeft, movedRight, elapsedTime, columnCount);
|
||||||
|
costs[COST_SLOW_BRACKET] += calcSlowBracketCost(row, movedLeft, movedRight, elapsedTime);
|
||||||
|
costs[COST_TWISTED_FOOT] += calcTwistedFootCost(resultState);
|
||||||
costs[COST_FACING] += calcFacingCosts( initialState, resultState, combinedColumns, columnCount);
|
costs[COST_FACING] += calcFacingCosts( initialState, resultState, combinedColumns, columnCount);
|
||||||
costs[COST_SPIN] += calcSpinCosts(initialState, resultState, combinedColumns, columnCount);
|
costs[COST_SPIN] += calcSpinCosts(initialState, resultState, combinedColumns, columnCount);
|
||||||
costs[COST_FOOTSWITCH] += caclFootswitchCost( initialState, resultState, row, combinedColumns, elapsedTime, columnCount);
|
costs[COST_FOOTSWITCH] += caclFootswitchCost( initialState, resultState, row, combinedColumns, elapsedTime, columnCount);
|
||||||
costs[COST_SIDESWITCH] += calcSideswitchCost( initialState, resultState, columnCount);
|
costs[COST_SIDESWITCH] += calcSideswitchCost( initialState, resultState, columnCount);
|
||||||
costs[COST_MISSED_FOOTSWITCH] += calcMissedFootswitchCost( row, jackedLeft, jackedRight, columnCount);
|
costs[COST_MISSED_FOOTSWITCH] += calcMissedFootswitchCost( row, jackedLeft, jackedRight, columnCount)
|
||||||
|
|
||||||
// To do: small weighting for swapping heel with toe or toe with heel (both add up)
|
|
||||||
// To do: huge weighting for having foot direction opposite of eachother (can't twist one leg 180 degrees)
|
|
||||||
costs[COST_JACK] += calcJackCost( movedLeft, movedRight, jackedLeft, jackedRight, elapsedTime, columnCount);
|
costs[COST_JACK] += calcJackCost( movedLeft, movedRight, jackedLeft, jackedRight, elapsedTime, columnCount);
|
||||||
|
|
||||||
// To do: weighting for moving a foot a far distance in a fast time
|
|
||||||
costs[COST_DISTANCE] += calcBigMovementsQuicklyCost( initialState, resultState, elapsedTime, columnCount);
|
costs[COST_DISTANCE] += calcBigMovementsQuicklyCost( initialState, resultState, elapsedTime, columnCount);
|
||||||
costs[COST_CROWDED_BRACKET] += calcCrowdedBracketCost(initialState, resultState, elapsedTime, columnCount);
|
// costs[COST_CROWDED_BRACKET] += calcCrowdedBracketCost(initialState, resultState, elapsedTime, columnCount);
|
||||||
|
|
||||||
// I don't like that we're updating columns here like this.
|
// I don't like that we're updating columns here like this.
|
||||||
// We're basically updating columns with the final position of the feet
|
// We're basically updating columns with the final position of the feet
|
||||||
@@ -405,6 +402,45 @@ float StepParityCost::calcJumpCost(Row & row, bool movedLeft, bool movedRight, f
|
|||||||
return cost;
|
return cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Jumps should be prioritized over brackets below a certain speed
|
||||||
|
float StepParityCost::calcSlowBracketCost(Row & row, bool movedLeft, bool movedRight, float elapsedTime)
|
||||||
|
{
|
||||||
|
float cost = 0;
|
||||||
|
if(elapsedTime > SLOW_BRACKET_THRESHOLD && movedLeft != movedRight &&
|
||||||
|
std::count_if(row.notes.begin(), row.notes.end(), [](StepParity::IntermediateNoteData note)
|
||||||
|
{ return note.type != TapNoteType_Empty; }) >= 2)
|
||||||
|
{
|
||||||
|
float timediff = elapsedTime - SLOW_BRACKET_THRESHOLD;
|
||||||
|
cost += timediff * SLOW_BRACKET;
|
||||||
|
}
|
||||||
|
return cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Does this placement result in one of the feet being twisted around?
|
||||||
|
// This should probably be getting filtered out as an invalid positioning before
|
||||||
|
// we even get to calculating costs.
|
||||||
|
float StepParityCost::calcTwistedFootCost(State * resultState)
|
||||||
|
{
|
||||||
|
float cost = 0;
|
||||||
|
int leftHeel = resultState->whereTheFeetAre[LEFT_HEEL];
|
||||||
|
int leftToe = resultState->whereTheFeetAre[LEFT_TOE];
|
||||||
|
int rightHeel = resultState->whereTheFeetAre[RIGHT_HEEL];
|
||||||
|
int rightToe = resultState->whereTheFeetAre[RIGHT_TOE];
|
||||||
|
|
||||||
|
StagePoint leftPos = averagePoint(leftHeel, leftToe);
|
||||||
|
StagePoint rightPos = averagePoint(rightHeel, rightToe);
|
||||||
|
|
||||||
|
bool crossedOver = rightPos.x < leftPos.x;
|
||||||
|
bool rightBackwards = rightHeel != -1 && rightToe != -1 ? layout[rightToe].y < layout[rightHeel].y : false;
|
||||||
|
bool leftBackwards = leftHeel != -1 && leftToe != -1 ? layout[leftToe].y < layout[leftHeel].y : false;
|
||||||
|
|
||||||
|
if(!crossedOver && (rightBackwards || leftBackwards))
|
||||||
|
{
|
||||||
|
cost += TWISTED_FOOT;
|
||||||
|
}
|
||||||
|
return cost;
|
||||||
|
}
|
||||||
|
|
||||||
float StepParityCost::calcMissedFootswitchCost(Row & row, bool jackedLeft, bool jackedRight, int columnCount)
|
float StepParityCost::calcMissedFootswitchCost(Row & row, bool jackedLeft, bool jackedRight, int columnCount)
|
||||||
{
|
{
|
||||||
float cost = 0;
|
float cost = 0;
|
||||||
@@ -554,40 +590,39 @@ float StepParityCost::calcSpinCosts(State * initialState, State * resultState, s
|
|||||||
return cost;
|
return cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Footswitches are harder the slower they are.
|
// Footswitches are harder to do when they get too slow.
|
||||||
// Add a penalty when they get slower than 8ths at 120bpm (0.25 seconds)
|
// Notes with an elapsed time greater than this will incur a penalty
|
||||||
float StepParityCost::caclFootswitchCost(State * initialState, State * resultState, Row & row, std::vector<StepParity::Foot> & combinedColumns, float elapsedTime, int columnCount)
|
float StepParityCost::caclFootswitchCost(State * initialState, State * resultState, Row & row, std::vector<StepParity::Foot> & combinedColumns, float elapsedTime, int columnCount)
|
||||||
{
|
{
|
||||||
float cost = 0;
|
float cost = 0;
|
||||||
// ignore footswitch with 24 or less distance (8th note); penalise slower footswitches based on distance
|
if (elapsedTime >= SLOW_FOOTSWITCH_THRESHOLD && elapsedTime < SLOW_FOOTSWITCH_IGNORE) {
|
||||||
if (elapsedTime >= 0.25) {
|
|
||||||
// footswitching has no penalty if there's a mine nearby
|
// footswitching has no penalty if there's a mine nearby
|
||||||
if (
|
if (
|
||||||
std::all_of(row.mines.begin(), row.mines.end(), [](int mine)
|
std::all_of(row.mines.begin(), row.mines.end(), [](int mine)
|
||||||
{ return mine == 0; }) &&
|
{ return mine == 0; }) &&
|
||||||
std::all_of(row.fakeMines.begin(), row.fakeMines.end(), [](int mine)
|
std::all_of(row.fakeMines.begin(), row.fakeMines.end(), [](int mine)
|
||||||
{ return mine == 0; }))
|
{ return mine == 0; }))
|
||||||
{
|
|
||||||
float timeScaled = elapsedTime - 0.25;
|
|
||||||
|
|
||||||
for (int i = 0; i < columnCount; i++)
|
|
||||||
{
|
{
|
||||||
if (
|
float timeScaled = elapsedTime - SLOW_FOOTSWITCH_THRESHOLD;
|
||||||
initialState->columns[i] == NONE ||
|
|
||||||
resultState->columns[i] == NONE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (
|
for (int i = 0; i < columnCount; i++)
|
||||||
initialState->columns[i] != resultState->columns[i] &&
|
|
||||||
!resultState->didTheFootMove[initialState->columns[i]])
|
|
||||||
{
|
{
|
||||||
cost += pow(timeScaled / 2.0f, 2) * FOOTSWITCH;
|
if (
|
||||||
break;
|
initialState->columns[i] == NONE ||
|
||||||
|
resultState->columns[i] == NONE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (
|
||||||
|
initialState->columns[i] != resultState->columns[i] &&
|
||||||
|
initialState->columns[i] != OTHER_PART_OF_FOOT[resultState->columns[i]]
|
||||||
|
)
|
||||||
|
{
|
||||||
|
cost += (timeScaled / (SLOW_FOOTSWITCH_THRESHOLD + timeScaled)) * FOOTSWITCH;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return cost;
|
return cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -637,17 +672,35 @@ float StepParityCost::calcBigMovementsQuicklyCost(State * initialState, State *
|
|||||||
for (StepParity::Foot foot : resultState->movedFeet)
|
for (StepParity::Foot foot : resultState->movedFeet)
|
||||||
{
|
{
|
||||||
if(foot == NONE)
|
if(foot == NONE)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
int idxFoot = initialState->whereTheFeetAre[foot];
|
}
|
||||||
if (idxFoot == -1)
|
|
||||||
|
int initialPosition = initialState->whereTheFeetAre[foot];
|
||||||
|
if(initialPosition == -1)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
cost +=
|
}
|
||||||
(sqrt(
|
|
||||||
getDistanceSq(
|
int resultPosition = resultState->whereTheFeetAre[foot];
|
||||||
layout[idxFoot],
|
|
||||||
layout[resultState->whereTheFeetAre[foot]])) *
|
|
||||||
DISTANCE) /
|
// If we're bracketing something, and the toes are now where the heel
|
||||||
elapsedTime;
|
// was, then we don't need to worry about it, we're not actually moving
|
||||||
|
// the foot very far
|
||||||
|
bool isBracketing = resultState->whereTheFeetAre[OTHER_PART_OF_FOOT[foot]] != -1;
|
||||||
|
if(isBracketing && resultState->whereTheFeetAre[OTHER_PART_OF_FOOT[foot]] == initialPosition)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
float dist = (sqrt(getDistanceSq(layout[initialPosition], layout[resultPosition])) * DISTANCE) / elapsedTime;
|
||||||
|
// Otherwise if we're still bracketing, this is probably a less drastic movement
|
||||||
|
if(isBracketing)
|
||||||
|
{
|
||||||
|
dist = dist * 0.2;
|
||||||
|
}
|
||||||
|
cost += dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cost;
|
return cost;
|
||||||
|
|||||||
+20
-5
@@ -11,20 +11,33 @@ namespace StepParity
|
|||||||
const int DOUBLESTEP= 850;
|
const int DOUBLESTEP= 850;
|
||||||
const int BRACKETJACK= 20;
|
const int BRACKETJACK= 20;
|
||||||
const int JACK= 30;
|
const int JACK= 30;
|
||||||
const int JUMP= 30;
|
const int JUMP= 0;
|
||||||
|
const int SLOW_BRACKET=300;
|
||||||
|
const int TWISTED_FOOT=100000;
|
||||||
const int BRACKETTAP= 400;
|
const int BRACKETTAP= 400;
|
||||||
const int HOLDSWITCH= 55;
|
const int HOLDSWITCH= 55;
|
||||||
const int MINE= 10000;
|
const int MINE= 10000;
|
||||||
const int FOOTSWITCH= 5000;
|
const int FOOTSWITCH= 325;
|
||||||
const int MISSED_FOOTSWITCH= 500;
|
const int MISSED_FOOTSWITCH= 500;
|
||||||
const int FACING= 2;
|
const int FACING= 2;
|
||||||
const int DISTANCE= 6;
|
const int DISTANCE= 6;
|
||||||
const int SPIN= 1000;
|
const int SPIN= 1000;
|
||||||
const int SIDESWITCH= 130;
|
const int SIDESWITCH= 130;
|
||||||
const int CROWDED_BRACKET = 40;
|
const int CROWDED_BRACKET = 0;
|
||||||
const int OTHER = 500;
|
const int OTHER = 0;
|
||||||
|
|
||||||
const float JACK_THRESHOLD = 0.1;
|
// 0.1 = 1/16th note at 150bpm. Jacks quicker than this are harder.
|
||||||
|
// Above this speed, footswitches should be prioritized
|
||||||
|
const float JACK_THRESHOLD = 0.1;
|
||||||
|
// 0.15 = 1/8th at 200bpm, or 3/16th at 150bpm. Below this speed, jumps should be prioritized
|
||||||
|
const float SLOW_BRACKET_THRESHOLD = 0.15;
|
||||||
|
|
||||||
|
// 0.2 = 1/8th at 150bpm. Footswitches slower than this are harder.
|
||||||
|
// Below this speed, jacks should be prioritized
|
||||||
|
const float SLOW_FOOTSWITCH_THRESHOLD = 0.2;
|
||||||
|
// 0.4 = 1/4th at 150bpm. Once a footswitch gets slow enough, though,
|
||||||
|
// just ignore it.
|
||||||
|
const float SLOW_FOOTSWITCH_IGNORE = 0.4;
|
||||||
|
|
||||||
class StepParityCost
|
class StepParityCost
|
||||||
{
|
{
|
||||||
@@ -54,6 +67,8 @@ namespace StepParity
|
|||||||
float calcBracketJackCost(State * initialState, State * resultState, std::vector<Row> &rows, int rowIndex, bool movedLeft, bool movedRight, bool jackedLeft, bool jackedRight, bool didJump, int columnCount);
|
float calcBracketJackCost(State * initialState, State * resultState, std::vector<Row> &rows, int rowIndex, bool movedLeft, bool movedRight, bool jackedLeft, bool jackedRight, bool didJump, int columnCount);
|
||||||
float calcDoublestepCost(State * initialState, State * resultState, std::vector<Row> & rows, int rowIndex, bool movedLeft, bool movedRight, bool jackedLeft, bool jackedRight, bool didJump, int columnCount);
|
float calcDoublestepCost(State * initialState, State * resultState, std::vector<Row> & rows, int rowIndex, bool movedLeft, bool movedRight, bool jackedLeft, bool jackedRight, bool didJump, int columnCount);
|
||||||
float calcJumpCost(Row &row, bool movedLeft, bool movedRight, float elapsedTime, int columnCount);
|
float calcJumpCost(Row &row, bool movedLeft, bool movedRight, float elapsedTime, int columnCount);
|
||||||
|
float calcSlowBracketCost(Row & row, bool movedLeft, bool movedRight, float elapsedTime);
|
||||||
|
float calcTwistedFootCost(State * resultState);
|
||||||
float calcMissedFootswitchCost(Row &row, bool jackedLeft, bool jackedRight, int columnCount);
|
float calcMissedFootswitchCost(Row &row, bool jackedLeft, bool jackedRight, int columnCount);
|
||||||
float calcFacingCosts(State * initialState, State * resultState, std::vector<StepParity::Foot> &combinedColumns, int columnCount);
|
float calcFacingCosts(State * initialState, State * resultState, std::vector<StepParity::Foot> &combinedColumns, int columnCount);
|
||||||
float calcSpinCosts(State * initialState, State * resultState, std::vector<StepParity::Foot> & combinedColumns, int columnCount);
|
float calcSpinCosts(State * initialState, State * resultState, std::vector<StepParity::Foot> & combinedColumns, int columnCount);
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ namespace StepParity {
|
|||||||
COST_BRACKETJACK,
|
COST_BRACKETJACK,
|
||||||
COST_JACK,
|
COST_JACK,
|
||||||
COST_JUMP,
|
COST_JUMP,
|
||||||
|
COST_SLOW_BRACKET,
|
||||||
|
COST_TWISTED_FOOT,
|
||||||
COST_BRACKETTAP,
|
COST_BRACKETTAP,
|
||||||
COST_HOLDSWITCH,
|
COST_HOLDSWITCH,
|
||||||
COST_MINE,
|
COST_MINE,
|
||||||
|
|||||||
+18
-4
@@ -23,9 +23,18 @@ XToLocalizedString( TechCountsCategory );
|
|||||||
LuaFunction(TechCountsCategoryToLocalizedString, TechCountsCategoryToLocalizedString(Enum::Check<TechCountsCategory>(L, 1)) );
|
LuaFunction(TechCountsCategoryToLocalizedString, TechCountsCategoryToLocalizedString(Enum::Check<TechCountsCategory>(L, 1)) );
|
||||||
LuaXType( TechCountsCategory );
|
LuaXType( TechCountsCategory );
|
||||||
|
|
||||||
const float JACK_CUTOFF = 0.176; // 170bpm 1/8th notes, anything slower isn't considered a jack
|
|
||||||
// TechCounts methods
|
|
||||||
|
|
||||||
|
// 0.176 ~= 1/8th at 175bpm
|
||||||
|
// Anything slower isn't counted as a jack
|
||||||
|
const float JACK_CUTOFF = 0.176;
|
||||||
|
// 0.3 = 1/4th at 200bpm (or 3/16th at 150bpm)
|
||||||
|
// Anything slower isn't counted as a footswitch
|
||||||
|
const float FOOTSWITCH_CUTOFF = 0.3;
|
||||||
|
// 0.235 ~= 1/8th at 128bpm
|
||||||
|
// Anything slower isn't counted as a doublestep
|
||||||
|
const float DOUBLESTEP_CUTOFF = 0.235;
|
||||||
|
|
||||||
|
// TechCounts methods
|
||||||
TechCounts::TechCounts()
|
TechCounts::TechCounts()
|
||||||
{
|
{
|
||||||
MakeUnknown();
|
MakeUnknown();
|
||||||
@@ -104,6 +113,7 @@ void TechCounts::CalculateTechCountsFromRows(const std::vector<StepParity::Row>
|
|||||||
const StepParity::Row &previousRow = rows[i - 1];
|
const StepParity::Row &previousRow = rows[i - 1];
|
||||||
|
|
||||||
int noteCount = 0;
|
int noteCount = 0;
|
||||||
|
float elapsedTime = currentRow.second - previousRow.second;
|
||||||
|
|
||||||
// copy the foot placement for the current row into currentColumns,
|
// copy the foot placement for the current row into currentColumns,
|
||||||
// and count up how many notes there are in this row
|
// and count up how many notes there are in this row
|
||||||
@@ -145,14 +155,17 @@ void TechCounts::CalculateTechCountsFromRows(const std::vector<StepParity::Row>
|
|||||||
|
|
||||||
if(previousFootPlacement[foot] == currentFootPlacement[foot])
|
if(previousFootPlacement[foot] == currentFootPlacement[foot])
|
||||||
{
|
{
|
||||||
if(currentRow.second - previousRow.second < JACK_CUTOFF)
|
if(elapsedTime < JACK_CUTOFF)
|
||||||
{
|
{
|
||||||
out[TechCountsCategory_Jacks] += 1;
|
out[TechCountsCategory_Jacks] += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
out[TechCountsCategory_Doublesteps] += 1;
|
if(elapsedTime < DOUBLESTEP_CUTOFF)
|
||||||
|
{
|
||||||
|
out[TechCountsCategory_Doublesteps] += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -183,6 +196,7 @@ void TechCounts::CalculateTechCountsFromRows(const std::vector<StepParity::Row>
|
|||||||
if(previousColumns[c] != StepParity::NONE
|
if(previousColumns[c] != StepParity::NONE
|
||||||
&& previousColumns[c] != currentColumns[c]
|
&& previousColumns[c] != currentColumns[c]
|
||||||
&& StepParity::OTHER_PART_OF_FOOT[previousColumns[c]] != currentColumns[c]
|
&& StepParity::OTHER_PART_OF_FOOT[previousColumns[c]] != currentColumns[c]
|
||||||
|
&& elapsedTime < FOOTSWITCH_CUTOFF
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// this is assuming only 4-panel single
|
// this is assuming only 4-panel single
|
||||||
|
|||||||
Reference in New Issue
Block a user