Simplest Behaviour Tree
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
namespace SimplestBehaviourTree | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
new RunTree().Run(); | |
Console.ReadLine(); | |
} | |
} | |
public class RunTree | |
{ | |
private int i = 0; | |
public void Run() | |
{ | |
var plant = new Action(PlantSeeds); | |
var plantIfThereIsSpace = new Selector(new Action(WeedsNotCoveringGround), plant); | |
var sequenece = new Sequence(new Action(GetToPlantingGrounds), plant); | |
var root = new Selector(sequenece, plantIfThereIsSpace); | |
//set a reference to the root | |
var behaviour = new Behavior(root); | |
behaviour.Behave(); | |
} | |
private Result GetToPlantingGrounds() | |
{ | |
if(i++<10) | |
{ | |
Console.WriteLine("Action - searching planting grounds"); | |
return Result.Running; | |
} | |
return Result.Success; | |
} | |
private static Result PlantSeeds() | |
{ | |
Console.WriteLine("Action - plant "); | |
return Result.Success; | |
} | |
private static Result WeedsNotCoveringGround() | |
{ | |
Console.WriteLine("Conditional - Is there space "); | |
return Result.Failure; | |
} | |
} | |
public enum Result | |
{ | |
Failure, | |
Success, | |
Running | |
} | |
public class Action : BehaviorComponent | |
{ | |
private readonly Func<Result> _action; | |
public Action(Func<Result> action) | |
{ | |
_action = action; | |
} | |
public override Result Behave() | |
{ | |
switch (_action.Invoke()) | |
{ | |
case Result.Success: | |
ReturnCode = Result.Success; | |
return ReturnCode; | |
case Result.Failure: | |
ReturnCode = Result.Failure; | |
return ReturnCode; | |
case Result.Running: | |
ReturnCode = Result.Running; | |
return ReturnCode; | |
default: | |
ReturnCode = Result.Failure; | |
return ReturnCode; | |
} | |
} | |
} | |
public interface IComposite | |
{ | |
} | |
public abstract class BehaviorComponent | |
{ | |
protected Result ReturnCode; | |
public abstract Result Behave(); | |
} | |
public class Behavior | |
{ | |
private readonly BehaviorComponent _root; | |
public Result ReturnCode { get; set; } | |
public Behavior(IComposite root) | |
{ | |
_root = root as BehaviorComponent; | |
} | |
public Result Behave() | |
{ | |
ReturnCode = _root.Behave(); | |
return ReturnCode; | |
} | |
} | |
public class Selector : BehaviorComponent, IComposite | |
{ | |
private readonly BehaviorComponent[] _behaviors; | |
public Selector(params BehaviorComponent[] behaviors) | |
{ | |
_behaviors = behaviors; | |
} | |
public override Result Behave() | |
{ | |
for (int index = 0; index < _behaviors.Length; ) | |
{ | |
var behaviorComponent = _behaviors[index]; | |
switch (behaviorComponent.Behave()) | |
{ | |
case Result.Failure: | |
index++; | |
continue; | |
case Result.Success: | |
index++; | |
ReturnCode = Result.Success; | |
return ReturnCode; | |
case Result.Running: | |
ReturnCode = Result.Running; | |
return ReturnCode; | |
default: | |
continue; | |
} | |
} | |
return ReturnCode; | |
} | |
} | |
public class Sequence : BehaviorComponent, IComposite | |
{ | |
private readonly BehaviorComponent[] _behaviors; | |
public Sequence(params BehaviorComponent[] behaviors) | |
{ | |
_behaviors = behaviors; | |
} | |
public override Result Behave() | |
{ | |
for (int index = 0; index < _behaviors.Length; ) | |
{ | |
var behaviorComponent = _behaviors[index]; | |
switch (behaviorComponent.Behave()) | |
{ | |
case Result.Success: | |
index++; | |
continue; | |
case Result.Failure: | |
index++; | |
ReturnCode = Result.Failure; | |
return ReturnCode; | |
case Result.Running: | |
continue; | |
default: | |
ReturnCode = Result.Success; | |
continue; | |
} | |
} | |
return ReturnCode; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment