AI Planning is a process of realization of strategies or action sequences. Hierarchical Task Networks are a subset of AI Planning approaches where tasks(actions) can require calling other tasks or be composed of multiple methods.
A task that is composed of multiple methods is called a composite task. A composite task is planned successfully when one of its methods is planned to run. A method and a primitive task can only call other tasks or operators. Operators are atomic identifiers of the underlying process and are represented by Strings. This project is inspired by AI Pro's article on HTNs
Many research projects in HTNs are driven by the LISP community (e.g. SHOP2) which often drives new developers away. This project implements a python-like syntax parser to allow for a friendlier HTN experience. Sample problems can be found in htn-problems folder. Overall the syntax uses newlines and tabulation as means of introducing expression separators and blocks. The following keywords are recognized:
task- represents the beginning of a task statement. Full syntax:task NAME(preconditions):whereNAMEis any non-keyword string of alphanumeric characters andpreconditionsis a boolean expressionmethod- represents the beginning of a method statement. Methods can be defined insidetasks only. Full syntax:method NAME(preconditions):whereNAMEis any non-keyword string of alphanumeric characters andpreconditionsis a boolean expression.else- syntactic sugar formethod DontNAME(!preconditions):- inverts the preconditions of a previous method. Since this is an equivalent of a method,elsecan only appear in ataskbody.effects- represents the beginning oftask's effects block. Effects usually contain variable assignment statements. Must appear on the same identation level astaskwithout any blank lines before the last task.or,and,not- syntactic sugar for|,&,!boolean operations.true,false- syntactic sugar for1and0literals. Internally all expressions operate on Rust'si32type.
Example:
task Main:
method FindTrunk(WsTrunkHealth == 0): # precondition - can only run this is WsTrunkHealth is 0
UprootTrunk()
Main() # Supports recursion, will plan Main task again.
method Attack(WsCanSeeEnemy): # name(conditions)
AttackEnemy()
Main()
else: # syntactic sugar for "method DontAttack(!WsCanSeeEnemy)"
CheckBridge()
Main()
method Wait:
wait()
Main()
task AttackEnemy:
method AttackWithTrunk(WsTrunkHealth > 0):
NavigateToEnemy()
DoTrunkSlam()
task DoTrunkSlam(WsTrunkHealth > 0):
DoTrunkSlamOperator()
effects:
WsTrunkHealth -= 1