From bae48844b50401f334187e626572e3cdc7c352d2 Mon Sep 17 00:00:00 2001 From: Asriel Camora Date: Sun, 18 Jun 2023 03:50:48 -0700 Subject: [PATCH] fix to be identical to crafty, remove debugs --- Benchmark/Program.cs | 10 ++- Craftimizer/SimulatorUtils.cs | 24 +++--- Craftimizer/SimulatorWindow.cs | 8 +- Simulator/Actions/BaseAction.cs | 13 ++-- Simulator/Actions/BaseBuffAction.cs | 7 +- Simulator/Actions/ByregotsBlessing.cs | 2 +- Simulator/Actions/FinalAppraisal.cs | 3 +- Simulator/Actions/GreatStrides.cs | 3 +- Simulator/Actions/Groundwork.cs | 3 +- Simulator/Actions/HeartAndSoul.cs | 2 +- Simulator/Actions/Innovation.cs | 3 +- Simulator/Actions/Manipulation.cs | 16 +++- Simulator/Actions/TrainedFinesse.cs | 2 +- Simulator/Actions/Veneration.cs | 3 +- Simulator/Actions/WasteNot.cs | 3 +- Simulator/Actions/WasteNot2.cs | 3 +- Simulator/Effect.cs | 14 ---- Simulator/Effects.cs | 102 ++++++++++++++++++++++++++ Simulator/SimulationState.cs | 4 +- Simulator/Simulator.cs | 66 +++++------------ Solver/Crafty/SimulationNode.cs | 2 - Solver/Crafty/Simulator.cs | 14 +++- Solver/Crafty/Solver.cs | 44 +---------- 23 files changed, 203 insertions(+), 148 deletions(-) delete mode 100644 Simulator/Effect.cs create mode 100644 Simulator/Effects.cs diff --git a/Benchmark/Program.cs b/Benchmark/Program.cs index 9878759..d91a17c 100644 --- a/Benchmark/Program.cs +++ b/Benchmark/Program.cs @@ -27,6 +27,14 @@ internal class Program }; var actions = new List(); - (actions, _) = Solver.Crafty.Solver.SearchStepwise(input, actions, a => Console.WriteLine(a)); + if (true) + (actions, _) = Solver.Crafty.Solver.SearchStepwise(input, actions, a => Console.WriteLine(a)); + else + { + (actions, _) = Solver.Crafty.Solver.SearchOneshot(input, actions); + foreach (var action in actions) + Console.Write($">{action.IntName()}"); + Console.WriteLine(); + } } } diff --git a/Craftimizer/SimulatorUtils.cs b/Craftimizer/SimulatorUtils.cs index 1bb09c2..2d474d3 100644 --- a/Craftimizer/SimulatorUtils.cs +++ b/Craftimizer/SimulatorUtils.cs @@ -138,27 +138,27 @@ internal static class EffectExtensions public static Status Status(this EffectType me) => LuminaSheets.StatusSheet.GetRow(me.StatusId())!; - public static ushort GetIconId(this Effect me) + public static ushort GetIconId(this EffectType me, int strength) { - var status = me.Type.Status(); + var status = me.Status(); uint iconId = status.Icon; - if (status.MaxStacks != 0 && me.Strength != null) - iconId += (uint)Math.Clamp(me.Strength!.Value, 1, status.MaxStacks) - 1; + if (status.MaxStacks != 0) + iconId += (uint)Math.Clamp(strength, 1, status.MaxStacks) - 1; return (ushort)iconId; } - public static TextureWrap GetIcon(this Effect me) => - Icons.GetIconFromId(me.GetIconId()); + public static TextureWrap GetIcon(this EffectType me, int strength) => + Icons.GetIconFromId(me.GetIconId(strength)); - public static string GetTooltip(this Effect me) + public static string GetTooltip(this EffectType me, int strength, int duration) { - var status = me.Type.Status(); + var status = me.Status(); var name = new StringBuilder(); name.Append(status.Name.ToDalamudString().TextValue); - if (status.MaxStacks != 0 && me.Strength != null) - name.Append($" {me.Strength}"); - if (!status.IsPermanent && me.Duration != null) - name.Append($" > {me.Duration}"); + if (status.MaxStacks != 0) + name.Append($" {strength}"); + if (!status.IsPermanent) + name.Append($" > {duration}"); return name.ToString(); } } diff --git a/Craftimizer/SimulatorWindow.cs b/Craftimizer/SimulatorWindow.cs index cf42356..753b8ed 100644 --- a/Craftimizer/SimulatorWindow.cs +++ b/Craftimizer/SimulatorWindow.cs @@ -109,14 +109,16 @@ public class SimulatorWindow : Window ImGui.PopStyleColor(); ImGuiHelpers.ScaledDummy(5); ImGui.Text($"Effects:"); - foreach (var effect in State.ActiveEffects) + foreach (var effect in Enum.GetValues()) { - var icon = effect.GetIcon(); + var strength = Simulation.GetEffectStrength(effect); + var duration = Simulation.GetEffectDuration(effect); + var icon = effect.GetIcon(strength); var h = ImGui.GetFontSize() * 1.25f; var w = icon.Width * h / icon.Height; ImGui.Image(icon.ImGuiHandle, new Vector2(w, h)); ImGui.SameLine(); - ImGui.Text(effect.GetTooltip()); + ImGui.Text(effect.GetTooltip(strength, duration)); } ImGuiHelpers.ScaledDummy(5); { diff --git a/Simulator/Actions/BaseAction.cs b/Simulator/Actions/BaseAction.cs index 8e01da3..c86c44f 100644 --- a/Simulator/Actions/BaseAction.cs +++ b/Simulator/Actions/BaseAction.cs @@ -32,14 +32,17 @@ public abstract class BaseAction public virtual void Use() { + if (Simulation.RollSuccess(SuccessRate)) + UseSuccess(); + Simulation.ReduceCP(CPCost); Simulation.ReduceDurability(DurabilityCost); - if (Simulation.HasEffect(EffectType.Manipulation)) - Simulation.RestoreDurability(5); - - if (Simulation.RollSuccess(SuccessRate)) - UseSuccess(); + if (Simulation.Durability > 0) + { + if (Simulation.HasEffect(EffectType.Manipulation)) + Simulation.RestoreDurability(5); + } if (IncreasesStepCount) Simulation.IncreaseStepCount(); diff --git a/Simulator/Actions/BaseBuffAction.cs b/Simulator/Actions/BaseBuffAction.cs index 5bc7de4..3af3414 100644 --- a/Simulator/Actions/BaseBuffAction.cs +++ b/Simulator/Actions/BaseBuffAction.cs @@ -4,7 +4,8 @@ namespace Craftimizer.Simulator.Actions; internal abstract class BaseBuffAction : BaseAction { - public abstract Effect Effect { get; } + public abstract EffectType Effect { get; } + public virtual byte Duration => 1; public virtual EffectType[] ConflictingEffects => Array.Empty(); public override int DurabilityCost => 0; @@ -14,13 +15,13 @@ internal abstract class BaseBuffAction : BaseAction if (ConflictingEffects.Length != 0) foreach(var effect in ConflictingEffects) Simulation.RemoveEffect(effect); - Simulation.AddEffect(Effect.Type, Effect.Duration, Effect.Strength); + Simulation.AddEffect(Effect, Duration); } public override string GetTooltip(bool addUsability) { var builder = new StringBuilder(base.GetTooltip(addUsability)); - builder.AppendLine($"{Effect.Duration} Steps"); + builder.AppendLine($"{Duration} Steps"); return builder.ToString(); } } diff --git a/Simulator/Actions/ByregotsBlessing.cs b/Simulator/Actions/ByregotsBlessing.cs index d82cc25..86f40dc 100644 --- a/Simulator/Actions/ByregotsBlessing.cs +++ b/Simulator/Actions/ByregotsBlessing.cs @@ -7,7 +7,7 @@ internal class ByregotsBlessing : BaseAction public override uint ActionId => 100339; public override int CPCost => 24; - public override float Efficiency => 1.00f + (0.20f * (Simulation.GetEffect(EffectType.InnerQuiet)?.Strength ?? 0)); + public override float Efficiency => 1.00f + (0.20f * Simulation.GetEffectStrength(EffectType.InnerQuiet)); public override bool IncreasesQuality => true; public override bool CanUse => Simulation.HasEffect(EffectType.InnerQuiet) && base.CanUse; diff --git a/Simulator/Actions/FinalAppraisal.cs b/Simulator/Actions/FinalAppraisal.cs index 3314357..e792d97 100644 --- a/Simulator/Actions/FinalAppraisal.cs +++ b/Simulator/Actions/FinalAppraisal.cs @@ -9,5 +9,6 @@ internal class FinalAppraisal : BaseBuffAction public override int CPCost => 1; public override bool IncreasesStepCount => false; - public override Effect Effect => new() { Type = EffectType.FinalAppraisal, Duration = 5 }; + public override EffectType Effect => EffectType.FinalAppraisal; + public override byte Duration => 5; } diff --git a/Simulator/Actions/GreatStrides.cs b/Simulator/Actions/GreatStrides.cs index f2eb7f5..202d949 100644 --- a/Simulator/Actions/GreatStrides.cs +++ b/Simulator/Actions/GreatStrides.cs @@ -8,5 +8,6 @@ internal class GreatStrides : BaseBuffAction public override int CPCost => 32; - public override Effect Effect => new() { Type = EffectType.GreatStrides, Duration = 3 }; + public override EffectType Effect => EffectType.GreatStrides; + public override byte Duration => 3; } diff --git a/Simulator/Actions/Groundwork.cs b/Simulator/Actions/Groundwork.cs index f37e1c1..baed064 100644 --- a/Simulator/Actions/Groundwork.cs +++ b/Simulator/Actions/Groundwork.cs @@ -13,8 +13,7 @@ internal class Groundwork : BaseAction get { var ret = Simulation.Input.Stats.Level >= 86 ? 3.60f : 3.00f; - // TODO: does not account for waste not - return Simulation.Durability < DurabilityCost ? ret / 2 : ret; + return Simulation.Durability < Simulation.CalculateDurabilityCost(DurabilityCost) ? ret / 2 : ret; } } public override bool IncreasesProgress => true; diff --git a/Simulator/Actions/HeartAndSoul.cs b/Simulator/Actions/HeartAndSoul.cs index 45ed5ed..ed13336 100644 --- a/Simulator/Actions/HeartAndSoul.cs +++ b/Simulator/Actions/HeartAndSoul.cs @@ -9,7 +9,7 @@ internal class HeartAndSoul : BaseBuffAction public override int CPCost => 0; public override bool IncreasesStepCount => false; - public override Effect Effect => new() { Type = EffectType.HeartAndSoul }; + public override EffectType Effect => EffectType.HeartAndSoul; public override bool CanUse => Simulation.Input.Stats.IsSpecialist && Simulation.CountPreviousAction(ActionType.HeartAndSoul) == 0; } diff --git a/Simulator/Actions/Innovation.cs b/Simulator/Actions/Innovation.cs index 5db1695..f8c5737 100644 --- a/Simulator/Actions/Innovation.cs +++ b/Simulator/Actions/Innovation.cs @@ -8,5 +8,6 @@ internal class Innovation : BaseBuffAction public override int CPCost => 18; - public override Effect Effect => new() { Type = EffectType.Innovation, Duration = 4 }; + public override EffectType Effect => EffectType.Innovation; + public override byte Duration => 4; } diff --git a/Simulator/Actions/Manipulation.cs b/Simulator/Actions/Manipulation.cs index 86b7ef6..2e9f44a 100644 --- a/Simulator/Actions/Manipulation.cs +++ b/Simulator/Actions/Manipulation.cs @@ -8,5 +8,19 @@ internal class Manipulation : BaseBuffAction public override int CPCost => 96; - public override Effect Effect => new() { Type = EffectType.Manipulation, Duration = 8 }; + public override EffectType Effect => EffectType.Manipulation; + public override byte Duration => 8; + + public override void Use() + { + if (Simulation.HasEffect(EffectType.Manipulation)) + Simulation.RestoreDurability(5); + + Simulation.ReduceCP(CPCost); + Simulation.ReduceDurability(DurabilityCost); + + UseSuccess(); + + Simulation.IncreaseStepCount(); + } } diff --git a/Simulator/Actions/TrainedFinesse.cs b/Simulator/Actions/TrainedFinesse.cs index 0535504..e65e7be 100644 --- a/Simulator/Actions/TrainedFinesse.cs +++ b/Simulator/Actions/TrainedFinesse.cs @@ -12,6 +12,6 @@ internal class TrainedFinesse : BaseAction public override int DurabilityCost => 0; public override bool CanUse => - (Simulation.GetEffect(EffectType.InnerQuiet)?.Strength ?? 0) == 10 + Simulation.GetEffectStrength(EffectType.InnerQuiet) == 10 && base.CanUse; } diff --git a/Simulator/Actions/Veneration.cs b/Simulator/Actions/Veneration.cs index ab0a45f..5bfb491 100644 --- a/Simulator/Actions/Veneration.cs +++ b/Simulator/Actions/Veneration.cs @@ -9,5 +9,6 @@ internal class Veneration : BaseBuffAction public override int CPCost => 18; public override int DurabilityCost => 0; - public override Effect Effect => new() { Type = EffectType.Veneration, Duration = 4 }; + public override EffectType Effect => EffectType.Veneration; + public override byte Duration => 4; } diff --git a/Simulator/Actions/WasteNot.cs b/Simulator/Actions/WasteNot.cs index 50f8211..d25be2c 100644 --- a/Simulator/Actions/WasteNot.cs +++ b/Simulator/Actions/WasteNot.cs @@ -8,6 +8,7 @@ internal class WasteNot : BaseBuffAction public override int CPCost => 56; - public override Effect Effect => new() { Type = EffectType.WasteNot, Duration = 4 }; + public override EffectType Effect => EffectType.WasteNot; + public override byte Duration => 4; public override EffectType[] ConflictingEffects => new[] { EffectType.WasteNot2 }; } diff --git a/Simulator/Actions/WasteNot2.cs b/Simulator/Actions/WasteNot2.cs index 0296292..ef1a3b0 100644 --- a/Simulator/Actions/WasteNot2.cs +++ b/Simulator/Actions/WasteNot2.cs @@ -8,6 +8,7 @@ internal class WasteNot2 : BaseBuffAction public override int CPCost => 98; - public override Effect Effect => new() { Type = EffectType.WasteNot2, Duration = 8 }; + public override EffectType Effect => EffectType.WasteNot2; + public override byte Duration => 8; public override EffectType[] ConflictingEffects => new[] { EffectType.WasteNot }; } diff --git a/Simulator/Effect.cs b/Simulator/Effect.cs deleted file mode 100644 index 2384987..0000000 --- a/Simulator/Effect.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Craftimizer.Simulator; - -public readonly record struct Effect -{ - public EffectType Type { get; init; } - public int? Duration { get; init; } - public int? Strength { get; init; } - - public bool HasDuration => Duration != null; - public bool HasStrength => Strength != null; - - public Effect DecrementDuration() => this with { Duration = Duration - 1 }; - public Effect IncrementStrength() => this with { Strength = Strength + 1 }; -} diff --git a/Simulator/Effects.cs b/Simulator/Effects.cs new file mode 100644 index 0000000..6372ada --- /dev/null +++ b/Simulator/Effects.cs @@ -0,0 +1,102 @@ +namespace Craftimizer.Simulator; + +public record struct Effects +{ + public byte InnerQuiet { get; set; } + public byte WasteNot { get; set; } + public byte Veneration { get; set; } + public byte GreatStrides { get; set; } + public byte Innovation { get; set; } + public byte FinalAppraisal { get; set; } + public byte WasteNot2 { get; set; } + public byte MuscleMemory { get; set; } + public byte Manipulation { get; set; } + public bool HeartAndSoul { get; set; } + + public void SetDuration(EffectType effect, byte duration) + { + switch (effect) + { + case EffectType.InnerQuiet: + if (duration == 0) + InnerQuiet = 0; + break; + case EffectType.WasteNot: + WasteNot = duration; + break; + case EffectType.Veneration: + Veneration = duration; + break; + case EffectType.GreatStrides: + GreatStrides = duration; + break; + case EffectType.Innovation: + Innovation = duration; + break; + case EffectType.FinalAppraisal: + FinalAppraisal = duration; + break; + case EffectType.WasteNot2: + WasteNot2 = duration; + break; + case EffectType.MuscleMemory: + MuscleMemory = duration; + break; + case EffectType.Manipulation: + Manipulation = duration; + break; + case EffectType.HeartAndSoul: + HeartAndSoul = duration != 0; + break; + } + } + + public void Strengthen(EffectType effect) + { + if (effect == EffectType.InnerQuiet && InnerQuiet < 10) + InnerQuiet++; + } + + public byte GetDuration(EffectType effect) => + effect switch + { + EffectType.InnerQuiet => (byte)(InnerQuiet != 0 ? 1 : 0), + EffectType.WasteNot => WasteNot, + EffectType.Veneration => Veneration, + EffectType.GreatStrides => GreatStrides, + EffectType.Innovation => Innovation, + EffectType.FinalAppraisal => FinalAppraisal, + EffectType.WasteNot2 => WasteNot2, + EffectType.MuscleMemory => MuscleMemory, + EffectType.Manipulation => Manipulation, + EffectType.HeartAndSoul => (byte)(HeartAndSoul ? 1 : 0), + _ => 0 + }; + + public byte GetStrength(EffectType effect) => + effect == EffectType.InnerQuiet ? InnerQuiet : + (byte)(GetDuration(effect) != 0 ? 1 : 0); + + public bool HasEffect(EffectType effect) => + GetDuration(effect) != 0; + + public void DecrementDuration() + { + if (WasteNot > 0) + WasteNot--; + if (WasteNot2 > 0) + WasteNot2--; + if (Veneration > 0) + Veneration--; + if (GreatStrides > 0) + GreatStrides--; + if (Innovation > 0) + Innovation--; + if (FinalAppraisal > 0) + FinalAppraisal--; + if (MuscleMemory > 0) + MuscleMemory--; + if (Manipulation > 0) + Manipulation--; + } +} diff --git a/Simulator/SimulationState.cs b/Simulator/SimulationState.cs index 9682744..c767199 100644 --- a/Simulator/SimulationState.cs +++ b/Simulator/SimulationState.cs @@ -1,6 +1,4 @@ using Craftimizer.Simulator.Actions; -using System; -using System.Collections.Generic; namespace Craftimizer.Simulator; @@ -16,7 +14,7 @@ public readonly record struct SimulationState public int Durability { get; init; } public int CP { get; init; } public Condition Condition { get; init; } - public List ActiveEffects { get; init; } + public Effects ActiveEffects { get; init; } public List ActionHistory { get; init; } // https://github.com/ffxiv-teamcraft/simulator/blob/0682dfa76043ff4ccb38832c184d046ceaff0733/src/model/tables.ts#L2 diff --git a/Simulator/Simulator.cs b/Simulator/Simulator.cs index 468af7a..84699ff 100644 --- a/Simulator/Simulator.cs +++ b/Simulator/Simulator.cs @@ -11,7 +11,7 @@ public class Simulator public int Durability { get; private set; } public int CP { get; private set; } public Condition Condition { get; private set; } - public List ActiveEffects { get; private set; } + public Effects ActiveEffects; public List ActionHistory { get; private set; } public bool IsFirstStep => StepCount == 0; @@ -47,7 +47,7 @@ public class Simulator Durability = state.Durability; CP = state.CP; Condition = state.Condition; - ActiveEffects = new(state.ActiveEffects); + ActiveEffects = state.ActiveEffects; ActionHistory = new(state.ActionHistory); } @@ -60,7 +60,7 @@ public class Simulator Durability = Durability, CP = CP, Condition = Condition, - ActiveEffects = ActiveEffects!, + ActiveEffects = ActiveEffects, ActionHistory = ActionHistory!, }; @@ -88,68 +88,36 @@ public class Simulator baseAction.Use(); ActionHistory!.Add(action); - for (var i = 0; i < ActiveEffects!.Count; ++i) - { - var effect = ActiveEffects[i].DecrementDuration(); - if (effect.Duration == 0) - { - ActiveEffects.RemoveAt(i); - --i; - } - else - ActiveEffects[i] = effect; - } + ActiveEffects.DecrementDuration(); return ActionResponse.UsedAction; } - private int GetEffectIdx(EffectType effect) => - ActiveEffects!.FindIndex(e => e.Type == effect); + public int GetEffectStrength(EffectType effect) => + ActiveEffects.GetStrength(effect); - public Effect? GetEffect(EffectType effect) - { - var idx = GetEffectIdx(effect); - return idx == -1 ? null : ActiveEffects![idx]; - } + public int GetEffectDuration(EffectType effect) => + ActiveEffects.GetDuration(effect); - public void AddEffect(EffectType effect, int? duration = null, int? strength = null) + public void AddEffect(EffectType effect, int duration) { - if (Condition == Condition.Primed && duration != null) + if (Condition == Condition.Primed) duration += 2; // Duration will be decreased in the next step, so we need to add 1 - if (duration != null) - duration++; + duration++; - var newEffect = new Effect { Type = effect, Duration = duration, Strength = strength }; - - var effectIdx = GetEffectIdx(effect); - if (effectIdx != -1) - ActiveEffects![effectIdx] = newEffect; - else - ActiveEffects!.Add(newEffect); + ActiveEffects.SetDuration(effect, (byte)duration); } - public void StrengthenEffect(EffectType effect, int? duration = null) - { - if (duration != null) - duration += 1; - - var effectIdx = GetEffectIdx(effect); - if (effectIdx != -1) - { - if (effect == EffectType.InnerQuiet && ActiveEffects![effectIdx].Strength < 10) - ActiveEffects[effectIdx] = ActiveEffects[effectIdx].IncrementStrength(); - } - else - ActiveEffects!.Add(new Effect { Type = effect, Duration = duration, Strength = 1 }); - } + public void StrengthenEffect(EffectType effect) => + ActiveEffects.Strengthen(effect); public void RemoveEffect(EffectType effect) => - ActiveEffects!.RemoveAll(e => e.Type == effect); + ActiveEffects.SetDuration(effect, 0); public bool HasEffect(EffectType effect) => - ActiveEffects!.Any(e => e.Type == effect); + ActiveEffects.HasEffect(effect); public bool IsPreviousAction(ActionType action, int stepsBack = 1) => ActionHistory!.Count >= stepsBack && ActionHistory[^stepsBack] == action; @@ -287,7 +255,7 @@ public class Simulator if (HasEffect(EffectType.Innovation)) buffModifier += 0.50f; - buffModifier *= 1 + ((GetEffect(EffectType.InnerQuiet)?.Strength ?? 0) * 0.10f); + buffModifier *= 1 + (GetEffectStrength(EffectType.InnerQuiet) * 0.10f); var conditionModifier = Condition switch { diff --git a/Solver/Crafty/SimulationNode.cs b/Solver/Crafty/SimulationNode.cs index 8843858..5dbd42d 100644 --- a/Solver/Crafty/SimulationNode.cs +++ b/Solver/Crafty/SimulationNode.cs @@ -59,8 +59,6 @@ public readonly record struct SimulationNode var fewerStepsScore = fewerStepsBonus * (1f - ((float)(State.ActionCount + 1) / Solver.MaxStepCount)); - Solver.WriteLine($"score: {progressScore:0.00000} {qualityScore:0.00000} {durabilityScore:0.00000} {cpScore:0.00000} {fewerStepsScore:0.00000}"); - return progressScore + qualityScore + durabilityScore + cpScore + fewerStepsScore; } } diff --git a/Solver/Crafty/Simulator.cs b/Solver/Crafty/Simulator.cs index 11410a5..0a92c9f 100644 --- a/Solver/Crafty/Simulator.cs +++ b/Solver/Crafty/Simulator.cs @@ -7,7 +7,7 @@ namespace Craftimizer.Solver.Crafty; public class Simulator : Sim { public new CompletionState CompletionState => - ActionHistory.Count >= Solver.MaxStepCount ? + (ActionHistory.Count + 1) >= Solver.MaxStepCount ? CompletionState.MaxActionCountReached : (CompletionState)base.CompletionState; public override bool IsComplete => CompletionState != CompletionState.Incomplete; @@ -63,6 +63,12 @@ public class Simulator : Sim if (!baseAction.CanUse) return false; + if (action == ActionType.StandardTouch && CP < 32) + return false; + + if (action == ActionType.AdvancedTouch && CP < 46) + return false; + if (CalculateSuccessRate(baseAction.SuccessRate) != 1) return false; @@ -75,7 +81,7 @@ public class Simulator : Sim return false; if (action == ActionType.Groundwork && - Durability < baseAction.DurabilityCost) + Durability < CalculateDurabilityCost(baseAction.DurabilityCost)) return false; if (action == ActionType.FinalAppraisal) @@ -127,7 +133,7 @@ public class Simulator : Sim } if (action == ActionType.ByregotsBlessing && - GetEffect(EffectType.InnerQuiet)?.Strength <= 1) + GetEffectStrength(EffectType.InnerQuiet) <= 1) return false; if ((action == ActionType.WasteNot || action == ActionType.WasteNot2) && @@ -151,7 +157,7 @@ public class Simulator : Sim return false; if ((action == ActionType.Veneration || action == ActionType.Innovation) && - (GetEffect(EffectType.Veneration)?.Duration > 1 || GetEffect(EffectType.Innovation)?.Duration > 1)) + (GetEffectDuration(EffectType.Veneration) > 1 || GetEffectDuration(EffectType.Innovation) > 1)) return false; } diff --git a/Solver/Crafty/Solver.cs b/Solver/Crafty/Solver.cs index 5150304..8a384f4 100644 --- a/Solver/Crafty/Solver.cs +++ b/Solver/Crafty/Solver.cs @@ -11,23 +11,12 @@ public class Solver //public Random Random => Simulator.Input.Random; - public const int Iterations = 100000; + public const int Iterations = 1000; public const float ScoreStorageThreshold = 1f; public const float MaxScoreWeightingConstant = 0.1f; public const float ExplorationConstant = 4f; public const int MaxStepCount = 25; - public static void Write(string data) - { - if (false) - Console.Write(data); - } - public static void WriteLine(string data) - { - if (false) - Console.WriteLine(data); - } - public Solver(SimulationState state, bool strict) { Simulator = new(state); @@ -88,9 +77,6 @@ public class Solver var exploitation = ((1f - w) * average_score) + (w * node.MaxScore); var exploration = MathF.Sqrt(c * MathF.Log(parent.Visits) / visits); - WriteLine($"a {node.ScoreSum} {node.MaxScore}"); - WriteLine($"b {exploitation} {exploration}"); - return exploitation + exploration; } @@ -143,36 +129,27 @@ public class Solver var expandable = selectedNode.State.AvailableActions.Count != 0; var likelyTerminal = selectedNode.Children.Count == 0; - WriteLine("select:"); - WriteLine($"{expandable} {likelyTerminal}".ToLower()); if (expandable || likelyTerminal) { break; } // select the node with the highest score selectedIndex = RustMaxBy(selectedNode.Children, n => Eval(Tree.Get(n).State.Scores, selectedNode.State.Scores)); - WriteLine($"{selectedIndex}"); } return selectedIndex; } public (int Index, CompletionState State, float Score) ExpandAndRollout(int initialIndex) { - WriteLine("expand_and_rollout"); - WriteLine($"{initialIndex}"); // expand once var initialNode = Tree.Get(initialIndex).State; if (initialNode.IsComplete) - { - WriteLine($"ret {initialIndex} {initialNode.CompletionState}"); return (initialIndex, initialNode.CompletionState, initialNode.CalculateScore() ?? 0); - } + var randomAction = initialNode.AvailableActions.ElementAt(0); - initialNode.AvailableActions.Remove(randomAction); - WriteLine($"pick {randomAction.IntName()}"); + initialNode.AvailableActions.RemoveAt(0); var expandedState = Execute(initialNode.State, randomAction, true); var expandedIndex = Tree.Insert(initialIndex, expandedState); - WriteLine($"ins {expandedIndex}"); // playout to a terminal state var currentState = Tree.Get(expandedIndex).State; @@ -189,14 +166,8 @@ public class Solver var score = currentState.CalculateScore() ?? 0; if (currentState.CompletionState == CompletionState.ProgressComplete) { - WriteLine($"calc: {score:0.00000}"); if (score >= ScoreStorageThreshold && score >= Tree.Get(0).State.Scores.MaxScore) { - WriteLine("exp_a"); - foreach (var action in currentState.State.ActionHistory.Skip(preCount)) - Write($">{action.IntName()}"); - WriteLine(""); - (var terminalIndex, _) = ExecuteActions(expandedIndex, currentState.State.ActionHistory.Skip(preCount).ToList(), true); return (terminalIndex, currentState.CompletionState, score); } @@ -206,7 +177,6 @@ public class Solver public void Backpropagate(int startIndex, int targetIndex, float score) { - WriteLine($"back {startIndex}->{targetIndex} {score}"); var currentIndex = startIndex; while (true) { @@ -215,7 +185,6 @@ public class Solver currentScores.Visits++; currentScores.ScoreSum += score; currentScores.MaxScore = Math.Max(currentScores.MaxScore, score); - WriteLine($"bak {currentIndex} {currentScores.Visits} {currentScores.ScoreSum} {currentScores.MaxScore}"); if (currentIndex == targetIndex) break; @@ -228,27 +197,22 @@ public class Solver { for (var i = 0; i < Iterations; i++) { - WriteLine($"search {i}"); var selectedIndex = Select(startIndex); - var (endIndex, state, score) = ExpandAndRollout(selectedIndex); + var (endIndex, _, score) = ExpandAndRollout(selectedIndex); - WriteLine($"backp {endIndex} {score}"); Backpropagate(endIndex, startIndex, score); } } public (List Actions, SimulationNode Node) Solution() { - WriteLine("sol"); var actions = new List(); var node = Tree.Get(0); while (node.Children.Count != 0) { var next_index = RustMaxBy(node.Children, n => Tree.Get(n).State.Scores.MaxScore); - WriteLine($"next: {next_index}"); node = Tree.Get(next_index); if (node.State.Action != null) { - WriteLine($"act: {node.State.Action.Value.IntName()}"); actions.Add(node.State.Action.Value); } }