Plugin: Add Raphael
This commit is contained in:
@@ -13,7 +13,9 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
|
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
|
||||||
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||||
|
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||||
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
|
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -226,7 +226,25 @@ internal static class ImGuiUtils
|
|||||||
|
|
||||||
public static void ArcProgress(float value, float radius, float ratio, uint backgroundColor, uint filledColor)
|
public static void ArcProgress(float value, float radius, float ratio, uint backgroundColor, uint filledColor)
|
||||||
{
|
{
|
||||||
Arc(MathF.PI / 2, MathF.PI / 2 - MathF.Tau * Math.Clamp(value, 0, 1), radius, ratio, backgroundColor, filledColor);
|
float startAngle, endAngle;
|
||||||
|
|
||||||
|
// https://github.com/ocornut/imgui/commit/c895e987adf746a997b655c64a6a8916c549ff6f#diff-d750e175eb584ba76bc560b8e54cf113ccbb31dd33f75078c1588925e197a3afR1304-R1310
|
||||||
|
if (value < 0)
|
||||||
|
{
|
||||||
|
const float ArcSize = 0.15f;
|
||||||
|
startAngle = -value % 1;
|
||||||
|
endAngle = startAngle + ArcSize;
|
||||||
|
|
||||||
|
startAngle = float.Lerp(MathF.PI / 2, -3 * MathF.PI / 2, startAngle);
|
||||||
|
endAngle = float.Lerp(MathF.PI / 2, -3 * MathF.PI / 2, endAngle);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
startAngle = MathF.PI / 2;
|
||||||
|
endAngle = MathF.PI / 2 - MathF.Tau * Math.Clamp(value, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Arc(startAngle, endAngle, radius, ratio, backgroundColor, filledColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class ViolinData
|
public sealed class ViolinData
|
||||||
|
|||||||
@@ -151,6 +151,14 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
ClipboardWindow = new(macros);
|
ClipboardWindow = new(macros);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IActiveNotification DisplaySolverWarning(string text) =>
|
||||||
|
DisplayNotification(new()
|
||||||
|
{
|
||||||
|
Content = text,
|
||||||
|
Title = "Solver Warning",
|
||||||
|
Type = NotificationType.Warning
|
||||||
|
});
|
||||||
|
|
||||||
public IActiveNotification DisplayNotification(Notification notification)
|
public IActiveNotification DisplayNotification(Notification notification)
|
||||||
{
|
{
|
||||||
var ret = Service.NotificationManager.AddNotification(notification);
|
var ret = Service.NotificationManager.AddNotification(notification);
|
||||||
|
|||||||
@@ -191,9 +191,11 @@ internal static class DynamicBars
|
|||||||
var progressWidth = availSpace.Value - percentWidth - spacing;
|
var progressWidth = availSpace.Value - percentWidth - spacing;
|
||||||
var progressColors = Colors.GetSolverProgressColors(solver.ProgressStage);
|
var progressColors = Colors.GetSolverProgressColors(solver.ProgressStage);
|
||||||
|
|
||||||
|
fraction = Math.Clamp(fraction, 0, 1);
|
||||||
|
|
||||||
using (ImRaii.PushColor(ImGuiCol.FrameBg, progressColors.Background))
|
using (ImRaii.PushColor(ImGuiCol.FrameBg, progressColors.Background))
|
||||||
using (ImRaii.PushColor(ImGuiCol.PlotHistogram, progressColors.Foreground))
|
using (ImRaii.PushColor(ImGuiCol.PlotHistogram, progressColors.Foreground))
|
||||||
ImGui.ProgressBar(Math.Clamp(fraction, 0, 1), new(progressWidth, ImGui.GetFrameHeight()), string.Empty);
|
ImGui.ProgressBar(solver.IsIndeterminate ? (float)-ImGui.GetTime() : fraction, new(progressWidth, ImGui.GetFrameHeight()), string.Empty);
|
||||||
if (ImGui.IsItemHovered())
|
if (ImGui.IsItemHovered())
|
||||||
DrawProgressBarTooltip(solver);
|
DrawProgressBarTooltip(solver);
|
||||||
ImGui.SameLine(0, spacing);
|
ImGui.SameLine(0, spacing);
|
||||||
@@ -203,9 +205,15 @@ internal static class DynamicBars
|
|||||||
|
|
||||||
public static void DrawProgressBarTooltip(Solver.Solver solver)
|
public static void DrawProgressBarTooltip(Solver.Solver solver)
|
||||||
{
|
{
|
||||||
var tooltip = $"Solver Progress: {solver.ProgressValue:N0} / {solver.ProgressMax:N0}";
|
string tooltip;
|
||||||
if (solver.ProgressValue > solver.ProgressMax)
|
if (solver.IsIndeterminate)
|
||||||
tooltip += $"\n\nThis is taking longer than expected. Check to see if your gear stats are good and the solver settings are adequate.";
|
tooltip = "Initializing Solver";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tooltip = $"Solver Progress: {solver.ProgressValue:N0} / {solver.ProgressMax:N0}";
|
||||||
|
if (solver.ProgressValue > solver.ProgressMax)
|
||||||
|
tooltip += $"\n\nThis is taking longer than expected. Check to see if your gear stats are good and the solver settings are adequate.";
|
||||||
|
}
|
||||||
ImGuiUtils.TooltipWrapped(tooltip);
|
ImGuiUtils.TooltipWrapped(tooltip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Craftimizer.Plugin;
|
using Craftimizer.Plugin;
|
||||||
using Craftimizer.Simulator;
|
using Craftimizer.Simulator;
|
||||||
using Craftimizer.Simulator.Actions;
|
using Craftimizer.Simulator.Actions;
|
||||||
|
using DotNext.Collections.Generic;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -95,6 +96,7 @@ internal sealed class SimulatedMacro
|
|||||||
private sealed record Step
|
private sealed record Step
|
||||||
{
|
{
|
||||||
public ActionType Action { get; }
|
public ActionType Action { get; }
|
||||||
|
public bool IsEphemeral { get; }
|
||||||
// State *after* executing the action
|
// State *after* executing the action
|
||||||
public ActionResponse Response { get; private set; }
|
public ActionResponse Response { get; private set; }
|
||||||
public SimulationState State { get; private set; }
|
public SimulationState State { get; private set; }
|
||||||
@@ -107,9 +109,10 @@ internal sealed class SimulatedMacro
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Call recalculate after this please!
|
// Call recalculate after this please!
|
||||||
public Step(ActionType action)
|
public Step(ActionType action, bool isEphemeral = false)
|
||||||
{
|
{
|
||||||
Action = action;
|
Action = action;
|
||||||
|
IsEphemeral = isEphemeral;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SimulationState Recalculate(Sim sim, in SimulationState lastState)
|
public SimulationState Recalculate(Sim sim, in SimulationState lastState)
|
||||||
@@ -125,6 +128,7 @@ internal sealed class SimulatedMacro
|
|||||||
};
|
};
|
||||||
|
|
||||||
private List<Step> Macro { get; set; } = [];
|
private List<Step> Macro { get; set; } = [];
|
||||||
|
|
||||||
private SimulationState initialState;
|
private SimulationState initialState;
|
||||||
public SimulationState InitialState
|
public SimulationState InitialState
|
||||||
{
|
{
|
||||||
@@ -140,6 +144,7 @@ internal sealed class SimulatedMacro
|
|||||||
}
|
}
|
||||||
private object QueueLock { get; } = new();
|
private object QueueLock { get; } = new();
|
||||||
private List<Step> QueuedSteps { get; set; } = [];
|
private List<Step> QueuedSteps { get; set; } = [];
|
||||||
|
private List<Step> QueuedEphemeralSteps { get; set; } = [];
|
||||||
|
|
||||||
public SimulationState FirstState => Macro.Count > 0 ? Macro[0].State : InitialState;
|
public SimulationState FirstState => Macro.Count > 0 ? Macro[0].State : InitialState;
|
||||||
public SimulationState State => Macro.Count > 0 ? Macro[^1].State : InitialState;
|
public SimulationState State => Macro.Count > 0 ? Macro[^1].State : InitialState;
|
||||||
@@ -158,7 +163,7 @@ internal sealed class SimulatedMacro
|
|||||||
|
|
||||||
public Reliablity GetReliability(RecipeData recipeData, Index? idx = null) =>
|
public Reliablity GetReliability(RecipeData recipeData, Index? idx = null) =>
|
||||||
Macro.Count > 0 ?
|
Macro.Count > 0 ?
|
||||||
Macro[idx ?? ^1].GetReliability(InitialState, Macro.Select(m => m.Action), recipeData) :
|
Macro[idx ?? ^1].GetReliability(InitialState, Actions.ToArray(), recipeData) :
|
||||||
new(InitialState, Array.Empty<ActionType>(), 0, recipeData);
|
new(InitialState, Array.Empty<ActionType>(), 0, recipeData);
|
||||||
|
|
||||||
private void TryRecalculateFrom(int index)
|
private void TryRecalculateFrom(int index)
|
||||||
@@ -213,15 +218,41 @@ internal sealed class SimulatedMacro
|
|||||||
TryRecalculateFrom(Math.Min(fromIdx, toIdx));
|
TryRecalculateFrom(Math.Min(fromIdx, toIdx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void RemoveEphemeral()
|
||||||
|
{
|
||||||
|
for (var i = Macro.Count - 1; i >= 0; --i)
|
||||||
|
{
|
||||||
|
if (Macro[i].IsEphemeral)
|
||||||
|
Macro.RemoveAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int Enqueue(ActionType action, int? maxSize = null)
|
public int Enqueue(ActionType action, int? maxSize = null)
|
||||||
{
|
{
|
||||||
lock (QueueLock)
|
lock (QueueLock)
|
||||||
{
|
{
|
||||||
if (maxSize is { } size && QueuedSteps.Count + Macro.Count >= size)
|
if (maxSize is { } size && QueuedSteps.Count + Macro.Count >= size)
|
||||||
return size;
|
return size;
|
||||||
|
|
||||||
|
QueuedEphemeralSteps.Clear();
|
||||||
QueuedSteps.Add(new(action));
|
QueuedSteps.Add(new(action));
|
||||||
return QueuedSteps.Count + Macro.Count;
|
return Macro.Count + QueuedSteps.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int EnqueueEphemeral(IEnumerable<ActionType> actions, int? maxSize = null)
|
||||||
|
{
|
||||||
|
lock (QueueLock)
|
||||||
|
{
|
||||||
|
QueuedEphemeralSteps.Clear();
|
||||||
|
foreach (var action in actions)
|
||||||
|
{
|
||||||
|
if (maxSize is { } size && QueuedSteps.Count + QueuedEphemeralSteps.Count + Macro.Count >= size)
|
||||||
|
return size;
|
||||||
|
|
||||||
|
QueuedEphemeralSteps.Add(new(action, true));
|
||||||
|
}
|
||||||
|
return Macro.Count + QueuedSteps.Count + QueuedEphemeralSteps.Count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,6 +261,7 @@ internal sealed class SimulatedMacro
|
|||||||
lock (QueueLock)
|
lock (QueueLock)
|
||||||
{
|
{
|
||||||
QueuedSteps.Clear();
|
QueuedSteps.Clear();
|
||||||
|
QueuedEphemeralSteps.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,11 +269,15 @@ internal sealed class SimulatedMacro
|
|||||||
{
|
{
|
||||||
lock (QueueLock)
|
lock (QueueLock)
|
||||||
{
|
{
|
||||||
if (QueuedSteps.Count > 0)
|
if (QueuedSteps.Count > 0 || QueuedEphemeralSteps.Count > 0)
|
||||||
{
|
{
|
||||||
|
RemoveEphemeral();
|
||||||
var startIdx = Macro.Count;
|
var startIdx = Macro.Count;
|
||||||
|
|
||||||
Macro.AddRange(QueuedSteps);
|
Macro.AddRange(QueuedSteps);
|
||||||
|
Macro.AddRange(QueuedEphemeralSteps);
|
||||||
QueuedSteps.Clear();
|
QueuedSteps.Clear();
|
||||||
|
QueuedEphemeralSteps.Clear();
|
||||||
TryRecalculateFrom(startIdx);
|
TryRecalculateFrom(startIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1182,7 +1182,7 @@ public sealed class MacroEditor : Window, IDisposable
|
|||||||
var actionBase = action.Base();
|
var actionBase = action.Base();
|
||||||
var failedAction = response != ActionResponse.UsedAction;
|
var failedAction = response != ActionResponse.UsedAction;
|
||||||
using var id = ImRaii.PushId(i);
|
using var id = ImRaii.PushId(i);
|
||||||
if (ImGui.ImageButton(action.GetIcon(RecipeData!.ClassJob).ImGuiHandle, new(imageSize), default, Vector2.One, 0, default, failedAction ? new(1, 1, 1, ImGui.GetStyle().DisabledAlpha) : Vector4.One))
|
if (ImGui.ImageButton(action.GetIcon(RecipeData!.ClassJob).ImGuiHandle, new(imageSize), default, Vector2.One, 0, default, failedAction ? new(1, 1, 1, ImGui.GetStyle().DisabledAlpha) : Vector4.One) && !SolverRunning)
|
||||||
RemoveStep(i);
|
RemoveStep(i);
|
||||||
if (response is ActionResponse.ActionNotUnlocked ||
|
if (response is ActionResponse.ActionNotUnlocked ||
|
||||||
(
|
(
|
||||||
@@ -1550,10 +1550,14 @@ public sealed class MacroEditor : Window, IDisposable
|
|||||||
|
|
||||||
var solver = new Solver.Solver(config, state) { Token = token };
|
var solver = new Solver.Solver(config, state) { Token = token };
|
||||||
solver.OnLog += Log.Debug;
|
solver.OnLog += Log.Debug;
|
||||||
|
solver.OnWarn += t => Service.Plugin.DisplaySolverWarning(t);
|
||||||
solver.OnNewAction += a => Macro.Enqueue(a);
|
solver.OnNewAction += a => Macro.Enqueue(a);
|
||||||
|
solver.OnSuggestSolution += a => Macro.EnqueueEphemeral(a.Actions);
|
||||||
SolverObject = solver;
|
SolverObject = solver;
|
||||||
solver.Start();
|
solver.Start();
|
||||||
_ = solver.GetTask().GetAwaiter().GetResult();
|
var t = solver.GetTask();
|
||||||
|
_ = t.ContinueWith(_ => Macro.RemoveEphemeral());
|
||||||
|
_ = t.GetAwaiter().GetResult();
|
||||||
|
|
||||||
token.ThrowIfCancellationRequested();
|
token.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
|||||||
@@ -844,7 +844,7 @@ public sealed unsafe class RecipeNote : Window, IDisposable
|
|||||||
{
|
{
|
||||||
var progressColors = Colors.GetSolverProgressColors(solver.ProgressStage);
|
var progressColors = Colors.GetSolverProgressColors(solver.ProgressStage);
|
||||||
ImGuiUtils.ArcProgress(
|
ImGuiUtils.ArcProgress(
|
||||||
fraction,
|
solver.IsIndeterminate ? (float)-ImGui.GetTime() : fraction,
|
||||||
windowHeight / 2f + 2,
|
windowHeight / 2f + 2,
|
||||||
.5f,
|
.5f,
|
||||||
ImGui.ColorConvertFloat4ToU32(progressColors.Background),
|
ImGui.ColorConvertFloat4ToU32(progressColors.Background),
|
||||||
@@ -1187,6 +1187,7 @@ public sealed unsafe class RecipeNote : Window, IDisposable
|
|||||||
|
|
||||||
var solver = new Solver.Solver(config, state) { Token = token };
|
var solver = new Solver.Solver(config, state) { Token = token };
|
||||||
solver.OnLog += Log.Debug;
|
solver.OnLog += Log.Debug;
|
||||||
|
solver.OnWarn += t => Service.Plugin.DisplaySolverWarning(t);
|
||||||
BestMacroSolver = solver;
|
BestMacroSolver = solver;
|
||||||
solver.Start();
|
solver.Start();
|
||||||
var solution = solver.GetTask().GetAwaiter().GetResult();
|
var solution = solver.GetTask().GetAwaiter().GetResult();
|
||||||
|
|||||||
+160
-121
@@ -149,6 +149,7 @@ public sealed class Settings : Window, IDisposable
|
|||||||
SolverAlgorithm.Stepwise => "Stepwise",
|
SolverAlgorithm.Stepwise => "Stepwise",
|
||||||
SolverAlgorithm.StepwiseForked => "Stepwise Forked",
|
SolverAlgorithm.StepwiseForked => "Stepwise Forked",
|
||||||
SolverAlgorithm.StepwiseGenetic => "Stepwise Genetic",
|
SolverAlgorithm.StepwiseGenetic => "Stepwise Genetic",
|
||||||
|
SolverAlgorithm.Raphael => "Optimal (Slow)",
|
||||||
_ => "Unknown",
|
_ => "Unknown",
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -160,9 +161,12 @@ public sealed class Settings : Window, IDisposable
|
|||||||
SolverAlgorithm.Stepwise => "Run through all iterations and pick the next best step, " +
|
SolverAlgorithm.Stepwise => "Run through all iterations and pick the next best step, " +
|
||||||
"and repeat using previous steps as a starting point",
|
"and repeat using previous steps as a starting point",
|
||||||
SolverAlgorithm.StepwiseForked => "Stepwise, but using multiple solvers simultaneously",
|
SolverAlgorithm.StepwiseForked => "Stepwise, but using multiple solvers simultaneously",
|
||||||
SolverAlgorithm.StepwiseGenetic => "Stepwise Forked, but the top N next best steps are " +
|
SolverAlgorithm.StepwiseGenetic => "Stepwise Forked, but the top N next best steps are " +
|
||||||
"selected from the solvers, and each one is equally " +
|
"selected from the solvers, and each one is equally " +
|
||||||
"used as a starting point",
|
"used as a starting point",
|
||||||
|
SolverAlgorithm.Raphael => "Finds the best solution, every time. This solver has " +
|
||||||
|
"very different options compared to the rest, as it " +
|
||||||
|
"is designed using an entirely different algorithm.",
|
||||||
_ => "Unknown"
|
_ => "Unknown"
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -527,118 +531,140 @@ public sealed class Settings : Window, IDisposable
|
|||||||
ref isDirty
|
ref isDirty
|
||||||
);
|
);
|
||||||
|
|
||||||
DrawOption(
|
if (config.Algorithm != SolverAlgorithm.Raphael)
|
||||||
"Target Iterations",
|
{
|
||||||
"The total number of iterations to run per crafting step. " +
|
|
||||||
"Higher values require more computational power. Higher values " +
|
|
||||||
"also may decrease variance, so other values should be tweaked " +
|
|
||||||
"as necessary to get a more favorable outcome.",
|
|
||||||
config.Iterations,
|
|
||||||
1000,
|
|
||||||
1000000,
|
|
||||||
v => config = config with { Iterations = v },
|
|
||||||
ref isDirty
|
|
||||||
);
|
|
||||||
|
|
||||||
DrawOption(
|
|
||||||
"Max Iterations",
|
|
||||||
"The solver may go about the target iteration value if the craft " +
|
|
||||||
"is sufficiently difficult, and it wasn't able to find any way to " +
|
|
||||||
"complete it yet. In rare cases, the solver might go on for a very " +
|
|
||||||
"long time. This maximum is here to prevent the solver from stealing " +
|
|
||||||
"all your RAM.",
|
|
||||||
config.MaxIterations,
|
|
||||||
config.Iterations,
|
|
||||||
5000000,
|
|
||||||
v => config = config with { MaxIterations = v },
|
|
||||||
ref isDirty
|
|
||||||
);
|
|
||||||
|
|
||||||
DrawOption(
|
|
||||||
"Max Step Count",
|
|
||||||
"The maximum number of crafting steps; this is generally the only " +
|
|
||||||
"setting you should change, and it should be set to around 5 steps " +
|
|
||||||
"more than what you'd expect. If this value is too low, the solver " +
|
|
||||||
"won't learn much per iteration; too high and it will waste time " +
|
|
||||||
"on useless extra steps.",
|
|
||||||
config.MaxStepCount,
|
|
||||||
1,
|
|
||||||
100,
|
|
||||||
v => config = config with { MaxStepCount = v },
|
|
||||||
ref isDirty
|
|
||||||
);
|
|
||||||
|
|
||||||
DrawOption(
|
|
||||||
"Exploration Constant",
|
|
||||||
"A constant that decides how often the solver will explore new, " +
|
|
||||||
"possibly good paths. If this value is too high, " +
|
|
||||||
"moves will mostly be decided at random.",
|
|
||||||
config.ExplorationConstant,
|
|
||||||
0,
|
|
||||||
10,
|
|
||||||
v => config = config with { ExplorationConstant = v },
|
|
||||||
ref isDirty
|
|
||||||
);
|
|
||||||
|
|
||||||
DrawOption(
|
|
||||||
"Score Weighting Constant",
|
|
||||||
"A constant ranging from 0 to 1 that configures how the solver " +
|
|
||||||
"scores and picks paths to travel to next. A value of 0 means " +
|
|
||||||
"actions will be chosen based on their average outcome, whereas " +
|
|
||||||
"1 uses their best outcome achieved so far.",
|
|
||||||
config.MaxScoreWeightingConstant,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
v => config = config with { MaxScoreWeightingConstant = v },
|
|
||||||
ref isDirty
|
|
||||||
);
|
|
||||||
|
|
||||||
using (var d = ImRaii.Disabled(config.Algorithm is not (SolverAlgorithm.OneshotForked or SolverAlgorithm.StepwiseForked or SolverAlgorithm.StepwiseGenetic)))
|
|
||||||
DrawOption(
|
DrawOption(
|
||||||
"Max Core Count",
|
"Target Iterations",
|
||||||
"The number of cores to use when solving. You should use as many " +
|
"The total number of iterations to run per crafting step. " +
|
||||||
"as you can. If it's too high, it will have an effect on your gameplay " +
|
"Higher values require more computational power. Higher values " +
|
||||||
$"experience. A good estimate would be 1 or 2 cores less than your " +
|
"also may decrease variance, so other values should be tweaked " +
|
||||||
$"system (FYI, you have {Environment.ProcessorCount} cores), but make sure to accomodate " +
|
"as necessary to get a more favorable outcome.",
|
||||||
$"for any other tasks you have in the background, if you have any.\n" +
|
config.Iterations,
|
||||||
"(Only used in the Forked and Genetic algorithms)",
|
1000,
|
||||||
config.MaxThreadCount,
|
1000000,
|
||||||
1,
|
v => config = config with { Iterations = v },
|
||||||
Environment.ProcessorCount,
|
|
||||||
v => config = config with { MaxThreadCount = v },
|
|
||||||
ref isDirty
|
ref isDirty
|
||||||
);
|
);
|
||||||
|
|
||||||
using (var d = ImRaii.Disabled(config.Algorithm is not (SolverAlgorithm.OneshotForked or SolverAlgorithm.StepwiseForked or SolverAlgorithm.StepwiseGenetic)))
|
|
||||||
DrawOption(
|
DrawOption(
|
||||||
"Fork Count",
|
"Max Iterations",
|
||||||
"Split the number of iterations across different solvers. In general, " +
|
"The solver may go about the target iteration value if the craft " +
|
||||||
"you should increase this value to at least the number of cores in " +
|
"is sufficiently difficult, and it wasn't able to find any way to " +
|
||||||
$"your system (FYI, you have {Environment.ProcessorCount} cores) to attain the most speedup. " +
|
"complete it yet. In rare cases, the solver might go on for a very " +
|
||||||
"The higher the number, the more chance you have of finding a " +
|
"long time. This maximum is here to prevent the solver from stealing " +
|
||||||
"better local maximum; this concept similar but not equivalent " +
|
"all your RAM.",
|
||||||
"to the exploration constant.\n" +
|
config.MaxIterations,
|
||||||
"(Only used in the Forked and Genetic algorithms)",
|
config.Iterations,
|
||||||
config.ForkCount,
|
5000000,
|
||||||
1,
|
v => config = config with { MaxIterations = v },
|
||||||
500,
|
|
||||||
v => config = config with { ForkCount = v },
|
|
||||||
ref isDirty
|
ref isDirty
|
||||||
);
|
);
|
||||||
|
|
||||||
using (var d = ImRaii.Disabled(config.Algorithm is not SolverAlgorithm.StepwiseGenetic))
|
|
||||||
DrawOption(
|
DrawOption(
|
||||||
"Elitist Action Count",
|
"Max Step Count",
|
||||||
"On every craft step, pick this many top solutions and use them as " +
|
"The maximum number of crafting steps; this is generally the only " +
|
||||||
"the input for the next craft step. For best results, use Fork Count / 2 " +
|
"setting you should change, and it should be set to around 5 steps " +
|
||||||
"and add about 1 or 2 more if needed.\n" +
|
"more than what you'd expect. If this value is too low, the solver " +
|
||||||
"(Only used in the Stepwise Genetic algorithm)",
|
"won't learn much per iteration; too high and it will waste time " +
|
||||||
config.FurcatedActionCount,
|
"on useless extra steps.",
|
||||||
|
config.MaxStepCount,
|
||||||
1,
|
1,
|
||||||
500,
|
100,
|
||||||
v => config = config with { FurcatedActionCount = v },
|
v => config = config with { MaxStepCount = v },
|
||||||
ref isDirty
|
ref isDirty
|
||||||
);
|
);
|
||||||
|
|
||||||
|
DrawOption(
|
||||||
|
"Exploration Constant",
|
||||||
|
"A constant that decides how often the solver will explore new, " +
|
||||||
|
"possibly good paths. If this value is too high, " +
|
||||||
|
"moves will mostly be decided at random.",
|
||||||
|
config.ExplorationConstant,
|
||||||
|
0,
|
||||||
|
10,
|
||||||
|
v => config = config with { ExplorationConstant = v },
|
||||||
|
ref isDirty
|
||||||
|
);
|
||||||
|
|
||||||
|
DrawOption(
|
||||||
|
"Score Weighting Constant",
|
||||||
|
"A constant ranging from 0 to 1 that configures how the solver " +
|
||||||
|
"scores and picks paths to travel to next. A value of 0 means " +
|
||||||
|
"actions will be chosen based on their average outcome, whereas " +
|
||||||
|
"1 uses their best outcome achieved so far.",
|
||||||
|
config.MaxScoreWeightingConstant,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
v => config = config with { MaxScoreWeightingConstant = v },
|
||||||
|
ref isDirty
|
||||||
|
);
|
||||||
|
|
||||||
|
using (ImRaii.Disabled(config.Algorithm is not (SolverAlgorithm.OneshotForked or SolverAlgorithm.StepwiseForked or SolverAlgorithm.StepwiseGenetic)))
|
||||||
|
DrawOption(
|
||||||
|
"Max Core Count",
|
||||||
|
"The number of cores to use when solving. You should use as many " +
|
||||||
|
"as you can. If it's too high, it will have an effect on your gameplay " +
|
||||||
|
$"experience. A good estimate would be 1 or 2 cores less than your " +
|
||||||
|
$"system (FYI, you have {Environment.ProcessorCount} cores), but make sure to accomodate " +
|
||||||
|
$"for any other tasks you have in the background, if you have any.\n" +
|
||||||
|
"(Only used in the Forked and Genetic algorithms)",
|
||||||
|
config.MaxThreadCount,
|
||||||
|
1,
|
||||||
|
Environment.ProcessorCount,
|
||||||
|
v => config = config with { MaxThreadCount = v },
|
||||||
|
ref isDirty
|
||||||
|
);
|
||||||
|
|
||||||
|
using (ImRaii.Disabled(config.Algorithm is not (SolverAlgorithm.OneshotForked or SolverAlgorithm.StepwiseForked or SolverAlgorithm.StepwiseGenetic)))
|
||||||
|
DrawOption(
|
||||||
|
"Fork Count",
|
||||||
|
"Split the number of iterations across different solvers. In general, " +
|
||||||
|
"you should increase this value to at least the number of cores in " +
|
||||||
|
$"your system (FYI, you have {Environment.ProcessorCount} cores) to attain the most speedup. " +
|
||||||
|
"The higher the number, the more chance you have of finding a " +
|
||||||
|
"better local maximum; this concept similar but not equivalent " +
|
||||||
|
"to the exploration constant.\n" +
|
||||||
|
"(Only used in the Forked and Genetic algorithms)",
|
||||||
|
config.ForkCount,
|
||||||
|
1,
|
||||||
|
500,
|
||||||
|
v => config = config with { ForkCount = v },
|
||||||
|
ref isDirty
|
||||||
|
);
|
||||||
|
|
||||||
|
using (ImRaii.Disabled(config.Algorithm is not SolverAlgorithm.StepwiseGenetic))
|
||||||
|
DrawOption(
|
||||||
|
"Elitist Action Count",
|
||||||
|
"On every craft step, pick this many top solutions and use them as " +
|
||||||
|
"the input for the next craft step. For best results, use Fork Count / 2 " +
|
||||||
|
"and add about 1 or 2 more if needed.\n" +
|
||||||
|
"(Only used in the Stepwise Genetic algorithm)",
|
||||||
|
config.FurcatedActionCount,
|
||||||
|
1,
|
||||||
|
500,
|
||||||
|
v => config = config with { FurcatedActionCount = v },
|
||||||
|
ref isDirty
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DrawOption(
|
||||||
|
"Ensure 100% Reliability",
|
||||||
|
"Find a rotation that can reach the target quality no matter " +
|
||||||
|
"how unlucky the random conditions are.",
|
||||||
|
config.Adversarial,
|
||||||
|
v => config = config with { Adversarial = v },
|
||||||
|
ref isDirty
|
||||||
|
);
|
||||||
|
DrawOption(
|
||||||
|
"Backload Progress",
|
||||||
|
"Find a rotation that only uses Progress-increasing actions " +
|
||||||
|
"at the end of the rotation. May speed up solve times.",
|
||||||
|
config.BackloadProgress,
|
||||||
|
v => config = config with { BackloadProgress = v },
|
||||||
|
ref isDirty
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var panel = ImRaii2.GroupPanel("Action Pool", -1, out var poolWidth))
|
using (var panel = ImRaii2.GroupPanel("Action Pool", -1, out var poolWidth))
|
||||||
@@ -658,27 +684,40 @@ public sealed class Settings : Window, IDisposable
|
|||||||
|
|
||||||
using (var panel = ImRaii2.GroupPanel("Advanced", -1, out _))
|
using (var panel = ImRaii2.GroupPanel("Advanced", -1, out _))
|
||||||
{
|
{
|
||||||
DrawOption(
|
if (config.Algorithm != SolverAlgorithm.Raphael)
|
||||||
"Max Rollout Step Count",
|
{
|
||||||
"The maximum number of crafting steps every iteration can consider. " +
|
DrawOption(
|
||||||
"Decreasing this value can have unintended side effects. Only change " +
|
"Max Rollout Step Count",
|
||||||
"this value if you absolutely know what you're doing.",
|
"The maximum number of crafting steps every iteration can consider. " +
|
||||||
config.MaxRolloutStepCount,
|
"Decreasing this value can have unintended side effects. Only change " +
|
||||||
1,
|
"this value if you absolutely know what you're doing.",
|
||||||
50,
|
config.MaxRolloutStepCount,
|
||||||
v => config = config with { MaxRolloutStepCount = v },
|
1,
|
||||||
ref isDirty
|
50,
|
||||||
);
|
v => config = config with { MaxRolloutStepCount = v },
|
||||||
|
ref isDirty
|
||||||
|
);
|
||||||
|
|
||||||
DrawOption(
|
DrawOption(
|
||||||
"Strict Actions",
|
"Strict Actions",
|
||||||
"When finding the next possible actions to execute, use a heuristic " +
|
"When finding the next possible actions to execute, use a heuristic " +
|
||||||
"to restrict which actions to attempt taking. This results in a much " +
|
"to restrict which actions to attempt taking. This results in a much " +
|
||||||
"better macro at the cost of not finding an extremely creative one.",
|
"better macro at the cost of not finding an extremely creative one.",
|
||||||
config.StrictActions,
|
config.StrictActions,
|
||||||
v => config = config with { StrictActions = v },
|
v => config = config with { StrictActions = v },
|
||||||
ref isDirty
|
ref isDirty
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DrawOption(
|
||||||
|
"Unsound Branch Pruning",
|
||||||
|
"TBD",
|
||||||
|
config.UnsoundBranchPruning,
|
||||||
|
v => config = config with { UnsoundBranchPruning = v },
|
||||||
|
ref isDirty
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var panel = ImRaii2.GroupPanel("Score Weights (Advanced)", -1, out _))
|
using (var panel = ImRaii2.GroupPanel("Score Weights (Advanced)", -1, out _))
|
||||||
|
|||||||
@@ -611,6 +611,7 @@ public sealed unsafe class SynthHelper : Window, IDisposable
|
|||||||
|
|
||||||
var solver = new Solver.Solver(config, state) { Token = token };
|
var solver = new Solver.Solver(config, state) { Token = token };
|
||||||
solver.OnLog += Log.Debug;
|
solver.OnLog += Log.Debug;
|
||||||
|
solver.OnWarn += t => Service.Plugin.DisplaySolverWarning(t);
|
||||||
solver.OnNewAction += EnqueueAction;
|
solver.OnNewAction += EnqueueAction;
|
||||||
SolverObject = solver;
|
SolverObject = solver;
|
||||||
solver.Start();
|
solver.Start();
|
||||||
|
|||||||
@@ -28,6 +28,11 @@
|
|||||||
"System.IO.Hashing": "8.0.0"
|
"System.IO.Hashing": "8.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Raphael.Net": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "1.0.0",
|
||||||
|
"contentHash": "J/D1pw2MT52hENysYs7SA++PBT4sHwUcPnTzjb9/lLigNJazob4v7WbBe2enKpfDAI6hO8al7p2Qlt2258fk8g=="
|
||||||
|
},
|
||||||
"System.IO.Hashing": {
|
"System.IO.Hashing": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "8.0.0",
|
"resolved": "8.0.0",
|
||||||
@@ -40,9 +45,17 @@
|
|||||||
"type": "Project",
|
"type": "Project",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Craftimizer.Simulator": "[1.0.0, )",
|
"Craftimizer.Simulator": "[1.0.0, )",
|
||||||
"DotNext": "[5.14.0, )"
|
"DotNext": "[5.14.0, )",
|
||||||
|
"Raphael.Net": "[1.0.0, )"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"net8.0-windows7.0/win-x64": {
|
||||||
|
"Raphael.Net": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "1.0.0",
|
||||||
|
"contentHash": "J/D1pw2MT52hENysYs7SA++PBT4sHwUcPnTzjb9/lLigNJazob4v7WbBe2enKpfDAI6hO8al7p2Qlt2258fk8g=="
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user