mirror of
https://github.com/lscharen/iigs-sprite-compiler.git
synced 2024-08-31 18:29:06 +00:00
Interim refactoring of core AI search code to be more inspectable
This commit is contained in:
parent
5b45dfefa8
commit
cfc2cda1a8
83
AI.Test/AI.Test.csproj
Normal file
83
AI.Test/AI.Test.csproj
Normal file
@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>66b89e29-23e4-4d16-a3d5-e55f0eda4d87</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>AI.Test</RootNamespace>
|
||||
<AssemblyName>AI.Test</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
|
||||
<IsCodedUITest>False</IsCodedUITest>
|
||||
<TestProjectType>UnitTest</TestProjectType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
|
||||
</ItemGroup>
|
||||
</When>
|
||||
<Otherwise>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
|
||||
</ItemGroup>
|
||||
</Otherwise>
|
||||
</Choose>
|
||||
<ItemGroup>
|
||||
<Compile Include="UnitTest1.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</When>
|
||||
</Choose>
|
||||
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
|
||||
<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.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
120
AI.Test/EightPuzzleBoard.cs
Normal file
120
AI.Test/EightPuzzleBoard.cs
Normal file
@ -0,0 +1,120 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AI.Test
|
||||
{
|
||||
public class EightPuzzleBoard
|
||||
{
|
||||
protected static Random rng = new Random();
|
||||
|
||||
public enum Direction
|
||||
{
|
||||
LEFT,
|
||||
RIGHT,
|
||||
UP,
|
||||
DOWN
|
||||
}
|
||||
|
||||
private int[] board;
|
||||
|
||||
public EightPuzzleBoard()
|
||||
: this(new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 })
|
||||
{
|
||||
}
|
||||
|
||||
public EightPuzzleBoard(int[] aBoard)
|
||||
{
|
||||
this.board = aBoard;
|
||||
}
|
||||
|
||||
public EightPuzzleBoard(EightPuzzleBoard aBoard)
|
||||
{
|
||||
this.board = (int[])aBoard.board.Clone();
|
||||
}
|
||||
|
||||
public EightPuzzleBoard Scramble()
|
||||
{
|
||||
return Scramble(10);
|
||||
}
|
||||
|
||||
public EightPuzzleBoard Scramble(int n)
|
||||
{
|
||||
var newPuzzle = new EightPuzzleBoard(this);
|
||||
var direction = Enum.GetValues(typeof(Direction)).Cast<Direction>().ToList();
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
int j = rng.Next(direction.Count);
|
||||
if (newPuzzle.CanMoveGap(direction[j]))
|
||||
{
|
||||
newPuzzle.MoveGap(direction[j]);
|
||||
}
|
||||
}
|
||||
|
||||
return newPuzzle;
|
||||
}
|
||||
|
||||
private int[] ind2sub(int x)
|
||||
{
|
||||
if (x < 0 || x > 8)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new int[] { x / 3, x % 3 };
|
||||
}
|
||||
|
||||
protected int sub2ind(int x, int y)
|
||||
{
|
||||
return x * 3 + y;
|
||||
}
|
||||
|
||||
public int this[int key]
|
||||
{
|
||||
get
|
||||
{
|
||||
return board[key];
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
board[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
private int GapPosition { get { return GetPositionOf(0); } }
|
||||
|
||||
public int CountMismatches(EightPuzzleBoard aBoard)
|
||||
{
|
||||
int count = 0;
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
if (board[i] != aBoard[i] && board[i] != 0)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private int GetPositionOf(int val)
|
||||
{
|
||||
int retVal = -1;
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
if (board[i] == val)
|
||||
{
|
||||
retVal = i;
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public int[] Board { get { return board; } }
|
||||
|
||||
|
||||
}
|
||||
}
|
36
AI.Test/Properties/AssemblyInfo.cs
Normal file
36
AI.Test/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("AI.Test")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("AI.Test")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2016")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("66b89e29-23e4-4d16-a3d5-e55f0eda4d87")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
14
AI.Test/SearchTest.cs
Normal file
14
AI.Test/SearchTest.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace AI.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class SearchTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void TestMethod1()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -5,7 +5,17 @@
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
||||
public abstract class AbstractAISearch<A, S, T, C>
|
||||
/// <summary>
|
||||
/// An abstract description of a state-space search. Specific algorthims are determined by
|
||||
/// how the nodes are expanded, eveanluated and enqueued.
|
||||
///
|
||||
/// The description of the AI problem is delegated to the ISearchProblem interface.
|
||||
/// </summary>
|
||||
/// <typeparam name="A"></typeparam>
|
||||
/// <typeparam name="S"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <typeparam name="C"></typeparam>
|
||||
public abstract class AbstractAISearch<A, S, T, C> : ISearch<A, S, T, C>
|
||||
where T : ISearchNode<A, S, T, C>
|
||||
where C : IPathCost<C>
|
||||
{
|
||||
@ -19,10 +29,12 @@
|
||||
// decouple the search algorithm from the state expansion
|
||||
|
||||
private INodeExpander<A, S, T, C> expander;
|
||||
private readonly IQueue<T> fringe;
|
||||
|
||||
public AbstractAISearch(INodeExpander<A, S, T, C> expander)
|
||||
public AbstractAISearch(INodeExpander<A, S, T, C> expander, IQueue<T> fringe)
|
||||
{
|
||||
this.expander = expander;
|
||||
this.fringe = fringe;
|
||||
}
|
||||
|
||||
public INodeExpander<A, S, T, C> Expander { get { return expander; } set { expander = value; } }
|
||||
@ -46,21 +58,34 @@
|
||||
{
|
||||
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))
|
||||
var step = SearchStep(problem, fringe);
|
||||
if (step.IsGoal)
|
||||
{
|
||||
return Solution(node);
|
||||
return Solution(step.Node);
|
||||
}
|
||||
|
||||
AddNodes(fringe, node, problem);
|
||||
}
|
||||
|
||||
return Enumerable.Empty<T>();
|
||||
}
|
||||
|
||||
public ISearchStepInfo<T> SearchStep(ISearchProblem<A, S, C> problem, IQueue<T> fringe)
|
||||
{
|
||||
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 new SearchStepInfo<T>(node, Solution(node));
|
||||
}
|
||||
|
||||
AddNodes(fringe, node, problem);
|
||||
|
||||
return new SearchStepInfo<T>(node, null);
|
||||
}
|
||||
|
||||
public IEnumerable<T> Expand(ISearchProblem<A, S, C> problem, T node)
|
||||
{
|
||||
return expander.Expand(problem, node);
|
||||
@ -73,10 +98,16 @@
|
||||
|
||||
public virtual IEnumerable<T> Search(ISearchProblem<A, S, C> problem, IQueue<T> fringe, S initialState)
|
||||
{
|
||||
fringe.Enqueue(expander.CreateNode(default(T), initialState));
|
||||
InitializeSearch(fringe, initialState);
|
||||
return ExtendSearch(problem, fringe);
|
||||
}
|
||||
|
||||
public void InitializeSearch(IQueue<T> fringe, S initialState)
|
||||
{
|
||||
fringe.Clear();
|
||||
fringe.Enqueue(expander.CreateNode(default(T), initialState));
|
||||
}
|
||||
|
||||
protected abstract void AddNodes(IQueue<T> fringe, T node, ISearchProblem<A, S, C> problem);
|
||||
}
|
||||
}
|
||||
|
103
SpriteCompiler/AI/AbstractStateSpaceSearch.cs
Normal file
103
SpriteCompiler/AI/AbstractStateSpaceSearch.cs
Normal file
@ -0,0 +1,103 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SpriteCompiler.AI
|
||||
{
|
||||
public abstract class AbstractStateSpaceSearch<A, S, T, C>
|
||||
where T : ISearchNode<A, S, T, C>
|
||||
where C : IPathCost<C>
|
||||
{
|
||||
private readonly INodeExpander<A, S, T, C> expander;
|
||||
private readonly Func<IQueue<T>> fringe;
|
||||
|
||||
public AbstractStateSpaceSearch(INodeExpander<A, S, T, C> expander, Func<IQueue<T>> fringe)
|
||||
{
|
||||
this.expander = expander;
|
||||
this.fringe = fringe;
|
||||
}
|
||||
|
||||
public ISearchProblemInstance<A, S, T, C> Create(ISearchProblem<A, S, C> problem, S initialState)
|
||||
{
|
||||
return new SearchProblemInstance<A, S, T, C>(problem, fringe(), initialState);
|
||||
}
|
||||
}
|
||||
|
||||
public interface ISearchProblemInstance<A, S, T, C>
|
||||
where T : ISearchNode<A, S, T, C>
|
||||
where C : IPathCost<C>
|
||||
{
|
||||
/// <summary>
|
||||
/// Tries to find a solution to the search problem. Returns null if no solution can be found.
|
||||
/// This method can be called repeatedly to try to find additional, sub optimal solutions if
|
||||
/// supported.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IEnumerable<T> FindSolution();
|
||||
|
||||
/// <summary>
|
||||
/// Take a single step of the searth to allow introspection of the search process
|
||||
/// </summary>
|
||||
/// <param name="problem"></param>
|
||||
/// <returns></returns>
|
||||
ISearchStepInfo<T> Step();
|
||||
|
||||
/// <summary>
|
||||
/// Provide a set of callbacks to watch the execution of a search
|
||||
/// </summary>
|
||||
// void Trace();
|
||||
}
|
||||
|
||||
public class SearchProblemInstance<A, S, T, C> : ISearchProblemInstance<A, S, T, C>
|
||||
where T : ISearchNode<A, S, T, C>
|
||||
where C : IPathCost<C>
|
||||
{
|
||||
private readonly ISearchProblem<A, S, C> problem;
|
||||
private readonly S initialState;
|
||||
private readonly IQueue<T> fringe;
|
||||
|
||||
public SearchProblemInstance(ISearchProblem<A, S, C> problem, IQueue<T> fringe, S initialState)
|
||||
{
|
||||
this.problem = problem;
|
||||
this.fringe = fringe;
|
||||
this.initialState = initialState;
|
||||
}
|
||||
|
||||
public IEnumerable<T> FindSolution()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public ISearchStepInfo<T> Step()
|
||||
{
|
||||
var node = fringe.Remove();
|
||||
|
||||
if (problem.IsGoal(node.State))
|
||||
{
|
||||
return new SearchStepInfo<T>(node, Solution(node));
|
||||
}
|
||||
|
||||
AddNodes(fringe, node, problem);
|
||||
|
||||
return new SearchStepInfo<T>(node, null);
|
||||
}
|
||||
|
||||
public IEnumerable<T> Solution(T node)
|
||||
{
|
||||
var sequence = new List<T>();
|
||||
|
||||
while (node != null)
|
||||
{
|
||||
sequence.Add(node);
|
||||
node = node.Parent;
|
||||
}
|
||||
|
||||
sequence.Reverse();
|
||||
|
||||
return sequence;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -32,5 +32,15 @@
|
||||
{
|
||||
return search.ExtendSearch(problem, fringe);
|
||||
}
|
||||
|
||||
public void InitializeSearch(S initialState)
|
||||
{
|
||||
search.InitializeSearch(fringe, initialState);
|
||||
}
|
||||
|
||||
public ISearchStepInfo<T> SearchStep(ISearchProblem<A,S,C> problem)
|
||||
{
|
||||
return search.SearchStep(problem, fringe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,5 +28,15 @@ namespace SpriteCompiler.AI
|
||||
{
|
||||
return search.ExtendSearch(problem, fringe);
|
||||
}
|
||||
|
||||
public void InitializeSearch(S initialState)
|
||||
{
|
||||
search.InitializeSearch(fringe, initialState);
|
||||
}
|
||||
|
||||
public ISearchStepInfo<T> SearchStep(ISearchProblem<A, S, C> problem)
|
||||
{
|
||||
return search.SearchStep(problem, fringe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,5 +20,7 @@
|
||||
*/
|
||||
IEnumerable<T> ExtendSearch(ISearchProblem<A, S, C> problem);
|
||||
|
||||
void InitializeSearch(S initialState);
|
||||
ISearchStepInfo<T> SearchStep(ISearchProblem<A, S, C> problem);
|
||||
}
|
||||
}
|
||||
|
31
SpriteCompiler/AI/ISearchStepInfo.cs
Normal file
31
SpriteCompiler/AI/ISearchStepInfo.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SpriteCompiler.AI
|
||||
{
|
||||
public interface ISearchStepInfo<T>
|
||||
{
|
||||
bool IsGoal { get; }
|
||||
T Node { get; }
|
||||
IEnumerable<T> Solution { get; }
|
||||
}
|
||||
|
||||
public class SearchStepInfo<T> : ISearchStepInfo<T>
|
||||
{
|
||||
private readonly T node;
|
||||
private readonly IEnumerable<T> solution;
|
||||
|
||||
public SearchStepInfo(T node, IEnumerable<T> solution)
|
||||
{
|
||||
this.solution = solution;
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
public IEnumerable<T> Solution { get { return solution; } }
|
||||
public bool IsGoal { get { return solution != null; } }
|
||||
public T Node { get { return node; } }
|
||||
}
|
||||
}
|
@ -41,5 +41,15 @@ namespace SpriteCompiler.AI
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void InitializeSearch(S initialState)
|
||||
{
|
||||
search.InitializeSearch(initialState);
|
||||
}
|
||||
|
||||
public ISearchStepInfo<T> SearchStep(ISearchProblem<A, S, C> problem)
|
||||
{
|
||||
return search.SearchStep(problem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,5 +22,15 @@
|
||||
|
||||
return new AStarSearch<CodeSequence, SpriteGeneratorState, SpriteGeneratorSearchNode, IntegerPathCost>(strategy);
|
||||
}
|
||||
|
||||
public static ISearch<CodeSequence, SpriteGeneratorState, SpriteGeneratorSearchNode, IntegerPathCost> Create(int maxCycles)
|
||||
{
|
||||
var expander = new SpriteGeneratorNodeExpander();
|
||||
//var strategy = new TreeSearch<CodeSequence, SpriteGeneratorState, SpriteGeneratorSearchNode, IntegerPathCost>(expander);
|
||||
var strategy = new GraphSearch<CodeSequence, SpriteGeneratorState, SpriteGeneratorSearchNode, IntegerPathCost>(expander);
|
||||
|
||||
var maxCost = (IntegerPathCost)maxCycles;
|
||||
return new IterativeDeepeningAStarSearch<CodeSequence, SpriteGeneratorState, SpriteGeneratorSearchNode, IntegerPathCost>(strategy, maxCost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,9 @@
|
||||
var mask = new List<byte>();
|
||||
var filename = (string)null;
|
||||
Color? maskColor = null;
|
||||
int? maxCycles = null;
|
||||
var sprite = new List<SpriteByte>();
|
||||
bool verbose = false;
|
||||
|
||||
var p = new FluentCommandLineParser();
|
||||
|
||||
@ -62,6 +64,12 @@
|
||||
p.Setup<string>('i', "image")
|
||||
.Callback(_ => filename = _);
|
||||
|
||||
p.Setup<string>('l', "limit")
|
||||
.Callback(_ => maxCycles = int.Parse(_));
|
||||
|
||||
p.Setup<string>('v', "verbose")
|
||||
.Callback(_ => verbose = true);
|
||||
|
||||
p.Setup<string>("bg-color")
|
||||
.Callback(_ => maskColor = Color.FromArgb(0xFF, Color.FromArgb(Convert.ToInt32(_, 16))));
|
||||
|
||||
@ -72,6 +80,15 @@
|
||||
Console.WriteLine("Input filename is " + filename);
|
||||
Console.WriteLine("Image mask color is " + (maskColor.HasValue ? maskColor.ToString() : "(none)"));
|
||||
|
||||
// Set the global state
|
||||
var problem = SpriteGeneratorSearchProblem.CreateSearchProblem();
|
||||
var search = maxCycles.HasValue ?
|
||||
SpriteGeneratorSearchProblem.Create(maxCycles.Value) :
|
||||
SpriteGeneratorSearchProblem.Create();
|
||||
|
||||
SpriteGeneratorState initialState = null;
|
||||
|
||||
// Handle the difference command line cases
|
||||
if (!String.IsNullOrEmpty(filename))
|
||||
{
|
||||
var palette = new Dictionary<Color, int>();
|
||||
@ -150,22 +167,37 @@
|
||||
sprite.Add(new SpriteByte(data_byte, mask_byte, offset));
|
||||
}
|
||||
}
|
||||
|
||||
initialState = SpriteGeneratorState.Init(sprite);
|
||||
}
|
||||
|
||||
// Set the global state
|
||||
var problem = SpriteGeneratorSearchProblem.CreateSearchProblem();
|
||||
var search = SpriteGeneratorSearchProblem.Create();
|
||||
|
||||
if (data.Count == mask.Count)
|
||||
else if (data.Count == mask.Count)
|
||||
{
|
||||
var solution = search.Search(problem, SpriteGeneratorState.Init(data, mask));
|
||||
WriteOutSolution(solution);
|
||||
initialState = SpriteGeneratorState.Init(data, mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
var solution = search.Search(problem, SpriteGeneratorState.Init(data));
|
||||
initialState = SpriteGeneratorState.Init(data);
|
||||
}
|
||||
|
||||
IEnumerable<SpriteGeneratorSearchNode> solution = null;
|
||||
if (verbose)
|
||||
{
|
||||
search.InitializeSearch(initialState);
|
||||
while (true)
|
||||
{
|
||||
var step = search.SearchStep(problem);
|
||||
if (step.IsGoal)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
solution = search.Search(problem, initialState);
|
||||
}
|
||||
|
||||
WriteOutSolution(solution);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -66,6 +66,7 @@
|
||||
<Compile Include="AI\IHeuristicFunction.cs" />
|
||||
<Compile Include="AI\InformedNodeExpander.cs" />
|
||||
<Compile Include="AI\INodeLimiter.cs" />
|
||||
<Compile Include="AI\ISearchStepInfo.cs" />
|
||||
<Compile Include="AI\ISuccessorFunction.cs" />
|
||||
<Compile Include="AI\IGoalTest.cs" />
|
||||
<Compile Include="AI\INodeExpander.cs" />
|
||||
|
Loading…
Reference in New Issue
Block a user