mirror of
https://github.com/lscharen/iigs-sprite-compiler.git
synced 2024-08-31 18:29:06 +00:00
Flesh out the AI support classes
This commit is contained in:
parent
b3569db950
commit
77f92507b7
@ -5,7 +5,7 @@
|
|||||||
where C : IPathCost<C>
|
where C : IPathCost<C>
|
||||||
{
|
{
|
||||||
public AStarSearch(AbstractAISearch<A, S, T, C> search)
|
public AStarSearch(AbstractAISearch<A, S, T, C> search)
|
||||||
: base(search, new AStarComparator<A, S, T, C>())
|
: base(search) // , new AStarComparator<A, S, T, C>())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
public abstract class AbstractAISearch<A, S, T, C>
|
public abstract class AbstractAISearch<A, S, T, C>
|
||||||
where T : ISearchNode<A, S, T, C>
|
where T : ISearchNode<A, S, T, C>
|
||||||
where C : IComparable<C>
|
where C : IPathCost<C>
|
||||||
{
|
{
|
||||||
// Conceptually the expander is responsible for two things:
|
// Conceptually the expander is responsible for two things:
|
||||||
//
|
//
|
||||||
@ -68,7 +68,7 @@
|
|||||||
return !solution.Any();
|
return !solution.Any();
|
||||||
}
|
}
|
||||||
|
|
||||||
public 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));
|
fringe.Enqueue(expander.CreateNode(default(T), initialState));
|
||||||
return ExtendSearch(problem, fringe);
|
return ExtendSearch(problem, fringe);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
namespace SpriteCompiler.AI
|
namespace SpriteCompiler.AI
|
||||||
{
|
{
|
||||||
|
using Adapters;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
public class BestFirstSearch<A, S, T, C> : ISearch<A, S, T, C>
|
public class BestFirstSearch<A, S, T, C> : ISearch<A, S, T, C>
|
||||||
@ -15,10 +16,10 @@
|
|||||||
this.fringe = fringe;
|
this.fringe = fringe;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BestFirstSearch(AbstractAISearch<A, S, T, C> search, IComparer<T> comparator)
|
public BestFirstSearch(AbstractAISearch<A, S, T, C> search)
|
||||||
{
|
{
|
||||||
this.search = search;
|
this.search = search;
|
||||||
// this.fringe = new PriorityQueue<T>(INITIAL_CAPACITY, comparator);
|
this.fringe = new QueueAdapter<T, C>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<T> Search(ISearchProblem<A, S, C> problem, S initialState)
|
public IEnumerable<T> Search(ISearchProblem<A, S, C> problem, S initialState)
|
||||||
|
38
SpriteCompiler/AI/GraphSearch.cs
Normal file
38
SpriteCompiler/AI/GraphSearch.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace SpriteCompiler.AI
|
||||||
|
{
|
||||||
|
public class GraphSearch<A, S, T, C> : AbstractAISearch<A, S, T, C>
|
||||||
|
where T : ISearchNode<A, S, T, C>
|
||||||
|
where C : IPathCost<C>
|
||||||
|
{
|
||||||
|
private readonly ISet<S> closed = new HashSet<S>();
|
||||||
|
|
||||||
|
public GraphSearch(INodeExpander<A, S, T, C> expander)
|
||||||
|
: base(expander)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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
|
||||||
|
/// you still want to use, that means you should know enough to extend this class or write
|
||||||
|
/// your own Search class.
|
||||||
|
/// </summary>
|
||||||
|
public override IEnumerable<T> Search(ISearchProblem<A, S, C> problem, IQueue<T> fringe, S initialState)
|
||||||
|
{
|
||||||
|
closed.Clear();
|
||||||
|
return base.Search(problem, fringe, initialState);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void AddNodes(IQueue<T> fringe, T node, ISearchProblem<A, S, C> problem)
|
||||||
|
{
|
||||||
|
if (!closed.Contains(node.State))
|
||||||
|
{
|
||||||
|
closed.Add(node.State);
|
||||||
|
fringe.AddRange(Expand(problem, node));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
SpriteCompiler/AI/IGoalTest.cs
Normal file
7
SpriteCompiler/AI/IGoalTest.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace SpriteCompiler.AI
|
||||||
|
{
|
||||||
|
public interface IGoalTest<S>
|
||||||
|
{
|
||||||
|
bool IsGoal(S state);
|
||||||
|
}
|
||||||
|
}
|
9
SpriteCompiler/AI/IHeuristicFunction.cs
Normal file
9
SpriteCompiler/AI/IHeuristicFunction.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace SpriteCompiler.AI
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
|
||||||
|
public interface IHeuristicFunction<S, C> where C : IPathCost<C>
|
||||||
|
{
|
||||||
|
C Eval(S state);
|
||||||
|
}
|
||||||
|
}
|
@ -11,7 +11,7 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface INodeExpander<A, S, T, C>
|
public interface INodeExpander<A, S, T, C>
|
||||||
where T : ISearchNode<A, S, T, C>
|
where T : ISearchNode<A, S, T, C>
|
||||||
where C : IComparable<C>
|
where C : IPathCost<C>
|
||||||
{
|
{
|
||||||
IEnumerable<T> Expand(ISearchProblem<A, S, C> problem, T node);
|
IEnumerable<T> Expand(ISearchProblem<A, S, C> problem, T node);
|
||||||
T CreateNode(T parent, S state);
|
T CreateNode(T parent, S state);
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
namespace SpriteCompiler.AI
|
namespace SpriteCompiler.AI
|
||||||
{
|
{
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
public interface IQueue<T>
|
public interface IQueue<T>
|
||||||
{
|
{
|
||||||
void Clear();
|
void Clear();
|
||||||
bool Empty { get; }
|
bool Empty { get; }
|
||||||
T Remove();
|
T Remove();
|
||||||
|
|
||||||
void Enqueue(T item);
|
void Enqueue(T item);
|
||||||
|
void AddRange(IEnumerable<T> items);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,13 +9,17 @@
|
|||||||
/// <typeparam name="S">State of the search</typeparam>
|
/// <typeparam name="S">State of the search</typeparam>
|
||||||
/// <typeparam name="T">Type of the parent</typeparam>
|
/// <typeparam name="T">Type of the parent</typeparam>
|
||||||
/// <typeparam name="C">Cost type</typeparam>
|
/// <typeparam name="C">Cost type</typeparam>
|
||||||
public interface ISearchNode<A, S, T, C> where C : IComparable<C>
|
public interface ISearchNode<A, S, T, C> : ISearchNode<C> where C : IPathCost<C>
|
||||||
{
|
{
|
||||||
A Action { get; set; }
|
A Action { get; set; }
|
||||||
C StepCost { get; set; }
|
C StepCost { get; set; }
|
||||||
C PathCost { get; }
|
|
||||||
int Depth { get; }
|
int Depth { get; }
|
||||||
S State { get; }
|
S State { get; }
|
||||||
T Parent { get; }
|
T Parent { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface ISearchNode<C>
|
||||||
|
{
|
||||||
|
C PathCost { get; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
9
SpriteCompiler/AI/IStepCostFunction.cs
Normal file
9
SpriteCompiler/AI/IStepCostFunction.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace SpriteCompiler.AI
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
|
||||||
|
public interface IStepCostFunction<A, S, C> where C : IPathCost<C>
|
||||||
|
{
|
||||||
|
C StepCost(S fromState, A action, S toState);
|
||||||
|
}
|
||||||
|
}
|
9
SpriteCompiler/AI/ISuccessorFunction.cs
Normal file
9
SpriteCompiler/AI/ISuccessorFunction.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace SpriteCompiler.AI
|
||||||
|
{
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
public interface ISuccessorFunction<A, S>
|
||||||
|
{
|
||||||
|
IDictionary<A, S> Successors(S state);
|
||||||
|
}
|
||||||
|
}
|
28
SpriteCompiler/AI/InformedNodeExpander.cs
Normal file
28
SpriteCompiler/AI/InformedNodeExpander.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace SpriteCompiler.AI
|
||||||
|
{
|
||||||
|
public abstract class InformedNodeExpander<A, S, T, C> : INodeExpander<A, S, T, C>
|
||||||
|
where T : HeuristicSearchNode<A, S, T, C>
|
||||||
|
where C : IPathCost<C>
|
||||||
|
{
|
||||||
|
public abstract T CreateNode(T parent, S state);
|
||||||
|
|
||||||
|
public IEnumerable<T> Expand(ISearchProblem<A, S, C> problem, T node)
|
||||||
|
{
|
||||||
|
foreach (var successor in problem.Successors(node.State))
|
||||||
|
{
|
||||||
|
var action = successor.Key;
|
||||||
|
var state = successor.Value;
|
||||||
|
var next = CreateNode(node, state);
|
||||||
|
|
||||||
|
next.Action = action;
|
||||||
|
next.StepCost = problem.StepCost(node.State, action, state);
|
||||||
|
next.Heuristic = problem.Heuristic(state);
|
||||||
|
|
||||||
|
yield return next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
45
SpriteCompiler/AI/SearchProblem.cs
Normal file
45
SpriteCompiler/AI/SearchProblem.cs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace SpriteCompiler.AI
|
||||||
|
{
|
||||||
|
public class SearchProblem<A, S, C> : ISearchProblem<A, S, C>
|
||||||
|
where C : IPathCost<C>
|
||||||
|
{
|
||||||
|
private readonly IGoalTest<S> goalTest;
|
||||||
|
private readonly IStepCostFunction<A, S, C> stepCost;
|
||||||
|
private readonly ISuccessorFunction<A, S> successorFn;
|
||||||
|
private readonly IHeuristicFunction<S, C> heuristicFn;
|
||||||
|
|
||||||
|
public SearchProblem(IGoalTest<S> goalTest, IStepCostFunction<A, S, C> stepCost, ISuccessorFunction<A, S> successor, IHeuristicFunction<S, C> heuristicFn)
|
||||||
|
{
|
||||||
|
this.goalTest = goalTest;
|
||||||
|
this.stepCost = stepCost;
|
||||||
|
this.successorFn = successor;
|
||||||
|
this.heuristicFn = heuristicFn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDictionary<A, S> Successors(S state)
|
||||||
|
{
|
||||||
|
return successorFn.Successors(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsGoal(S state)
|
||||||
|
{
|
||||||
|
return goalTest.IsGoal(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public C StepCost(S fromState, A action, S toState)
|
||||||
|
{
|
||||||
|
return stepCost.StepCost(fromState, action, toState);
|
||||||
|
}
|
||||||
|
|
||||||
|
public C Heuristic(S state)
|
||||||
|
{
|
||||||
|
return heuristicFn.Eval(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
SpriteCompiler/AI/TreeSearch.cs
Normal file
22
SpriteCompiler/AI/TreeSearch.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace SpriteCompiler.AI
|
||||||
|
{
|
||||||
|
public class TreeSearch<A, S, T, C> : AbstractAISearch<A, S, T, C>
|
||||||
|
where T : ISearchNode<A, S, T, C>
|
||||||
|
where C : IPathCost<C>
|
||||||
|
{
|
||||||
|
public TreeSearch(INodeExpander<A, S, T, C> expander)
|
||||||
|
: base(expander)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generic tree search. See page 72 in Russell and Norvig
|
||||||
|
/// </summary>
|
||||||
|
protected override void AddNodes(IQueue<T> fringe, T node, ISearchProblem<A, S, C> problem)
|
||||||
|
{
|
||||||
|
fringe.AddRange(Expand(problem, node));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user