Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

General Touchscreen Rebalance #28396

Open
wants to merge 38 commits into
base: master
Choose a base branch
from

Conversation

BenZeng04
Copy link

This is a refactored version of https://github.com/TDRework/osu/tree/touchscreen-rebalance with significantly reduced runtime.

The proposal overhauls the touchscreen star-rating system, replacing the existing flat exponential to aim star rating with a probabilistic estimation of which hand is used to hit each individual object, maintaining a list of the most likely sequences while calculating difficulty.

All the changes in this PR (and in the previous version) are outlined in https://docs.google.com/document/d/1LWP7W5A5pghMpfXY0cj1v-ODjZsApe-MP2n7PvPOjYs/edit#heading=h.2910458agvn1.

Copy link
Member

@tsunyoku tsunyoku left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are my first thoughts upon just reading the code without considering the values or actual ideas - I'll get to a more thorough review soon when I have more opportunity to properly stomach what is going on here. However, so far I just feel iffy about a lot of the naming and organisational choices.

I'm not sure how I feel about the "raw touch" and "touch" naming because at first glance - what is the difference?

Comment on lines 135 to +157
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate)
{
var skills = new List<Skill>
List<Skill> skills;

if (mods.Any(h => h is OsuModTouchDevice))
{
new Aim(mods, true),
new Aim(mods, false),
new Speed(mods)
};
skills = new List<Skill>
{
new TouchAim(mods, clockRate, true),
new TouchAim(mods, clockRate, false),
new TouchSpeed(mods, clockRate),
new Aim(mods, true),
};
}
else
{
skills = new List<Skill>
{
new Aim(mods, true),
new Aim(mods, false),
new Speed(mods),
};
}
Copy link
Member

@tsunyoku tsunyoku Jun 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this part does really make me nervous about the index-based access of skills. I've mentioned this in the past but has never really been something that strikes me as "we really need to address this now" but with conditionally existing skills I think this is going to become very confusing. I think it might be a good idea to create some record/class containing all of the skills with nullables where necessary so it's less ominous or prone to errors.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the first thing we can do quickly is replace indexing with simple skills.First(x=> x is Speed) to at least make it less confusing to look at

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that this is going to be more confusing and I'm aware that index-based access of skills have been touched on before. The reason that I did this is to improve runtime, as yeahbennou mentioned to me that pre-refactor runtime is horrible, and this is one of the causes of it.

@@ -22,7 +22,7 @@ public static class SpeedEvaluator
/// <item><description>and how easily they can be cheesed.</description></item>
/// </list>
/// </summary>
public static double EvaluateDifficultyOf(DifficultyHitObject current)
public static double EvaluateDifficultyOf(DifficultyHitObject current, bool singletapped)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the naming of singletapped could be reconsidered to seem a little less generic since it really only applies to touch screen while the speed evaluator is used for non-TD too

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely - I took this directly from pre-refactor. Open to suggestions.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed this to tappedWithTouch for now in the latest commit. It seems more accurate.


protected abstract double StrainValueOf(OsuDifficultyHitObject current);

protected abstract double StrainValueIf(OsuDifficultyHitObject simulated, TouchHand currentHand, TouchHand lastHand);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does "if" even mean here?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It means that the object may potentially be hit with a different hand.

The code is severely underdocumented right now, so any confusion regarding the code is expected. I will provide documentation when I can.

Comment on lines 24 to 28
private RawTouchAim(RawTouchAim copy)
: base(copy)
{
withSliders = copy.withSliders;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need all this deep clone stuff? Can't you just new RawTouchAim(clockRate, withSliders) since you have access to the existing skill anyways?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See RawTouchSkill's copy constructor.

LastRightDifficultyObjects = new List<DifficultyHitObject>();
}

protected RawTouchSkill(RawTouchSkill copy)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again I really don't like this design of taking in an existing object to clone from it..


protected abstract double StrainValueIf(OsuDifficultyHitObject simulated, TouchHand currentHand, TouchHand lastHand);

public abstract RawTouchSkill DeepClone();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like I already added enough comments about this at this point but I just really don't like this. What do we actually need deep cloning for?

Comment on lines 41 to 45
protected override RawTouchSkill[] GetRawSkills() => new RawTouchSkill[]
{
new RawTouchAim(clockRate, withSliders),
new RawTouchSpeed(clockRate),
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if it's the right place to put these "raw" skills here... generally speaking I'm having a really hard time trying to understand what the hell is going on

This GetRawSkills exists in a few places and I don't know how I feel about a "touch aim" skill containing "raw" skills for "touch aim" and "touch speed" and vice versa wherever it's relevant

Copy link

@Rian8337 Rian8337 Jun 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the "raw" skills part is the part that I'm most concerned about. It was quite difficult to come up with a good structure as this is the part where aim and speed are mixed together. I'm open to suggestions.

Comment on lines 19 to 26
public TouchProbability(TouchProbability copy)
{
Probability = copy.Probability;
Skills = new RawTouchSkill[copy.Skills.Length];

for (int i = 0; i < Skills.Length; i++)
Skills[i] = copy.Skills[i].DeepClone();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😳

@Givikap120
Copy link
Contributor

I feel like this PR heavily needs general pp refactoring first
Removing independent skills system and implementing single Skills class where one skill can depend on another
Cuz without this the PR looks very messy, with all those copies

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.

6 participants