Replace ActionHistory with persistent ActionStatuses

This commit is contained in:
Asriel Camora
2023-06-20 22:37:59 -07:00
parent cdd4f5923e
commit 47c9339d56
12 changed files with 66 additions and 38 deletions
+11 -10
View File
@@ -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();
+29
View File
@@ -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;
}
}
+1 -1
View File
@@ -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;
} }
+1 -1
View File
@@ -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();
+1 -1
View File
@@ -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;
} }
+1 -1
View File
@@ -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;
} }
+1 -1
View File
@@ -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;
} }
+1 -1
View File
@@ -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;
} }
+4 -4
View File
@@ -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
View File
@@ -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();
+3 -3
View File
@@ -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;
+5 -5
View File
@@ -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,13 +299,12 @@ 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);