Replace ActionHistory with persistent ActionStatuses
This commit is contained in:
@@ -122,16 +122,17 @@ public class SimulatorWindow : Window
|
|||||||
}
|
}
|
||||||
ImGuiHelpers.ScaledDummy(5);
|
ImGuiHelpers.ScaledDummy(5);
|
||||||
{
|
{
|
||||||
var i = 0;
|
ImGui.Text("TODO: Action History");
|
||||||
foreach (var action in State.ActionHistory)
|
//var i = 0;
|
||||||
{
|
//foreach (var action in State.ActionHistory)
|
||||||
var baseAction = action.With(Simulation);
|
//{
|
||||||
ImGui.Image(action.GetIcon(ClassJob.Carpenter).ImGuiHandle, new Vector2(ImGui.GetFontSize() * 2f));
|
// var baseAction = action.With(Simulation);
|
||||||
if (ImGui.IsItemHovered())
|
// ImGui.Image(action.GetIcon(ClassJob.Carpenter).ImGuiHandle, new Vector2(ImGui.GetFontSize() * 2f));
|
||||||
ImGui.SetTooltip($"{action.GetName(ClassJob.Carpenter)}\n{baseAction.GetTooltip(false)}");
|
// if (ImGui.IsItemHovered())
|
||||||
if (++i % 5 != 0)
|
// ImGui.SetTooltip($"{action.GetName(ClassJob.Carpenter)}\n{baseAction.GetTooltip(false)}");
|
||||||
ImGui.SameLine();
|
// if (++i % 5 != 0)
|
||||||
}
|
// ImGui.SameLine();
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
ImGui.EndChild();
|
ImGui.EndChild();
|
||||||
ImGui.EndTable();
|
ImGui.EndTable();
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using Craftimizer.Simulator.Actions;
|
||||||
|
|
||||||
|
namespace Craftimizer.Simulator;
|
||||||
|
|
||||||
|
public record struct ActionStates
|
||||||
|
{
|
||||||
|
public byte TouchComboIdx { get; set; }
|
||||||
|
public byte CarefulObservationCount { get; set; }
|
||||||
|
public bool UsedHeartAndSoul { get; set; }
|
||||||
|
public bool Observed { get; set; }
|
||||||
|
|
||||||
|
public void MutateState(ActionType action)
|
||||||
|
{
|
||||||
|
if (action == ActionType.BasicTouch)
|
||||||
|
TouchComboIdx = 1;
|
||||||
|
else if (TouchComboIdx == 1 && action == ActionType.StandardTouch)
|
||||||
|
TouchComboIdx = 2;
|
||||||
|
else
|
||||||
|
TouchComboIdx = 0;
|
||||||
|
|
||||||
|
if (action == ActionType.CarefulObservation)
|
||||||
|
CarefulObservationCount++;
|
||||||
|
|
||||||
|
if (action == ActionType.HeartAndSoul)
|
||||||
|
UsedHeartAndSoul = true;
|
||||||
|
|
||||||
|
Observed = action == ActionType.Observe;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ internal sealed class AdvancedTouch : BaseAction
|
|||||||
public override int Level => 84;
|
public override int Level => 84;
|
||||||
public override uint ActionId => 100411;
|
public override uint ActionId => 100411;
|
||||||
|
|
||||||
public override int CPCost => Simulation.IsPreviousAction(ActionType.StandardTouch) && Simulation.IsPreviousAction(ActionType.BasicTouch, 2) ? 18 : 46;
|
public override int CPCost => Simulation.ActionStates.TouchComboIdx == 2 ? 18 : 46;
|
||||||
public override float Efficiency => 1.50f;
|
public override float Efficiency => 1.50f;
|
||||||
public override bool IncreasesQuality => true;
|
public override bool IncreasesQuality => true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ internal sealed class CarefulObservation : BaseAction
|
|||||||
public override int DurabilityCost => 0;
|
public override int DurabilityCost => 0;
|
||||||
public override bool IncreasesStepCount => false;
|
public override bool IncreasesStepCount => false;
|
||||||
|
|
||||||
public override bool CanUse => Simulation.Input.Stats.IsSpecialist && Simulation.CountPreviousAction(ActionType.CarefulObservation) < 3;
|
public override bool CanUse => Simulation.Input.Stats.IsSpecialist && Simulation.ActionStates.CarefulObservationCount < 3;
|
||||||
|
|
||||||
public override void UseSuccess() =>
|
public override void UseSuccess() =>
|
||||||
Simulation.StepCondition();
|
Simulation.StepCondition();
|
||||||
|
|||||||
@@ -9,5 +9,5 @@ internal sealed class FocusedSynthesis : BaseAction
|
|||||||
public override int CPCost => 5;
|
public override int CPCost => 5;
|
||||||
public override float Efficiency => 2.00f;
|
public override float Efficiency => 2.00f;
|
||||||
public override bool IncreasesProgress => true;
|
public override bool IncreasesProgress => true;
|
||||||
public override float SuccessRate => Simulation.IsPreviousAction(ActionType.Observe) ? 1.00f : 0.50f;
|
public override float SuccessRate => Simulation.ActionStates.Observed ? 1.00f : 0.50f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,5 +9,5 @@ internal sealed class FocusedTouch : BaseAction
|
|||||||
public override int CPCost => 18;
|
public override int CPCost => 18;
|
||||||
public override float Efficiency => 1.50f;
|
public override float Efficiency => 1.50f;
|
||||||
public override bool IncreasesQuality => true;
|
public override bool IncreasesQuality => true;
|
||||||
public override float SuccessRate => Simulation.IsPreviousAction(ActionType.Observe) ? 1.00f : 0.50f;
|
public override float SuccessRate => Simulation.ActionStates.Observed ? 1.00f : 0.50f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,5 +11,5 @@ internal sealed class HeartAndSoul : BaseBuffAction
|
|||||||
|
|
||||||
public override EffectType Effect => EffectType.HeartAndSoul;
|
public override EffectType Effect => EffectType.HeartAndSoul;
|
||||||
|
|
||||||
public override bool CanUse => Simulation.Input.Stats.IsSpecialist && Simulation.CountPreviousAction(ActionType.HeartAndSoul) == 0;
|
public override bool CanUse => Simulation.Input.Stats.IsSpecialist && !Simulation.ActionStates.UsedHeartAndSoul;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ internal sealed class StandardTouch : BaseAction
|
|||||||
public override int Level => 18;
|
public override int Level => 18;
|
||||||
public override uint ActionId => 100004;
|
public override uint ActionId => 100004;
|
||||||
|
|
||||||
public override int CPCost => Simulation.IsPreviousAction(ActionType.BasicTouch) ? 18 : 32;
|
public override int CPCost => Simulation.ActionStates.TouchComboIdx == 1 ? 18 : 32;
|
||||||
public override float Efficiency => 1.25f;
|
public override float Efficiency => 1.25f;
|
||||||
public override bool IncreasesQuality => true;
|
public override bool IncreasesQuality => true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ public readonly record struct SimulationState
|
|||||||
{
|
{
|
||||||
public SimulationInput Input { get; init; }
|
public SimulationInput Input { get; init; }
|
||||||
|
|
||||||
public int ActionCount => ActionHistory.Count;
|
public int ActionCount { get; init; }
|
||||||
|
|
||||||
public int StepCount { get; init; }
|
public int StepCount { get; init; }
|
||||||
public int Progress { get; init; }
|
public int Progress { get; init; }
|
||||||
public int Quality { get; init; }
|
public int Quality { get; init; }
|
||||||
@@ -15,7 +14,7 @@ public readonly record struct SimulationState
|
|||||||
public int CP { get; init; }
|
public int CP { get; init; }
|
||||||
public Condition Condition { get; init; }
|
public Condition Condition { get; init; }
|
||||||
public Effects ActiveEffects { get; init; }
|
public Effects ActiveEffects { get; init; }
|
||||||
public List<ActionType> ActionHistory { get; init; }
|
public ActionStates ActionStates { get; init; }
|
||||||
|
|
||||||
// https://github.com/ffxiv-teamcraft/simulator/blob/0682dfa76043ff4ccb38832c184d046ceaff0733/src/model/tables.ts#L2
|
// https://github.com/ffxiv-teamcraft/simulator/blob/0682dfa76043ff4ccb38832c184d046ceaff0733/src/model/tables.ts#L2
|
||||||
private static readonly int[] HQPercentTable = {
|
private static readonly int[] HQPercentTable = {
|
||||||
@@ -39,6 +38,7 @@ public readonly record struct SimulationState
|
|||||||
CP = Input.Stats.CP;
|
CP = Input.Stats.CP;
|
||||||
Condition = Condition.Normal;
|
Condition = Condition.Normal;
|
||||||
ActiveEffects = new();
|
ActiveEffects = new();
|
||||||
ActionHistory = new();
|
ActionCount = 0;
|
||||||
|
ActionStates = new();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-10
@@ -5,6 +5,7 @@ namespace Craftimizer.Simulator;
|
|||||||
public class Simulator
|
public class Simulator
|
||||||
{
|
{
|
||||||
public SimulationInput Input { get; private set; }
|
public SimulationInput Input { get; private set; }
|
||||||
|
public int ActionCount { get; private set; }
|
||||||
public int StepCount { get; private set; }
|
public int StepCount { get; private set; }
|
||||||
public int Progress { get; private set; }
|
public int Progress { get; private set; }
|
||||||
public int Quality { get; private set; }
|
public int Quality { get; private set; }
|
||||||
@@ -12,7 +13,7 @@ public class Simulator
|
|||||||
public int CP { get; private set; }
|
public int CP { get; private set; }
|
||||||
public Condition Condition { get; private set; }
|
public Condition Condition { get; private set; }
|
||||||
public Effects ActiveEffects;
|
public Effects ActiveEffects;
|
||||||
public List<ActionType> ActionHistory { get; private set; }
|
public ActionStates ActionStates;
|
||||||
|
|
||||||
public bool IsFirstStep => StepCount == 0;
|
public bool IsFirstStep => StepCount == 0;
|
||||||
|
|
||||||
@@ -41,6 +42,7 @@ public class Simulator
|
|||||||
private void Emplace(SimulationState state)
|
private void Emplace(SimulationState state)
|
||||||
{
|
{
|
||||||
Input = state.Input;
|
Input = state.Input;
|
||||||
|
ActionCount = state.ActionCount;
|
||||||
StepCount = state.StepCount;
|
StepCount = state.StepCount;
|
||||||
Progress = state.Progress;
|
Progress = state.Progress;
|
||||||
Quality = state.Quality;
|
Quality = state.Quality;
|
||||||
@@ -48,12 +50,13 @@ public class Simulator
|
|||||||
CP = state.CP;
|
CP = state.CP;
|
||||||
Condition = state.Condition;
|
Condition = state.Condition;
|
||||||
ActiveEffects = state.ActiveEffects;
|
ActiveEffects = state.ActiveEffects;
|
||||||
ActionHistory = new(state.ActionHistory);
|
ActionStates = state.ActionStates;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SimulationState Displace() => new()
|
private SimulationState Displace() => new()
|
||||||
{
|
{
|
||||||
Input = Input,
|
Input = Input,
|
||||||
|
ActionCount = ActionCount,
|
||||||
StepCount = StepCount,
|
StepCount = StepCount,
|
||||||
Progress = Progress,
|
Progress = Progress,
|
||||||
Quality = Quality,
|
Quality = Quality,
|
||||||
@@ -61,7 +64,7 @@ public class Simulator
|
|||||||
CP = CP,
|
CP = CP,
|
||||||
Condition = Condition,
|
Condition = Condition,
|
||||||
ActiveEffects = ActiveEffects,
|
ActiveEffects = ActiveEffects,
|
||||||
ActionHistory = ActionHistory!,
|
ActionStates = ActionStates,
|
||||||
};
|
};
|
||||||
|
|
||||||
public (ActionResponse Response, SimulationState NewState) Execute(SimulationState state, ActionType action)
|
public (ActionResponse Response, SimulationState NewState) Execute(SimulationState state, ActionType action)
|
||||||
@@ -86,7 +89,8 @@ public class Simulator
|
|||||||
}
|
}
|
||||||
|
|
||||||
baseAction.Use();
|
baseAction.Use();
|
||||||
ActionHistory!.Add(action);
|
ActionStates.MutateState(action);
|
||||||
|
ActionCount++;
|
||||||
|
|
||||||
ActiveEffects.DecrementDuration();
|
ActiveEffects.DecrementDuration();
|
||||||
|
|
||||||
@@ -119,12 +123,6 @@ public class Simulator
|
|||||||
public bool HasEffect(EffectType effect) =>
|
public bool HasEffect(EffectType effect) =>
|
||||||
ActiveEffects.HasEffect(effect);
|
ActiveEffects.HasEffect(effect);
|
||||||
|
|
||||||
public bool IsPreviousAction(ActionType action, int stepsBack = 1) =>
|
|
||||||
ActionHistory!.Count >= stepsBack && ActionHistory[^stepsBack] == action;
|
|
||||||
|
|
||||||
public int CountPreviousAction(ActionType action) =>
|
|
||||||
ActionHistory!.Count(a => a == action);
|
|
||||||
|
|
||||||
public virtual bool RollSuccessRaw(float successRate) =>
|
public virtual bool RollSuccessRaw(float successRate) =>
|
||||||
successRate >= Input.Random.NextSingle();
|
successRate >= Input.Random.NextSingle();
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace Craftimizer.Solver.Crafty;
|
|||||||
public class Simulator : Sim
|
public class Simulator : Sim
|
||||||
{
|
{
|
||||||
public new CompletionState CompletionState =>
|
public new CompletionState CompletionState =>
|
||||||
(ActionHistory.Count + 1) >= Solver.MaxStepCount ?
|
(ActionCount + 1) >= Solver.MaxStepCount ?
|
||||||
CompletionState.MaxActionCountReached :
|
CompletionState.MaxActionCountReached :
|
||||||
(CompletionState)base.CompletionState;
|
(CompletionState)base.CompletionState;
|
||||||
public override bool IsComplete => CompletionState != CompletionState.Incomplete;
|
public override bool IsComplete => CompletionState != CompletionState.Incomplete;
|
||||||
@@ -65,7 +65,7 @@ public class Simulator : Sim
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (action == ActionType.Observe &&
|
if (action == ActionType.Observe &&
|
||||||
IsPreviousAction(ActionType.Observe))
|
ActionStates.Observed)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (action == ActionType.FinalAppraisal)
|
if (action == ActionType.FinalAppraisal)
|
||||||
@@ -78,7 +78,7 @@ public class Simulator : Sim
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
// only allow Focused moves after Observe
|
// only allow Focused moves after Observe
|
||||||
if (IsPreviousAction(ActionType.Observe) &&
|
if (ActionStates.Observed &&
|
||||||
action != ActionType.FocusedSynthesis &&
|
action != ActionType.FocusedSynthesis &&
|
||||||
action != ActionType.FocusedTouch)
|
action != ActionType.FocusedTouch)
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -242,12 +242,13 @@ public class Solver
|
|||||||
|
|
||||||
// playout to a terminal state
|
// playout to a terminal state
|
||||||
var currentState = Tree.Get(expandedIndex).State;
|
var currentState = Tree.Get(expandedIndex).State;
|
||||||
var preCount = currentState.State.ActionCount;
|
var actions = new List<ActionType>();
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (currentState.IsComplete)
|
if (currentState.IsComplete)
|
||||||
break;
|
break;
|
||||||
randomAction = currentState.AvailableActions.ElementAt(0);
|
randomAction = currentState.AvailableActions.ElementAt(0);
|
||||||
|
actions.Add(randomAction);
|
||||||
currentState = Execute(currentState.State, randomAction, true);
|
currentState = Execute(currentState.State, randomAction, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,7 +258,7 @@ public class Solver
|
|||||||
{
|
{
|
||||||
if (score >= ScoreStorageThreshold && score >= Tree.Get(0).State.Scores.MaxScore)
|
if (score >= ScoreStorageThreshold && score >= Tree.Get(0).State.Scores.MaxScore)
|
||||||
{
|
{
|
||||||
(var terminalIndex, _) = ExecuteActions(expandedIndex, currentState.State.ActionHistory.Skip(preCount).ToList(), true);
|
(var terminalIndex, _) = ExecuteActions(expandedIndex, actions, true);
|
||||||
return (terminalIndex, currentState.CompletionState, score);
|
return (terminalIndex, currentState.CompletionState, score);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -298,14 +299,13 @@ public class Solver
|
|||||||
{
|
{
|
||||||
var actions = new List<ActionType>();
|
var actions = new List<ActionType>();
|
||||||
var node = Tree.Get(0);
|
var node = Tree.Get(0);
|
||||||
while (node.Children.Count != 0) {
|
while (node.Children.Count != 0)
|
||||||
|
{
|
||||||
var next_index = RustMaxBy(node.Children, n => Tree.Get(n).State.Scores.MaxScore);
|
var next_index = RustMaxBy(node.Children, n => Tree.Get(n).State.Scores.MaxScore);
|
||||||
node = Tree.Get(next_index);
|
node = Tree.Get(next_index);
|
||||||
if (node.State.Action != null)
|
if (node.State.Action != null)
|
||||||
{
|
|
||||||
actions.Add(node.State.Action.Value);
|
actions.Add(node.State.Action.Value);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return (actions, node.State);
|
return (actions, node.State);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user