Tweak byregot scoring system, add bonuses to config
This commit is contained in:
@@ -12,8 +12,8 @@ internal sealed class AdvancedTouchCombo : BaseAction
|
|||||||
public override int CPCost(Simulator s) => 18 + 18 + 18;
|
public override int CPCost(Simulator s) => 18 + 18 + 18;
|
||||||
|
|
||||||
public override bool CanUse(Simulator s) =>
|
public override bool CanUse(Simulator s) =>
|
||||||
// BasicTouch.DurabilityCost vv vv StandardTouch.DurabilityCost
|
// BasicTouch.DurabilityCost vv vv StandardTouch.DurabilityCost
|
||||||
base.CanUse(s) && StandardTouchCombo.VerifyDurability3(s, 10, 10);
|
base.CanUse(s) && VerifyDurability3(s, 10, 10);
|
||||||
|
|
||||||
private static readonly BasicTouch ActionA = new();
|
private static readonly BasicTouch ActionA = new();
|
||||||
private static readonly StandardTouch ActionB = new();
|
private static readonly StandardTouch ActionB = new();
|
||||||
|
|||||||
@@ -80,4 +80,54 @@ public abstract class BaseAction
|
|||||||
builder.AppendLine($"{s.CalculateSuccessRate(SuccessRate(s)) * 100:##}%% Success Rate");
|
builder.AppendLine($"{s.CalculateSuccessRate(SuccessRate(s)) * 100:##}%% Success Rate");
|
||||||
return builder.ToString();
|
return builder.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool VerifyDurability2(int durabilityA, int durability, Effects effects)
|
||||||
|
{
|
||||||
|
var wasteNots = effects.HasEffect(EffectType.WasteNot) || effects.HasEffect(EffectType.WasteNot2);
|
||||||
|
// -A
|
||||||
|
durability -= (int)MathF.Ceiling(durabilityA * (wasteNots ? .5f : 1f));
|
||||||
|
if (durability <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// If we can do the first action and still have durability left to survive to the next
|
||||||
|
// step (even before the Manipulation modifier), we can certainly do the next action.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool VerifyDurability2(SimulationState s, int durabilityA) =>
|
||||||
|
VerifyDurability2(durabilityA, s.Durability, s.ActiveEffects);
|
||||||
|
|
||||||
|
public static bool VerifyDurability2(Simulator s, int durabilityA) =>
|
||||||
|
VerifyDurability2(durabilityA, s.Durability, s.ActiveEffects);
|
||||||
|
|
||||||
|
public static bool VerifyDurability3(int durabilityA, int durabilityB, int durability, Effects effects)
|
||||||
|
{
|
||||||
|
var wasteNots = Math.Max(effects.GetDuration(EffectType.WasteNot), effects.GetDuration(EffectType.WasteNot2));
|
||||||
|
var manips = effects.HasEffect(EffectType.Manipulation);
|
||||||
|
|
||||||
|
durability -= (int)MathF.Ceiling(durabilityA * wasteNots > 0 ? .5f : 1f);
|
||||||
|
if (durability <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (manips)
|
||||||
|
durability += 5;
|
||||||
|
|
||||||
|
if (wasteNots > 0)
|
||||||
|
wasteNots--;
|
||||||
|
|
||||||
|
durability -= (int)MathF.Ceiling(durabilityB * wasteNots > 0 ? .5f : 1f);
|
||||||
|
|
||||||
|
if (durability <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// If we can do the second action and still have durability left to survive to the next
|
||||||
|
// step (even before the Manipulation modifier), we can certainly do the next action.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool VerifyDurability3(Simulator s, int durabilityA, int durabilityB) =>
|
||||||
|
VerifyDurability3(durabilityA, durabilityB, s.Durability, s.ActiveEffects);
|
||||||
|
|
||||||
|
public static bool VerifyDurability3(SimulationState s, int durabilityA, int durabilityB) =>
|
||||||
|
VerifyDurability3(durabilityA, durabilityB, s.Durability, s.ActiveEffects);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ internal sealed class FocusedSynthesisCombo : BaseAction
|
|||||||
public override int CPCost(Simulator s) => 7 + 5;
|
public override int CPCost(Simulator s) => 7 + 5;
|
||||||
|
|
||||||
public override bool CanUse(Simulator s) =>
|
public override bool CanUse(Simulator s) =>
|
||||||
// Observe.DurabilityCost v
|
// Observe.DurabilityCost v
|
||||||
base.CanUse(s) && StandardTouchCombo.VerifyDurability2(s, 0);
|
base.CanUse(s) && VerifyDurability2(s, 0);
|
||||||
|
|
||||||
private static readonly Observe ActionA = new();
|
private static readonly Observe ActionA = new();
|
||||||
private static readonly FocusedSynthesis ActionB = new();
|
private static readonly FocusedSynthesis ActionB = new();
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ internal sealed class FocusedTouchCombo : BaseAction
|
|||||||
public override int CPCost(Simulator s) => 7 + 18;
|
public override int CPCost(Simulator s) => 7 + 18;
|
||||||
|
|
||||||
public override bool CanUse(Simulator s) =>
|
public override bool CanUse(Simulator s) =>
|
||||||
// Observe.DurabilityCost v
|
// Observe.DurabilityCost v
|
||||||
base.CanUse(s) && StandardTouchCombo.VerifyDurability2(s, 0);
|
base.CanUse(s) && VerifyDurability2(s, 0);
|
||||||
|
|
||||||
private static readonly Observe ActionA = new();
|
private static readonly Observe ActionA = new();
|
||||||
private static readonly FocusedTouch ActionB = new();
|
private static readonly FocusedTouch ActionB = new();
|
||||||
|
|||||||
@@ -25,45 +25,4 @@ internal sealed class StandardTouchCombo : BaseAction
|
|||||||
|
|
||||||
public override string GetTooltip(Simulator s, bool addUsability) =>
|
public override string GetTooltip(Simulator s, bool addUsability) =>
|
||||||
$"{ActionA.GetTooltip(s, addUsability)}\n{ActionB.GetTooltip(s, addUsability)}";
|
$"{ActionA.GetTooltip(s, addUsability)}\n{ActionB.GetTooltip(s, addUsability)}";
|
||||||
|
|
||||||
public static bool VerifyDurability2(Simulator s, int durabilityA)
|
|
||||||
{
|
|
||||||
var d = s.Durability;
|
|
||||||
var wasteNots = s.HasEffect(EffectType.WasteNot) || s.HasEffect(EffectType.WasteNot2);
|
|
||||||
|
|
||||||
// -A
|
|
||||||
d -= (int)MathF.Ceiling(durabilityA * (wasteNots ? .5f : 1f));
|
|
||||||
if (d <= 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// If we can do the first action and still have durability left to survive to the next
|
|
||||||
// step (even before the Manipulation modifier), we can certainly do the next action.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool VerifyDurability3(Simulator s, int durabilityA, int durabilityB)
|
|
||||||
{
|
|
||||||
var d = s.Durability;
|
|
||||||
var wasteNots = Math.Max(s.GetEffectDuration(EffectType.WasteNot), s.GetEffectDuration(EffectType.WasteNot2));
|
|
||||||
var manips = s.GetEffectDuration(EffectType.Manipulation);
|
|
||||||
|
|
||||||
d -= (int)MathF.Ceiling(durabilityA * wasteNots > 0 ? .5f : 1f);
|
|
||||||
if (d <= 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (manips > 0)
|
|
||||||
d += 5;
|
|
||||||
|
|
||||||
if (wasteNots > 0)
|
|
||||||
wasteNots--;
|
|
||||||
|
|
||||||
d -= (int)MathF.Ceiling(durabilityB * wasteNots > 0 ? .5f : 1f);
|
|
||||||
|
|
||||||
if (d <= 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// If we can do the second action and still have durability left to survive to the next
|
|
||||||
// step (even before the Manipulation modifier), we can certainly do the next action.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,27 +30,18 @@ public struct SimulationNode
|
|||||||
CompletionState.NoMoreActions :
|
CompletionState.NoMoreActions :
|
||||||
simCompletionState;
|
simCompletionState;
|
||||||
|
|
||||||
public readonly float? CalculateScore(int maxStepCount) => CalculateScoreForState(State, SimulationCompletionState, maxStepCount);
|
public readonly float? CalculateScore(SolverConfig config) =>
|
||||||
|
CalculateScoreForState(State, SimulationCompletionState, config);
|
||||||
|
|
||||||
private static bool CanByregot(SimulationState state)
|
private static bool CanByregot(SimulationState state)
|
||||||
{
|
{
|
||||||
if (state.ActiveEffects.InnerQuiet == 0)
|
if (state.ActiveEffects.InnerQuiet == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var wasteNot = Math.Max(state.ActiveEffects.WasteNot, state.ActiveEffects.WasteNot2);
|
return BaseAction.VerifyDurability2(state, 10);
|
||||||
var manipulation = state.ActiveEffects.Manipulation;
|
|
||||||
var durability = state.Durability;
|
|
||||||
durability -= wasteNot-- > 0 ? 5 : 10;
|
|
||||||
if (durability <= 0)
|
|
||||||
return false;
|
|
||||||
if (manipulation-- > 0)
|
|
||||||
durability += 5;
|
|
||||||
durability -= wasteNot-- > 0 ? 5 : 10;
|
|
||||||
|
|
||||||
return durability >= 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float? CalculateScoreForState(SimulationState state, CompletionState completionState, int maxStepCount)
|
public static float? CalculateScoreForState(SimulationState state, CompletionState completionState, SolverConfig config)
|
||||||
{
|
{
|
||||||
if (completionState != CompletionState.ProgressComplete)
|
if (completionState != CompletionState.ProgressComplete)
|
||||||
return null;
|
return null;
|
||||||
@@ -58,40 +49,33 @@ public struct SimulationNode
|
|||||||
static float Apply(float bonus, float value, float target) =>
|
static float Apply(float bonus, float value, float target) =>
|
||||||
bonus * Math.Min(1f, value / target);
|
bonus * Math.Min(1f, value / target);
|
||||||
|
|
||||||
var progressBonus = 0.20f;
|
|
||||||
var qualityBonus = 0.65f;
|
|
||||||
var durabilityBonus = 0.05f;
|
|
||||||
var cpBonus = 0.05f;
|
|
||||||
var fewerStepsBonus = 0.05f;
|
|
||||||
|
|
||||||
var progressScore = Apply(
|
var progressScore = Apply(
|
||||||
progressBonus,
|
config.ScoreProgressBonus,
|
||||||
state.Progress,
|
state.Progress,
|
||||||
state.Input.Recipe.MaxProgress
|
state.Input.Recipe.MaxProgress
|
||||||
);
|
);
|
||||||
|
|
||||||
var byregotBonus = CanByregot(state) ? (state.ActiveEffects.InnerQuiet * .2f + 1) * state.Input.BaseQualityGain : 0;
|
var byregotBonus = CanByregot(state) ? (state.ActiveEffects.InnerQuiet * .2f + 1) * state.Input.BaseQualityGain : 0;
|
||||||
var quality = Math.Clamp(state.Quality + byregotBonus, 0, state.Input.Recipe.MaxQuality);
|
|
||||||
var qualityScore = Apply(
|
var qualityScore = Apply(
|
||||||
qualityBonus,
|
config.ScoreQualityBonus,
|
||||||
quality,
|
state.Quality + byregotBonus,
|
||||||
state.Input.Recipe.MaxQuality
|
state.Input.Recipe.MaxQuality
|
||||||
);
|
);
|
||||||
|
|
||||||
var durabilityScore = Apply(
|
var durabilityScore = Apply(
|
||||||
durabilityBonus,
|
config.ScoreDurabilityBonus,
|
||||||
state.Durability,
|
state.Durability,
|
||||||
state.Input.Recipe.MaxDurability
|
state.Input.Recipe.MaxDurability
|
||||||
);
|
);
|
||||||
|
|
||||||
var cpScore = Apply(
|
var cpScore = Apply(
|
||||||
cpBonus,
|
config.ScoreCPBonus,
|
||||||
state.CP,
|
state.CP,
|
||||||
state.Input.Stats.CP
|
state.Input.Stats.CP
|
||||||
);
|
);
|
||||||
|
|
||||||
var fewerStepsScore =
|
var fewerStepsScore =
|
||||||
fewerStepsBonus * (1f - ((float)(state.ActionCount + 1) / maxStepCount));
|
config.ScoreFewerStepsBonus * (1f - ((float)(state.ActionCount + 1) / config.MaxStepCount));
|
||||||
|
|
||||||
return progressScore + qualityScore + durabilityScore + cpScore + fewerStepsScore;
|
return progressScore + qualityScore + durabilityScore + cpScore + fewerStepsScore;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ public sealed class Solver
|
|||||||
ref var initialState = ref initialNode.State;
|
ref var initialState = ref initialNode.State;
|
||||||
// expand once
|
// expand once
|
||||||
if (initialState.IsComplete)
|
if (initialState.IsComplete)
|
||||||
return (initialNode, initialState.CalculateScore(config.MaxStepCount) ?? 0);
|
return (initialNode, initialState.CalculateScore(config) ?? 0);
|
||||||
|
|
||||||
var poppedAction = initialState.AvailableActions.PopRandom(random);
|
var poppedAction = initialState.AvailableActions.PopRandom(random);
|
||||||
var expandedNode = initialNode.Add(Execute(simulator, initialState.State, poppedAction, true));
|
var expandedNode = initialNode.Add(Execute(simulator, initialState.State, poppedAction, true));
|
||||||
@@ -225,7 +225,7 @@ public sealed class Solver
|
|||||||
}
|
}
|
||||||
|
|
||||||
// store the result if a max score was reached
|
// store the result if a max score was reached
|
||||||
var score = SimulationNode.CalculateScoreForState(currentState, currentCompletionState, config.MaxStepCount) ?? 0;
|
var score = SimulationNode.CalculateScoreForState(currentState, currentCompletionState, config) ?? 0;
|
||||||
if (currentCompletionState == CompletionState.ProgressComplete)
|
if (currentCompletionState == CompletionState.ProgressComplete)
|
||||||
{
|
{
|
||||||
if (score >= config.ScoreStorageThreshold && score >= MaxScore)
|
if (score >= config.ScoreStorageThreshold && score >= MaxScore)
|
||||||
|
|||||||
@@ -15,6 +15,12 @@ public readonly record struct SolverConfig
|
|||||||
public int FurcatedActionCount { get; init; }
|
public int FurcatedActionCount { get; init; }
|
||||||
public bool StrictActions { get; init; }
|
public bool StrictActions { get; init; }
|
||||||
|
|
||||||
|
public float ScoreProgressBonus { get; init; }
|
||||||
|
public float ScoreQualityBonus { get; init; }
|
||||||
|
public float ScoreDurabilityBonus { get; init; }
|
||||||
|
public float ScoreCPBonus { get; init; }
|
||||||
|
public float ScoreFewerStepsBonus { get; init; }
|
||||||
|
|
||||||
public SolverConfig()
|
public SolverConfig()
|
||||||
{
|
{
|
||||||
Iterations = 300000;
|
Iterations = 300000;
|
||||||
@@ -26,5 +32,11 @@ public readonly record struct SolverConfig
|
|||||||
ForkCount = Environment.ProcessorCount;
|
ForkCount = Environment.ProcessorCount;
|
||||||
FurcatedActionCount = ForkCount / 2;
|
FurcatedActionCount = ForkCount / 2;
|
||||||
StrictActions = true;
|
StrictActions = true;
|
||||||
|
|
||||||
|
ScoreProgressBonus = .20f;
|
||||||
|
ScoreQualityBonus = .65f;
|
||||||
|
ScoreDurabilityBonus = .05f;
|
||||||
|
ScoreCPBonus = .05f;
|
||||||
|
ScoreFewerStepsBonus = .05f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user