diff --git a/SpriteCompiler.Test/SpriteCompiler.Test.csproj b/SpriteCompiler.Test/SpriteCompiler.Test.csproj
index 97dd1ed..5a699df 100644
--- a/SpriteCompiler.Test/SpriteCompiler.Test.csproj
+++ b/SpriteCompiler.Test/SpriteCompiler.Test.csproj
@@ -62,6 +62,7 @@
+
diff --git a/SpriteCompiler.Test/StateTests.cs b/SpriteCompiler.Test/StateTests.cs
new file mode 100644
index 0000000..9e5d623
--- /dev/null
+++ b/SpriteCompiler.Test/StateTests.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Linq;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using SpriteCompiler.Problem;
+using SpriteCompiler.AI;
+using System.Diagnostics;
+using System.Collections.Generic;
+using FluentAssertions;
+
+namespace SpriteCompiler.Test
+{
+ [TestClass]
+ public class StateTests
+ {
+ [TestMethod]
+ public void TestStateEquivalence()
+ {
+ // States are used in HashSet, so we need to
+ // test that two instances of the same state
+ // are recognized as equivalent
+ var state1 = new SpriteGeneratorState();
+ var state2 = new SpriteGeneratorState();
+
+ Assert.AreEqual(state1, state2);
+
+ var set = new HashSet();
+ set.Add(state1);
+
+ Assert.IsTrue(set.Contains(state2));
+ }
+ }
+}
diff --git a/SpriteCompiler.Test/Tests.cs b/SpriteCompiler.Test/Tests.cs
index 33ab430..a2026ac 100644
--- a/SpriteCompiler.Test/Tests.cs
+++ b/SpriteCompiler.Test/Tests.cs
@@ -103,8 +103,8 @@ namespace SpriteCompiler.Test
// Write out the solution
WriteOutSolution(solution);
- //Assert.AreEqual(3, solution.Count());
- //Assert.AreEqual(10, (int)solution.Last().PathCost);
+ Assert.AreEqual(6, solution.Count());
+ Assert.AreEqual(25, (int)solution.Last().PathCost);
}
private void WriteOutSolution(IEnumerable solution)
diff --git a/SpriteCompiler/AI/AbstractAISearch.cs b/SpriteCompiler/AI/AbstractAISearch.cs
index 99f06ab..522f3ea 100644
--- a/SpriteCompiler/AI/AbstractAISearch.cs
+++ b/SpriteCompiler/AI/AbstractAISearch.cs
@@ -47,8 +47,9 @@
while (!fringe.Empty)
{
var node = fringe.Remove();
+#if DEBUG
Console.WriteLine(string.Format("Removed {0} from the queue with g = {1}, c(n, n') = {2}", node.State, node.PathCost, node.StepCost));
-
+#endif
if (problem.IsGoal(node.State))
{
return Solution(node);
diff --git a/SpriteCompiler/AI/GraphSearch.cs b/SpriteCompiler/AI/GraphSearch.cs
index 39d9594..9cd2319 100644
--- a/SpriteCompiler/AI/GraphSearch.cs
+++ b/SpriteCompiler/AI/GraphSearch.cs
@@ -16,7 +16,7 @@ namespace SpriteCompiler.AI
///
/// Generic graph search. See page 83 in Russell and Norvig. This only works in informed
- /// search if the heuristic is admissible.However, if a heuristic is not admissible and
+ /// search if the heuristic is admissible. However, if a heuristic is not admissible and
/// you still want to use, that means you should know enough to extend this class or write
/// your own Search class.
///
diff --git a/SpriteCompiler/AI/InformedNodeExpander.cs b/SpriteCompiler/AI/InformedNodeExpander.cs
index 4db5129..39e8223 100644
--- a/SpriteCompiler/AI/InformedNodeExpander.cs
+++ b/SpriteCompiler/AI/InformedNodeExpander.cs
@@ -16,8 +16,10 @@ namespace SpriteCompiler.AI
var successors = problem.Successors(node.State);
// Debug
+ #if DEBUG
Console.WriteLine(String.Format("There are {0} successors for {1}", successors.Count(), node));
Console.WriteLine(String.Format("This node has a current path cost of {0}", node.PathCost));
+ #endif
foreach (var successor in successors)
{
@@ -29,8 +31,9 @@ namespace SpriteCompiler.AI
next.StepCost = problem.StepCost(node.State, action, state);
next.Heuristic = problem.Heuristic(state);
+#if DEBUG
Console.WriteLine(" Action = " + next.Action + ", g(n') = " + next.PathCost + ", h(n') = " + next.Heuristic);
-
+#endif
yield return next;
}
}
diff --git a/SpriteCompiler/Adapters/QueueAdapter.cs b/SpriteCompiler/Adapters/QueueAdapter.cs
index 288faed..9fa48c7 100644
--- a/SpriteCompiler/Adapters/QueueAdapter.cs
+++ b/SpriteCompiler/Adapters/QueueAdapter.cs
@@ -20,7 +20,9 @@
{
foreach (var item in items)
{
+#if DEBUG
Console.WriteLine("Enqueuing " + item + " with cost " + item.EstCost);
+#endif
queue.Enqueue(item, item.EstCost);
}
}
diff --git a/SpriteCompiler/Problem/Register.cs b/SpriteCompiler/Problem/Register.cs
index 4751593..7459a36 100644
--- a/SpriteCompiler/Problem/Register.cs
+++ b/SpriteCompiler/Problem/Register.cs
@@ -69,6 +69,11 @@
}
}
+ public override int GetHashCode()
+ {
+ return Value.GetHashCode() + Tag.GetHashCode();
+ }
+
public override bool Equals(object obj)
{
return Equals(obj as Register);
diff --git a/SpriteCompiler/Problem/SpriteGeneratorSearchProblem.cs b/SpriteCompiler/Problem/SpriteGeneratorSearchProblem.cs
index 387ab78..bdf5ed2 100644
--- a/SpriteCompiler/Problem/SpriteGeneratorSearchProblem.cs
+++ b/SpriteCompiler/Problem/SpriteGeneratorSearchProblem.cs
@@ -17,7 +17,8 @@
public static ISearch Create()
{
var expander = new SpriteGeneratorNodeExpander();
- var strategy = new TreeSearch(expander);
+ //var strategy = new TreeSearch(expander);
+ var strategy = new GraphSearch(expander);
return new AStarSearch(strategy);
}
diff --git a/SpriteCompiler/Problem/SpriteGeneratorState.cs b/SpriteCompiler/Problem/SpriteGeneratorState.cs
index 66f3f22..267b387 100644
--- a/SpriteCompiler/Problem/SpriteGeneratorState.cs
+++ b/SpriteCompiler/Problem/SpriteGeneratorState.cs
@@ -117,6 +117,18 @@
;
}
+ public override int GetHashCode()
+ {
+ return
+ A.GetHashCode() +
+ X.GetHashCode() +
+ Y.GetHashCode() +
+ D.GetHashCode() +
+ S.GetHashCode() +
+ P.GetHashCode()
+ ;
+ }
+
public static bool operator ==(SpriteGeneratorState state1, SpriteGeneratorState state2)
{
if (((object)state1) == null || ((object)state2) == null)
diff --git a/SpriteCompiler/Program.cs b/SpriteCompiler/Program.cs
index c4f0226..f63d6d8 100644
--- a/SpriteCompiler/Program.cs
+++ b/SpriteCompiler/Program.cs
@@ -4,6 +4,7 @@
using SpriteCompiler.Problem;
using System;
using System.Collections.Generic;
+ using System.Drawing;
using System.Linq;
public class ApplicationArguments
@@ -26,11 +27,57 @@
static void Main(string[] args)
{
- byte[] data = null;
+ IEnumerable data = null;
- Console.WriteLine(string.Join(", ", args.Select(s => "'" + s + "'")));
- data = args.Select(s => Convert.ToByte(s, 16)).ToArray();
+ try
+ {
+ data = args.Select((s, i) => new SpriteByte(Convert.ToByte(s, 16), (ushort)i));
+ }
+ catch (FormatException e)
+ {
+ // If there is only one or two arguments, them marybe the user passed in a file
+ if (args.Length <= 2)
+ {
+ var palette = new Dictionary();
+ int nextIndex = 1;
+ // Convert the image / mask to a paletted image
+ var bitmap = new Bitmap(args[0]);
+ int[,] buffer = new int[bitmap.Width, bitmap.Height];
+
+ for (int r = 0; r < bitmap.Height; r++)
+ {
+ for (int w = 0; w < bitmap.Width; w++)
+ {
+ var rgb = bitmap.GetPixel(w, r);
+
+ if (!palette.ContainsKey(rgb))
+ {
+ if (palette.Count >= 15)
+ {
+ throw new Exception("Image cannot have more than 15 unique colors");
+ }
+ palette[rgb] = nextIndex++;
+ }
+
+ buffer[w, r] = palette[rgb];
+ }
+ }
+
+ // Pair up pixles to build bytes
+ var sprite = new List();
+
+ for (int r = 0; r < bitmap.Height; r++)
+ {
+ for (int w = 0; w < bitmap.Width; w += 2)
+ {
+ sprite.Add(new SpriteByte((byte)((buffer[w, r] << 4) + buffer[w + 1, r]), (ushort)(r * 160 + (w / 2))));
+ }
+ }
+
+ data = sprite;
+ }
+ }
/*
return;
diff --git a/SpriteCompiler/Samples/SpriteX2_000.gif b/SpriteCompiler/Samples/SpriteX2_000.gif
new file mode 100644
index 0000000..2d7075e
Binary files /dev/null and b/SpriteCompiler/Samples/SpriteX2_000.gif differ
diff --git a/SpriteCompiler/Samples/SpriteX2_001.gif b/SpriteCompiler/Samples/SpriteX2_001.gif
new file mode 100644
index 0000000..29fde57
Binary files /dev/null and b/SpriteCompiler/Samples/SpriteX2_001.gif differ
diff --git a/SpriteCompiler/SpriteCompiler.csproj b/SpriteCompiler/SpriteCompiler.csproj
index 1615ddd..dc24373 100644
--- a/SpriteCompiler/SpriteCompiler.csproj
+++ b/SpriteCompiler/SpriteCompiler.csproj
@@ -43,6 +43,7 @@
+
@@ -92,6 +93,10 @@
+
+
+
+