diff --git a/Craftimizer.Test/Craftimizer.Test.csproj b/Craftimizer.Test/Craftimizer.Test.csproj
new file mode 100644
index 0000000..5344fb4
--- /dev/null
+++ b/Craftimizer.Test/Craftimizer.Test.csproj
@@ -0,0 +1,24 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Craftimizer.Test/Solver/ActionSet.cs b/Craftimizer.Test/Solver/ActionSet.cs
new file mode 100644
index 0000000..27061a0
--- /dev/null
+++ b/Craftimizer.Test/Solver/ActionSet.cs
@@ -0,0 +1,104 @@
+using Craftimizer.Simulator.Actions;
+
+namespace Craftimizer.Test.Solver;
+
+[TestClass]
+public class ActionSetTests
+{
+ [TestMethod]
+ public void TestAcceptedActions()
+ {
+ var actions = Craftimizer.Solver.Simulator.AcceptedActions;
+ var lut = Craftimizer.Solver.Simulator.AcceptedActionsLUT;
+
+ Assert.IsTrue(actions.Length <= 32);
+ foreach(var i in Enum.GetValues())
+ {
+ var idx = lut[(byte)i];
+ if (idx != 0)
+ Assert.AreEqual(i, actions[idx]);
+ }
+ }
+
+ [TestMethod]
+ public void TestSize()
+ {
+ var set = new ActionSet();
+ Assert.IsTrue(set.IsEmpty);
+ Assert.AreEqual(0, set.Count);
+
+ set.AddAction(ActionType.BasicSynthesis);
+ set.AddAction(ActionType.WasteNot2);
+
+ Assert.AreEqual(2, set.Count);
+ Assert.IsFalse(set.IsEmpty);
+
+ set.RemoveAction(ActionType.BasicSynthesis);
+ set.RemoveAction(ActionType.WasteNot2);
+
+ Assert.IsTrue(set.IsEmpty);
+ Assert.AreEqual(0, set.Count);
+ }
+
+ [TestMethod]
+ public void TestAddRemove()
+ {
+ var set = new ActionSet();
+
+ Assert.IsTrue(set.AddAction(ActionType.BasicSynthesis));
+ Assert.IsFalse(set.AddAction(ActionType.BasicSynthesis));
+
+ Assert.IsTrue(set.RemoveAction(ActionType.BasicSynthesis));
+ Assert.IsFalse(set.RemoveAction(ActionType.BasicSynthesis));
+
+ Assert.IsTrue(set.AddAction(ActionType.BasicSynthesis));
+ Assert.IsTrue(set.AddAction(ActionType.WasteNot2));
+
+ Assert.IsTrue(set.RemoveAction(ActionType.BasicSynthesis));
+ Assert.IsTrue(set.RemoveAction(ActionType.WasteNot2));
+ }
+
+ [TestMethod]
+ public void TestHasAction()
+ {
+ var set = new ActionSet();
+
+ set.AddAction(ActionType.BasicSynthesis);
+
+ Assert.IsTrue(set.HasAction(ActionType.BasicSynthesis));
+ Assert.IsFalse(set.HasAction(ActionType.WasteNot2));
+
+ set.AddAction(ActionType.WasteNot2);
+ Assert.IsTrue(set.HasAction(ActionType.BasicSynthesis));
+ Assert.IsTrue(set.HasAction(ActionType.WasteNot2));
+
+ set.RemoveAction(ActionType.BasicSynthesis);
+ Assert.IsFalse(set.HasAction(ActionType.BasicSynthesis));
+ Assert.IsTrue(set.HasAction(ActionType.WasteNot2));
+ }
+
+ [TestMethod]
+ public void TestElementAt()
+ {
+ var set = new ActionSet();
+
+ set.AddAction(ActionType.BasicSynthesis);
+ set.AddAction(ActionType.ByregotsBlessing);
+ set.AddAction(ActionType.DelicateSynthesis);
+ set.AddAction(ActionType.FocusedTouch);
+
+ Assert.AreEqual(3, set.Count);
+
+ Assert.AreEqual(ActionType.DelicateSynthesis, set.ElementAt(0));
+ Assert.AreEqual(ActionType.FocusedTouch, set.ElementAt(1));
+ Assert.AreEqual(ActionType.ByregotsBlessing, set.ElementAt(2));
+ Assert.AreEqual(ActionType.BasicSynthesis, set.ElementAt(3));
+
+ set.RemoveAction(ActionType.FocusedTouch);
+
+ Assert.AreEqual(3, set.Count);
+ Assert.AreEqual(ActionType.DelicateSynthesis, set.ElementAt(0));
+ Assert.AreEqual(ActionType.ByregotsBlessing, set.ElementAt(1));
+ Assert.AreEqual(ActionType.BasicSynthesis, set.ElementAt(2));
+ }
+}
diff --git a/Craftimizer.Test/Usings.cs b/Craftimizer.Test/Usings.cs
new file mode 100644
index 0000000..da624f8
--- /dev/null
+++ b/Craftimizer.Test/Usings.cs
@@ -0,0 +1,3 @@
+global using Microsoft.VisualStudio.TestTools.UnitTesting;
+global using Craftimizer.Solver;
+global using Craftimizer.Simulator;
diff --git a/Craftimizer.sln b/Craftimizer.sln
index 358354c..9b6d4a8 100644
--- a/Craftimizer.sln
+++ b/Craftimizer.sln
@@ -17,6 +17,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Craftimizer.Solver", "Solve
{172EE849-AC7E-4F2A-ACAB-EF9D065523B3} = {172EE849-AC7E-4F2A-ACAB-EF9D065523B3}
EndProjectSection
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Craftimizer.Test", "Craftimizer.Test\Craftimizer.Test.csproj", "{C3AEA981-9DA8-405C-995B-86528493891B}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -57,6 +59,14 @@ Global
{2B0EA452-6DFC-48DB-9049-EA782E600C21}.Release|Any CPU.Build.0 = Release|Any CPU
{2B0EA452-6DFC-48DB-9049-EA782E600C21}.Release|x64.ActiveCfg = Release|Any CPU
{2B0EA452-6DFC-48DB-9049-EA782E600C21}.Release|x64.Build.0 = Release|Any CPU
+ {C3AEA981-9DA8-405C-995B-86528493891B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C3AEA981-9DA8-405C-995B-86528493891B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C3AEA981-9DA8-405C-995B-86528493891B}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {C3AEA981-9DA8-405C-995B-86528493891B}.Debug|x64.Build.0 = Debug|Any CPU
+ {C3AEA981-9DA8-405C-995B-86528493891B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C3AEA981-9DA8-405C-995B-86528493891B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C3AEA981-9DA8-405C-995B-86528493891B}.Release|x64.ActiveCfg = Release|Any CPU
+ {C3AEA981-9DA8-405C-995B-86528493891B}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE