mirror of
https://github.com/lscharen/iigs-sprite-compiler.git
synced 2024-10-06 03:56:57 +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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,8 +4,18 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
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 T : ISearchNode<A, S, T, C>
|
||||||
where C : IPathCost<C>
|
where C : IPathCost<C>
|
||||||
{
|
{
|
||||||
@ -19,10 +29,12 @@
|
|||||||
// decouple the search algorithm from the state expansion
|
// decouple the search algorithm from the state expansion
|
||||||
|
|
||||||
private INodeExpander<A, S, T, C> expander;
|
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.expander = expander;
|
||||||
|
this.fringe = fringe;
|
||||||
}
|
}
|
||||||
|
|
||||||
public INodeExpander<A, S, T, C> Expander { get { return expander; } set { expander = value; } }
|
public INodeExpander<A, S, T, C> Expander { get { return expander; } set { expander = value; } }
|
||||||
@ -46,21 +58,34 @@
|
|||||||
{
|
{
|
||||||
while (!fringe.Empty)
|
while (!fringe.Empty)
|
||||||
{
|
{
|
||||||
var node = fringe.Remove();
|
var step = SearchStep(problem, fringe);
|
||||||
#if DEBUG
|
if (step.IsGoal)
|
||||||
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);
|
return Solution(step.Node);
|
||||||
}
|
}
|
||||||
|
|
||||||
AddNodes(fringe, node, problem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Enumerable.Empty<T>();
|
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)
|
public IEnumerable<T> Expand(ISearchProblem<A, S, C> problem, T node)
|
||||||
{
|
{
|
||||||
return expander.Expand(problem, 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)
|
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);
|
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);
|
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);
|
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);
|
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);
|
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();
|
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);
|
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 mask = new List<byte>();
|
||||||
var filename = (string)null;
|
var filename = (string)null;
|
||||||
Color? maskColor = null;
|
Color? maskColor = null;
|
||||||
|
int? maxCycles = null;
|
||||||
var sprite = new List<SpriteByte>();
|
var sprite = new List<SpriteByte>();
|
||||||
|
bool verbose = false;
|
||||||
|
|
||||||
var p = new FluentCommandLineParser();
|
var p = new FluentCommandLineParser();
|
||||||
|
|
||||||
@ -62,6 +64,12 @@
|
|||||||
p.Setup<string>('i', "image")
|
p.Setup<string>('i', "image")
|
||||||
.Callback(_ => filename = _);
|
.Callback(_ => filename = _);
|
||||||
|
|
||||||
|
p.Setup<string>('l', "limit")
|
||||||
|
.Callback(_ => maxCycles = int.Parse(_));
|
||||||
|
|
||||||
|
p.Setup<string>('v', "verbose")
|
||||||
|
.Callback(_ => verbose = true);
|
||||||
|
|
||||||
p.Setup<string>("bg-color")
|
p.Setup<string>("bg-color")
|
||||||
.Callback(_ => maskColor = Color.FromArgb(0xFF, Color.FromArgb(Convert.ToInt32(_, 16))));
|
.Callback(_ => maskColor = Color.FromArgb(0xFF, Color.FromArgb(Convert.ToInt32(_, 16))));
|
||||||
|
|
||||||
@ -72,6 +80,15 @@
|
|||||||
Console.WriteLine("Input filename is " + filename);
|
Console.WriteLine("Input filename is " + filename);
|
||||||
Console.WriteLine("Image mask color is " + (maskColor.HasValue ? maskColor.ToString() : "(none)"));
|
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))
|
if (!String.IsNullOrEmpty(filename))
|
||||||
{
|
{
|
||||||
var palette = new Dictionary<Color, int>();
|
var palette = new Dictionary<Color, int>();
|
||||||
@ -149,23 +166,38 @@
|
|||||||
|
|
||||||
sprite.Add(new SpriteByte(data_byte, mask_byte, offset));
|
sprite.Add(new SpriteByte(data_byte, mask_byte, offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Set the global state
|
initialState = SpriteGeneratorState.Init(sprite);
|
||||||
var problem = SpriteGeneratorSearchProblem.CreateSearchProblem();
|
}
|
||||||
var search = SpriteGeneratorSearchProblem.Create();
|
else if (data.Count == mask.Count)
|
||||||
|
|
||||||
if (data.Count == mask.Count)
|
|
||||||
{
|
{
|
||||||
var solution = search.Search(problem, SpriteGeneratorState.Init(data, mask));
|
initialState = SpriteGeneratorState.Init(data, mask);
|
||||||
WriteOutSolution(solution);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var solution = search.Search(problem, SpriteGeneratorState.Init(data));
|
initialState = SpriteGeneratorState.Init(data);
|
||||||
WriteOutSolution(solution);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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\IHeuristicFunction.cs" />
|
||||||
<Compile Include="AI\InformedNodeExpander.cs" />
|
<Compile Include="AI\InformedNodeExpander.cs" />
|
||||||
<Compile Include="AI\INodeLimiter.cs" />
|
<Compile Include="AI\INodeLimiter.cs" />
|
||||||
|
<Compile Include="AI\ISearchStepInfo.cs" />
|
||||||
<Compile Include="AI\ISuccessorFunction.cs" />
|
<Compile Include="AI\ISuccessorFunction.cs" />
|
||||||
<Compile Include="AI\IGoalTest.cs" />
|
<Compile Include="AI\IGoalTest.cs" />
|
||||||
<Compile Include="AI\INodeExpander.cs" />
|
<Compile Include="AI\INodeExpander.cs" />
|
||||||
|
Loading…
Reference in New Issue
Block a user