Begin adding ability to load images from command line. Additional tests; start to move toward graph search and then IDA*

This commit is contained in:
Lucas Scharenbroich 2016-12-05 21:55:04 -06:00
parent 5fe12243ad
commit 0a26e62c73
14 changed files with 118 additions and 9 deletions

View File

@ -62,6 +62,7 @@
<ItemGroup>
<Compile Include="HeuristicTests.cs" />
<Compile Include="RegisterTests.cs" />
<Compile Include="StateTests.cs" />
<Compile Include="Tests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>

View File

@ -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<SpriteGeneratorState>();
set.Add(state1);
Assert.IsTrue(set.Contains(state2));
}
}
}

View File

@ -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<SpriteGeneratorSearchNode> solution)

View File

@ -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);

View File

@ -16,7 +16,7 @@ namespace SpriteCompiler.AI
/// <summary>
/// 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.
/// </summary>

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -69,6 +69,11 @@
}
}
public override int GetHashCode()
{
return Value.GetHashCode() + Tag.GetHashCode();
}
public override bool Equals(object obj)
{
return Equals(obj as Register);

View File

@ -17,7 +17,8 @@
public static ISearch<CodeSequence, SpriteGeneratorState, SpriteGeneratorSearchNode, IntegerPathCost> Create()
{
var expander = new SpriteGeneratorNodeExpander();
var strategy = new TreeSearch<CodeSequence, SpriteGeneratorState, SpriteGeneratorSearchNode, IntegerPathCost>(expander);
//var strategy = new TreeSearch<CodeSequence, SpriteGeneratorState, SpriteGeneratorSearchNode, IntegerPathCost>(expander);
var strategy = new GraphSearch<CodeSequence, SpriteGeneratorState, SpriteGeneratorSearchNode, IntegerPathCost>(expander);
return new AStarSearch<CodeSequence, SpriteGeneratorState, SpriteGeneratorSearchNode, IntegerPathCost>(strategy);
}

View File

@ -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)

View File

@ -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<SpriteByte> 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<Color, int>();
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<SpriteByte>();
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;

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -43,6 +43,7 @@
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
@ -92,6 +93,10 @@
<None Include="packages.config" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Content Include="Samples\SpriteX2_000.gif" />
<Content Include="Samples\SpriteX2_001.gif" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.