Changed StageLayout into a struct and consolidated layout math functions into it.
Added convenience methods for determining if a given column is an up, down, or side arrow. Added explicit tech counts for up footswitches and down footswitches
This commit is contained in:
+23
-118
@@ -7,30 +7,6 @@
|
|||||||
using namespace StepParity;
|
using namespace StepParity;
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool vectorIncludes(const std::vector<T>& vec, const T& value, int columnCount) {
|
|
||||||
for (int i = 0; i < columnCount; i++)
|
|
||||||
{
|
|
||||||
if(vec[i] == value)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
int indexOf(const std::vector<T>& vec, const T& value, int columnCount) {
|
|
||||||
for (int i = 0; i < columnCount; i++)
|
|
||||||
{
|
|
||||||
if(vec[i] == value)
|
|
||||||
{
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool isEmpty(const std::vector<T> & vec, int columnCount) {
|
bool isEmpty(const std::vector<T> & vec, int columnCount) {
|
||||||
for (int i = 0; i < columnCount; i++)
|
for (int i = 0; i < columnCount; i++)
|
||||||
@@ -241,7 +217,7 @@ float StepParityCost::calcHoldSwitchCost(State * initialState, State * resultSta
|
|||||||
(previousFoot == -1
|
(previousFoot == -1
|
||||||
? 1
|
? 1
|
||||||
: sqrt(
|
: sqrt(
|
||||||
getDistanceSq(layout[c], layout[previousFoot])
|
layout.getDistanceSq(c, previousFoot)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -427,12 +403,12 @@ float StepParityCost::calcTwistedFootCost(State * resultState)
|
|||||||
int rightHeel = resultState->whereTheFeetAre[RIGHT_HEEL];
|
int rightHeel = resultState->whereTheFeetAre[RIGHT_HEEL];
|
||||||
int rightToe = resultState->whereTheFeetAre[RIGHT_TOE];
|
int rightToe = resultState->whereTheFeetAre[RIGHT_TOE];
|
||||||
|
|
||||||
StagePoint leftPos = averagePoint(leftHeel, leftToe);
|
StagePoint leftPos = layout.averagePoint(leftHeel, leftToe);
|
||||||
StagePoint rightPos = averagePoint(rightHeel, rightToe);
|
StagePoint rightPos = layout.averagePoint(rightHeel, rightToe);
|
||||||
|
|
||||||
bool crossedOver = rightPos.x < leftPos.x;
|
bool crossedOver = rightPos.x < leftPos.x;
|
||||||
bool rightBackwards = rightHeel != -1 && rightToe != -1 ? layout[rightToe].y < layout[rightHeel].y : false;
|
bool rightBackwards = rightHeel != -1 && rightToe != -1 ? layout.columns[rightToe].y < layout.columns[rightHeel].y : false;
|
||||||
bool leftBackwards = leftHeel != -1 && leftToe != -1 ? layout[leftToe].y < layout[leftHeel].y : false;
|
bool leftBackwards = leftHeel != -1 && leftToe != -1 ? layout.columns[leftToe].y < layout.columns[leftHeel].y : false;
|
||||||
|
|
||||||
if(!crossedOver && (rightBackwards || leftBackwards))
|
if(!crossedOver && (rightBackwards || leftBackwards))
|
||||||
{
|
{
|
||||||
@@ -493,19 +469,19 @@ float StepParityCost::calcFacingCosts(State * initialState, State * resultState,
|
|||||||
// facing backwards gives a bit of bad weight (scaled heavily the further back you angle, so crossovers aren't Too bad; less bad than doublesteps)
|
// facing backwards gives a bit of bad weight (scaled heavily the further back you angle, so crossovers aren't Too bad; less bad than doublesteps)
|
||||||
float heelFacing =
|
float heelFacing =
|
||||||
endLeftHeel != -1 && endRightHeel != -1
|
endLeftHeel != -1 && endRightHeel != -1
|
||||||
? getXDifference(endLeftHeel, endRightHeel)
|
? layout.getXDifference(endLeftHeel, endRightHeel)
|
||||||
: 0;
|
: 0;
|
||||||
float toeFacing =
|
float toeFacing =
|
||||||
endLeftToe != -1 && endRightToe != -1
|
endLeftToe != -1 && endRightToe != -1
|
||||||
? getXDifference(endLeftToe, endRightToe)
|
? layout.getXDifference(endLeftToe, endRightToe)
|
||||||
: 0;
|
: 0;
|
||||||
float leftFacing =
|
float leftFacing =
|
||||||
endLeftHeel != -1 && endLeftToe != -1
|
endLeftHeel != -1 && endLeftToe != -1
|
||||||
? getYDifference(endLeftHeel, endLeftToe)
|
? layout.getYDifference(endLeftHeel, endLeftToe)
|
||||||
: 0;
|
: 0;
|
||||||
float rightFacing =
|
float rightFacing =
|
||||||
endRightHeel != -1 && endRightToe != -1
|
endRightHeel != -1 && endRightToe != -1
|
||||||
? getYDifference(endRightHeel, endRightToe)
|
? layout.getYDifference(endRightHeel, endRightToe)
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
|
|
||||||
@@ -560,16 +536,16 @@ float StepParityCost::calcSpinCosts(State * initialState, State * resultState, s
|
|||||||
if (endRightToe == -1) endRightToe = endRightHeel;
|
if (endRightToe == -1) endRightToe = endRightHeel;
|
||||||
|
|
||||||
// spin
|
// spin
|
||||||
StagePoint previousLeftPos = averagePoint(
|
StagePoint previousLeftPos = layout.averagePoint(
|
||||||
initialState->whereTheFeetAre[LEFT_HEEL],
|
initialState->whereTheFeetAre[LEFT_HEEL],
|
||||||
initialState->whereTheFeetAre[LEFT_TOE]
|
initialState->whereTheFeetAre[LEFT_TOE]
|
||||||
);
|
);
|
||||||
StagePoint previousRightPos = averagePoint(
|
StagePoint previousRightPos = layout.averagePoint(
|
||||||
initialState->whereTheFeetAre[RIGHT_HEEL],
|
initialState->whereTheFeetAre[RIGHT_HEEL],
|
||||||
initialState->whereTheFeetAre[RIGHT_TOE]
|
initialState->whereTheFeetAre[RIGHT_TOE]
|
||||||
);
|
);
|
||||||
StagePoint leftPos = averagePoint(endLeftHeel, endLeftToe);
|
StagePoint leftPos = layout.averagePoint(endLeftHeel, endLeftToe);
|
||||||
StagePoint rightPos = averagePoint(endRightHeel, endRightToe);
|
StagePoint rightPos = layout.averagePoint(endRightHeel, endRightToe);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
rightPos.x < leftPos.x &&
|
rightPos.x < leftPos.x &&
|
||||||
@@ -626,26 +602,19 @@ float StepParityCost::caclFootswitchCost(State * initialState, State * resultSta
|
|||||||
return cost;
|
return cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This doesn't work for doubles, since it's only checking P1 left and P1 right
|
|
||||||
float StepParityCost::calcSideswitchCost(State * initialState, State * resultState, int columnCount)
|
float StepParityCost::calcSideswitchCost(State * initialState, State * resultState, int columnCount)
|
||||||
{
|
{
|
||||||
float cost = 0;
|
float cost = 0;
|
||||||
if (
|
for(auto c : layout.sideArrows)
|
||||||
initialState->columns[0] != resultState->columns[0] &&
|
|
||||||
resultState->columns[0] != NONE &&
|
|
||||||
initialState->columns[0] != NONE &&
|
|
||||||
!resultState->didTheFootMove[initialState->columns[0]])
|
|
||||||
{
|
{
|
||||||
cost += SIDESWITCH;
|
if (
|
||||||
}
|
initialState->columns[c] != resultState->columns[c] &&
|
||||||
|
resultState->columns[c] != NONE &&
|
||||||
if (
|
initialState->columns[c] != NONE &&
|
||||||
initialState->columns[3] != resultState->columns[3] &&
|
!resultState->didTheFootMove[initialState->columns[c]])
|
||||||
resultState->columns[3] != NONE &&
|
{
|
||||||
initialState->columns[3] != NONE &&
|
cost += SIDESWITCH;
|
||||||
!resultState->didTheFootMove[initialState->columns[3]]
|
}
|
||||||
) {
|
|
||||||
cost += SIDESWITCH;
|
|
||||||
}
|
}
|
||||||
return cost;
|
return cost;
|
||||||
}
|
}
|
||||||
@@ -694,7 +663,7 @@ float StepParityCost::calcBigMovementsQuicklyCost(State * initialState, State *
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
float dist = (sqrt(getDistanceSq(layout[initialPosition], layout[resultPosition])) * DISTANCE) / elapsedTime;
|
float dist = (sqrt(layout.getDistanceSq(initialPosition, resultPosition)) * DISTANCE) / elapsedTime;
|
||||||
// Otherwise if we're still bracketing, this is probably a less drastic movement
|
// Otherwise if we're still bracketing, this is probably a less drastic movement
|
||||||
if(isBracketing)
|
if(isBracketing)
|
||||||
{
|
{
|
||||||
@@ -878,67 +847,3 @@ bool StepParityCost::didJackRight(State * initialState, State * resultState, int
|
|||||||
}
|
}
|
||||||
return jackedRight;
|
return jackedRight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
float StepParityCost::getDistanceSq(StepParity::StagePoint p1, StepParity::StagePoint p2)
|
|
||||||
{
|
|
||||||
return (p1.y - p2.y) * (p1.y - p2.y) + (p1.x - p2.x) * (p1.x - p2.x);
|
|
||||||
}
|
|
||||||
|
|
||||||
float StepParityCost::getPlayerAngle(StepParity::StagePoint left, StepParity::StagePoint right)
|
|
||||||
{
|
|
||||||
float x1 = right.x - left.x;
|
|
||||||
float y1 = right.y - left.y;
|
|
||||||
float x2 = 1;
|
|
||||||
float y2 = 0;
|
|
||||||
float dot = x1 * x2 + y1 * y2;
|
|
||||||
float det = x1 * y2 - y1 * x2;
|
|
||||||
return atan2f(det, dot);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
float StepParityCost::getXDifference(int leftIndex, int rightIndex) {
|
|
||||||
if (leftIndex == rightIndex) return 0;
|
|
||||||
float dx = layout[rightIndex].x - layout[leftIndex].x;
|
|
||||||
float dy = layout[rightIndex].y - layout[leftIndex].y;
|
|
||||||
|
|
||||||
float distance = sqrt(dx * dx + dy * dy);
|
|
||||||
dx /= distance;
|
|
||||||
|
|
||||||
bool negative = dx <= 0;
|
|
||||||
|
|
||||||
dx = pow(dx, 4);
|
|
||||||
|
|
||||||
if (negative) dx = -dx;
|
|
||||||
|
|
||||||
return dx;
|
|
||||||
}
|
|
||||||
|
|
||||||
float StepParityCost::getYDifference(int leftIndex, int rightIndex) {
|
|
||||||
if (leftIndex == rightIndex) return 0;
|
|
||||||
float dx = layout[rightIndex].x - layout[leftIndex].x;
|
|
||||||
float dy = layout[rightIndex].y - layout[leftIndex].y;
|
|
||||||
|
|
||||||
float distance = sqrt(dx * dx + dy * dy);
|
|
||||||
dy /= distance;
|
|
||||||
|
|
||||||
bool negative = dy <= 0;
|
|
||||||
|
|
||||||
dy = pow(dy, 4);
|
|
||||||
|
|
||||||
if (negative) dy = -dy;
|
|
||||||
|
|
||||||
return dy;
|
|
||||||
}
|
|
||||||
|
|
||||||
StagePoint StepParityCost::averagePoint(int leftIndex, int rightIndex) {
|
|
||||||
if (leftIndex == -1 && rightIndex == -1) return { 0,0 };
|
|
||||||
if (leftIndex == -1) return layout[rightIndex];
|
|
||||||
if (rightIndex == -1) return layout[leftIndex];
|
|
||||||
return {
|
|
||||||
(layout[leftIndex].x + layout[rightIndex].x) / 2.0f,
|
|
||||||
(layout[leftIndex].y + layout[rightIndex].y) / 2.0f,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|||||||
+1
-11
@@ -45,9 +45,7 @@ namespace StepParity
|
|||||||
StageLayout layout;
|
StageLayout layout;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StepParityCost(StageLayout _layout)
|
StepParityCost(const StageLayout& _layout): layout(_layout){
|
||||||
{
|
|
||||||
layout = _layout;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Computes and returns a cost value for the player moving from initialState to resultState.
|
/// @brief Computes and returns a cost value for the player moving from initialState to resultState.
|
||||||
@@ -81,14 +79,6 @@ namespace StepParity
|
|||||||
bool didDoubleStep(State * initialState, State * resultState, std::vector<Row> &rows, int rowIndex, bool movedLeft, bool jackedLeft, bool movedRight, bool jackedRight, int columnCount);
|
bool didDoubleStep(State * initialState, State * resultState, std::vector<Row> &rows, int rowIndex, bool movedLeft, bool jackedLeft, bool movedRight, bool jackedRight, int columnCount);
|
||||||
bool didJackLeft(State * initialState, State * resultState, int leftHeel, int leftToe, bool movedLeft, bool didJump, int columnCount);
|
bool didJackLeft(State * initialState, State * resultState, int leftHeel, int leftToe, bool movedLeft, bool didJump, int columnCount);
|
||||||
bool didJackRight(State * initialState, State * resultState, int rightHeel, int rightToe, bool movedRight, bool didJump,int columnCount);
|
bool didJackRight(State * initialState, State * resultState, int rightHeel, int rightToe, bool movedRight, bool didJump,int columnCount);
|
||||||
|
|
||||||
float getDistanceSq(StepParity::StagePoint p1, StepParity::StagePoint p2);
|
|
||||||
float getPlayerAngle(StepParity::StagePoint left, StepParity::StagePoint right);
|
|
||||||
|
|
||||||
float getXDifference(int leftIndex, int rightIndex);
|
|
||||||
float getYDifference(int leftIndex, int rightIndex);
|
|
||||||
StagePoint averagePoint(int leftIndex, int rightIndex);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -74,6 +74,100 @@ StepParityNode * StepParityGraph::addOrGetExistingNode(const State &state)
|
|||||||
return stateNodeMap[rowIndex][state];
|
return stateNodeMap[rowIndex][state];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// StageLayout
|
||||||
|
//
|
||||||
|
|
||||||
|
bool StageLayout::bracketCheck(int column1, int column2)
|
||||||
|
{
|
||||||
|
StagePoint p1 = columns[column1];
|
||||||
|
StagePoint p2 = columns[column2];
|
||||||
|
return getDistanceSq(p1, p2) <= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StageLayout::isSideArrow(int column)
|
||||||
|
{
|
||||||
|
return std::find(sideArrows.begin(), sideArrows.end(), column) != sideArrows.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StageLayout::isUpArrow(int column)
|
||||||
|
{
|
||||||
|
return std::find(upArrows.begin(), upArrows.end(), column) != upArrows.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StageLayout::isDownArrow(int column)
|
||||||
|
{
|
||||||
|
return std::find(downArrows.begin(), downArrows.end(), column) != downArrows.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
float StageLayout::getDistanceSq(int c1, int c2)
|
||||||
|
{
|
||||||
|
return getDistanceSq(columns[c1], columns[c2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
float StageLayout::getDistanceSq(StepParity::StagePoint p1, StepParity::StagePoint p2)
|
||||||
|
{
|
||||||
|
return (p1.y - p2.y) * (p1.y - p2.y) + (p1.x - p2.x) * (p1.x - p2.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
float StageLayout::getXDifference(int leftIndex, int rightIndex) {
|
||||||
|
if (leftIndex == rightIndex) return 0;
|
||||||
|
float dx = columns[rightIndex].x - columns[leftIndex].x;
|
||||||
|
float dy = columns[rightIndex].y - columns[leftIndex].y;
|
||||||
|
|
||||||
|
float distance = sqrt(dx * dx + dy * dy);
|
||||||
|
dx /= distance;
|
||||||
|
|
||||||
|
bool negative = dx <= 0;
|
||||||
|
|
||||||
|
dx = pow(dx, 4);
|
||||||
|
|
||||||
|
if (negative) dx = -dx;
|
||||||
|
|
||||||
|
return dx;
|
||||||
|
}
|
||||||
|
|
||||||
|
float StageLayout::getYDifference(int leftIndex, int rightIndex) {
|
||||||
|
if (leftIndex == rightIndex) return 0;
|
||||||
|
float dx = columns[rightIndex].x - columns[leftIndex].x;
|
||||||
|
float dy = columns[rightIndex].y - columns[leftIndex].y;
|
||||||
|
|
||||||
|
float distance = sqrt(dx * dx + dy * dy);
|
||||||
|
dy /= distance;
|
||||||
|
|
||||||
|
bool negative = dy <= 0;
|
||||||
|
|
||||||
|
dy = pow(dy, 4);
|
||||||
|
|
||||||
|
if (negative) dy = -dy;
|
||||||
|
|
||||||
|
return dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
StagePoint StageLayout::averagePoint(int leftIndex, int rightIndex) {
|
||||||
|
if (leftIndex == -1 && rightIndex == -1) return { 0,0 };
|
||||||
|
if (leftIndex == -1) return columns[rightIndex];
|
||||||
|
if (rightIndex == -1) return columns[leftIndex];
|
||||||
|
return {
|
||||||
|
(columns[leftIndex].x + columns[rightIndex].x) / 2.0f,
|
||||||
|
(columns[leftIndex].y + columns[rightIndex].y) / 2.0f,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
float StageLayout::getPlayerAngle(int c1, int c2)
|
||||||
|
{
|
||||||
|
return getPlayerAngle(columns[c1], columns[c2]);
|
||||||
|
}
|
||||||
|
float StageLayout::getPlayerAngle(StepParity::StagePoint left, StepParity::StagePoint right)
|
||||||
|
{
|
||||||
|
float x1 = right.x - left.x;
|
||||||
|
float y1 = right.y - left.y;
|
||||||
|
float x2 = 1;
|
||||||
|
float y2 = 0;
|
||||||
|
float dot = x1 * x2 + y1 * y2;
|
||||||
|
float det = x1 * y2 - y1 * x2;
|
||||||
|
return atan2f(det, dot);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Json methods
|
// Json methods
|
||||||
|
|||||||
@@ -74,16 +74,43 @@ namespace StepParity {
|
|||||||
"TOTAL"
|
"TOTAL"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct StagePoint {
|
struct StagePoint {
|
||||||
float x;
|
float x;
|
||||||
float y;
|
float y;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief A vector of StagePoints, which represents the
|
// StageLayout represents the relative position of each panel on the dance stage,
|
||||||
/// relative position of each arrow on the dance stage.
|
// and provides some basic math function
|
||||||
typedef std::vector<StagePoint> StageLayout;
|
struct StageLayout {
|
||||||
|
StepsType type;
|
||||||
|
int columnCount;
|
||||||
|
std::vector<StagePoint> columns;
|
||||||
|
std::vector<int> upArrows;
|
||||||
|
std::vector<int> downArrows;
|
||||||
|
std::vector<int> sideArrows;
|
||||||
|
|
||||||
|
|
||||||
|
StageLayout(StepsType t,
|
||||||
|
const std::vector<StagePoint>& c,
|
||||||
|
const std::vector<int> & u,
|
||||||
|
const std::vector<int> & d,
|
||||||
|
const std::vector<int> & s) :type(t), columns(c), upArrows(u), downArrows(d), sideArrows(s) {
|
||||||
|
this->columnCount = static_cast<int>(this->columns.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool bracketCheck(int column1, int column2);
|
||||||
|
bool isSideArrow(int column);
|
||||||
|
bool isUpArrow(int column);
|
||||||
|
bool isDownArrow(int column);
|
||||||
|
float getDistanceSq(int c1, int c2);
|
||||||
|
float getDistanceSq(StagePoint p1, StagePoint p2);
|
||||||
|
float getXDifference(int leftIndex, int rightIndex);
|
||||||
|
float getYDifference(int leftIndex, int rightIndex);
|
||||||
|
StagePoint averagePoint(int leftIndex, int rightIndex);
|
||||||
|
float getPlayerAngle(int c1, int c2);
|
||||||
|
float getPlayerAngle(StepParity::StagePoint left, StepParity::StagePoint right);
|
||||||
|
};
|
||||||
|
|
||||||
/// @brief A vector of Foot values, which represents the player's
|
/// @brief A vector of Foot values, which represents the player's
|
||||||
/// foot placement on the dance stage.
|
/// foot placement on the dance stage.
|
||||||
|
|||||||
@@ -5,40 +5,13 @@
|
|||||||
#include "TechCounts.h"
|
#include "TechCounts.h"
|
||||||
#include "GameState.h"
|
#include "GameState.h"
|
||||||
|
|
||||||
// Generates foot parity given notedata
|
|
||||||
// Original algorithm by Jewel, polished by tillvit, then ported to C++
|
|
||||||
|
|
||||||
using namespace StepParity;
|
using namespace StepParity;
|
||||||
|
|
||||||
const std::map<StepsType, StageLayout> Layouts = {
|
|
||||||
{StepsType_dance_single, {
|
|
||||||
{0, 1}, // Left
|
|
||||||
{1, 0}, // Down
|
|
||||||
{1, 2}, // Up
|
|
||||||
{2, 1} // Right
|
|
||||||
}},
|
|
||||||
{StepsType_dance_double, {
|
|
||||||
{0, 1}, // P1 Left
|
|
||||||
{1, 0}, // P1 Down
|
|
||||||
{1, 2}, // P1 Up
|
|
||||||
{2, 1}, // P1 Right
|
|
||||||
|
|
||||||
{3, 1}, // P2 Left
|
|
||||||
{4, 0}, // P2 Down
|
|
||||||
{4, 2}, // P2 Up
|
|
||||||
{5, 1} // P2 Right
|
|
||||||
}}
|
|
||||||
};
|
|
||||||
|
|
||||||
void StepParityGenerator::analyzeNoteData(const NoteData &in, StepsType stepsType)
|
void StepParityGenerator::analyzeNoteData(const NoteData &in)
|
||||||
{
|
{
|
||||||
if(Layouts.find(stepsType) == Layouts.end())
|
|
||||||
{
|
|
||||||
LOG->Warn("Tried to call StepParityGenerator::analyze with an unsupported StepsType %s", StepsTypeToString(stepsType).c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
layout = Layouts.at(stepsType);
|
|
||||||
columnCount = in.GetNumTracks();
|
columnCount = in.GetNumTracks();
|
||||||
|
|
||||||
CreateRows(in);
|
CreateRows(in);
|
||||||
@@ -224,12 +197,12 @@ std::vector<FootPlacement> StepParityGenerator::PermuteFootPlacements(const Row
|
|||||||
}
|
}
|
||||||
if (leftHeelIndex != -1 && leftToeIndex != -1)
|
if (leftHeelIndex != -1 && leftToeIndex != -1)
|
||||||
{
|
{
|
||||||
if (!bracketCheck(leftHeelIndex, leftToeIndex))
|
if (!layout.bracketCheck(leftHeelIndex, leftToeIndex))
|
||||||
return std::vector<FootPlacement>();
|
return std::vector<FootPlacement>();
|
||||||
}
|
}
|
||||||
if (rightHeelIndex != -1 && rightToeIndex != -1)
|
if (rightHeelIndex != -1 && rightToeIndex != -1)
|
||||||
{
|
{
|
||||||
if (!bracketCheck(rightHeelIndex, rightToeIndex))
|
if (!layout.bracketCheck(rightHeelIndex, rightToeIndex))
|
||||||
return std::vector<FootPlacement>();
|
return std::vector<FootPlacement>();
|
||||||
}
|
}
|
||||||
return {columns};
|
return {columns};
|
||||||
@@ -518,15 +491,3 @@ Json::Value StepParityGenerator::SMEditorParityJson()
|
|||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StepParityGenerator::bracketCheck(int column1, int column2)
|
|
||||||
{
|
|
||||||
StagePoint p1 = layout[column1];
|
|
||||||
StagePoint p2 = layout[column2];
|
|
||||||
return getDistanceSq(p1, p2) <= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
float StepParityGenerator::getDistanceSq(StepParity::StagePoint p1, StepParity::StagePoint p2)
|
|
||||||
{
|
|
||||||
return (p1.y - p2.y) * (p1.y - p2.y) + (p1.x - p2.x) * (p1.x - p2.x);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -10,6 +10,26 @@
|
|||||||
|
|
||||||
namespace StepParity {
|
namespace StepParity {
|
||||||
|
|
||||||
|
const std::map<StepsType, StageLayout> Layouts = {
|
||||||
|
{StepsType_dance_single, StageLayout(StepsType_dance_single, {
|
||||||
|
{0, 1}, // Left
|
||||||
|
{1, 0}, // Down
|
||||||
|
{1, 2}, // Up
|
||||||
|
{2, 1} // Right
|
||||||
|
}, {2}, {1}, {0,3})},
|
||||||
|
{StepsType_dance_double, StageLayout(StepsType_dance_double, {
|
||||||
|
{0, 1}, // P1 Left
|
||||||
|
{1, 0}, // P1 Down
|
||||||
|
{1, 2}, // P1 Up
|
||||||
|
{2, 1}, // P1 Right
|
||||||
|
|
||||||
|
{3, 1}, // P2 Left
|
||||||
|
{4, 0}, // P2 Down
|
||||||
|
{4, 2}, // P2 Up
|
||||||
|
{5, 1} // P2 Right
|
||||||
|
}, {26}, {1,5}, {0,3,4,7})}
|
||||||
|
};
|
||||||
|
|
||||||
/// @brief This class handles most of the work for generating step parities for a step chart.
|
/// @brief This class handles most of the work for generating step parities for a step chart.
|
||||||
class StepParityGenerator
|
class StepParityGenerator
|
||||||
{
|
{
|
||||||
@@ -23,11 +43,12 @@ namespace StepParity {
|
|||||||
std::vector<int> nodes_for_rows;
|
std::vector<int> nodes_for_rows;
|
||||||
int columnCount;
|
int columnCount;
|
||||||
|
|
||||||
|
StepParityGenerator(const StageLayout & l) : layout(l) {
|
||||||
|
}
|
||||||
/// @brief Analyzes the given NoteData to generate a vector of StepParity::Rows, with each step annotated with
|
/// @brief Analyzes the given NoteData to generate a vector of StepParity::Rows, with each step annotated with
|
||||||
/// a foot placement.
|
/// a foot placement.
|
||||||
/// @param in The NoteData to analyze
|
/// @param in The NoteData to analyze
|
||||||
/// @param stepsTypeStr StepsType, currently only supports "dance-single"
|
void analyzeNoteData(const NoteData &in);
|
||||||
void analyzeNoteData(const NoteData &in, StepsType stepsType);
|
|
||||||
|
|
||||||
/// @brief Analyzes the given graph to find the least costly path from the beginnning to the end of the stepchart.
|
/// @brief Analyzes the given graph to find the least costly path from the beginnning to the end of the stepchart.
|
||||||
/// Sets the `parity` for the relevant notes of each row in rows.
|
/// Sets the `parity` for the relevant notes of each row in rows.
|
||||||
|
|||||||
+7
-6
@@ -389,16 +389,17 @@ void Steps::CalculateTechCounts()
|
|||||||
m_CachedTechCounts[pn]
|
m_CachedTechCounts[pn]
|
||||||
.Zero();
|
.Zero();
|
||||||
|
|
||||||
// For now, we're only supporting dance-single and dance-double
|
|
||||||
if(this->m_StepsType != StepsType_dance_single && this->m_StepsType != StepsType_dance_double)
|
// If we don't have a valid layout for this StepsType, then don't even bother
|
||||||
|
if(StepParity::Layouts.find(this->m_StepsType) == StepParity::Layouts.end())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
StepParity::StageLayout layout = StepParity::Layouts.at(this->m_StepsType);
|
||||||
GAMESTATE->SetProcessedTimingData(this->GetTimingData());
|
GAMESTATE->SetProcessedTimingData(this->GetTimingData());
|
||||||
StepParity::StepParityGenerator gen;
|
StepParity::StepParityGenerator gen = StepParity::StepParityGenerator(layout);
|
||||||
gen.analyzeNoteData(tempNoteData, this->m_StepsType);
|
gen.analyzeNoteData(tempNoteData);
|
||||||
TechCounts::CalculateTechCountsFromRows(gen.rows, m_CachedTechCounts[0]);
|
TechCounts::CalculateTechCountsFromRows(gen.rows, layout, m_CachedTechCounts[0]);
|
||||||
std::fill_n( m_CachedTechCounts + 1, NUM_PLAYERS-1, m_CachedTechCounts[0] );
|
std::fill_n( m_CachedTechCounts + 1, NUM_PLAYERS-1, m_CachedTechCounts[0] );
|
||||||
|
|
||||||
GAMESTATE->SetProcessedTimingData(nullptr);
|
GAMESTATE->SetProcessedTimingData(nullptr);
|
||||||
|
|||||||
+14
-4
@@ -11,7 +11,9 @@
|
|||||||
|
|
||||||
static const char *TechCountsCategoryNames[] = {
|
static const char *TechCountsCategoryNames[] = {
|
||||||
"Crossovers",
|
"Crossovers",
|
||||||
"Footswitches",
|
"Total Footswitches",
|
||||||
|
"Up Footswitches",
|
||||||
|
"Down Footswitches",
|
||||||
"Sideswitches",
|
"Sideswitches",
|
||||||
"Jacks",
|
"Jacks",
|
||||||
"Brackets",
|
"Brackets",
|
||||||
@@ -89,7 +91,7 @@ void TechCounts::FromString( RString sTechCounts )
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TechCounts::CalculateTechCountsFromRows(const std::vector<StepParity::Row> &rows, TechCounts &out)
|
void TechCounts::CalculateTechCountsFromRows(const std::vector<StepParity::Row> &rows, StepParity::StageLayout & layout, TechCounts &out)
|
||||||
{
|
{
|
||||||
// arrays to hold the column for each Foot enum.
|
// arrays to hold the column for each Foot enum.
|
||||||
// A value of -1 means that Foot is not on any column
|
// A value of -1 means that Foot is not on any column
|
||||||
@@ -200,13 +202,21 @@ void TechCounts::CalculateTechCountsFromRows(const std::vector<StepParity::Row>
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
// this is assuming only 4-panel single
|
// this is assuming only 4-panel single
|
||||||
if(c == 0 || c == 3)
|
if(layout.isSideArrow(c))
|
||||||
{
|
{
|
||||||
out[TechCountsCategory_Sideswitches] += 1;
|
out[TechCountsCategory_Sideswitches] += 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
out[TechCountsCategory_Footswitches] += 1;
|
out[TechCountsCategory_TotalFootswitches] += 1;
|
||||||
|
if(layout.isUpArrow(c))
|
||||||
|
{
|
||||||
|
out[TechCountsCategory_UpFootswitches] += 1;
|
||||||
|
}
|
||||||
|
else if(layout.isDownArrow(c))
|
||||||
|
{
|
||||||
|
out[TechCountsCategory_DownFootswitches] += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if the right foot is pressing the left arrow, or the left foot is pressing the right ==> crossover
|
// if the right foot is pressing the left arrow, or the left foot is pressing the right ==> crossover
|
||||||
|
|||||||
+4
-2
@@ -12,7 +12,9 @@ class NoteData;
|
|||||||
enum TechCountsCategory
|
enum TechCountsCategory
|
||||||
{
|
{
|
||||||
TechCountsCategory_Crossovers = 0,
|
TechCountsCategory_Crossovers = 0,
|
||||||
TechCountsCategory_Footswitches,
|
TechCountsCategory_TotalFootswitches,
|
||||||
|
TechCountsCategory_UpFootswitches,
|
||||||
|
TechCountsCategory_DownFootswitches,
|
||||||
TechCountsCategory_Sideswitches,
|
TechCountsCategory_Sideswitches,
|
||||||
TechCountsCategory_Jacks,
|
TechCountsCategory_Jacks,
|
||||||
TechCountsCategory_Brackets,
|
TechCountsCategory_Brackets,
|
||||||
@@ -77,7 +79,7 @@ public:
|
|||||||
void FromString( RString sValues );
|
void FromString( RString sValues );
|
||||||
|
|
||||||
void PushSelf( lua_State *L );
|
void PushSelf( lua_State *L );
|
||||||
static void CalculateTechCountsFromRows(const std::vector<StepParity::Row> &rows, TechCounts &out);
|
static void CalculateTechCountsFromRows(const std::vector<StepParity::Row> &rows, StepParity::StageLayout & layout, TechCounts &out);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user