]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Allow the creation of recursive HTNs (#30138)
authorosjarw <62134478+osjarw@users.noreply.github.com>
Tue, 30 Jul 2024 02:18:53 +0000 (05:18 +0300)
committerGitHub <noreply@github.com>
Tue, 30 Jul 2024 02:18:53 +0000 (12:18 +1000)
Allow recursive HTNs

Content.IntegrationTests/Tests/NPC/NPCTest.cs
Content.Server/NPC/HTN/HTNCompoundPrototype.cs
Content.Server/NPC/HTN/HTNPlanJob.cs
Content.Server/NPC/HTN/HTNTask.cs

index 83321fe6138f32f2d52d828b870810a8b7454b3e..064fd6c5bf062a0c2061c05fcc2bcb23d9bc54c2 100644 (file)
@@ -45,6 +45,10 @@ public sealed class NPCTest
                     var count = counts.GetOrNew(compound.ID);
                     count++;
 
+                    // Compound tasks marked with AllowRecursion are only evaluated once
+                    if (counts.ContainsKey(compound.ID) && compound.AllowRecursion)
+                        continue;
+
                     Assert.That(count, Is.LessThan(50));
                     counts[compound.ID] = count;
                     Count(protoManager.Index<HTNCompoundPrototype>(compoundTask.Task), counts, htnSystem, protoManager);
index 29cfb96f977b96985dd280a1f8b078a7bd331a5b..69f84419736f0668df028a75a2c06feba3c340ba 100644 (file)
@@ -12,4 +12,10 @@ public sealed partial class HTNCompoundPrototype : IPrototype
 
     [DataField("branches", required: true)]
     public List<HTNBranch> Branches = new();
+
+    /// <summary>
+    /// Exclude this compound task from the CompoundRecursion integration test.
+    /// </summary>
+    [DataField]
+    public bool AllowRecursion = false;
 }
index 8158303524a6a7661309d9b7e3cb778f419623dc..9c62f5840a726e20cad28ac41b08cc6cc22d219d 100644 (file)
@@ -63,8 +63,13 @@ public sealed class HTNPlanJob : Job<HTNPlan>
         // How many primitive tasks we've added since last record.
         var primitiveCount = 0;
 
+        int tasksProcessed = 0;
+
         while (tasksToProcess.TryDequeue(out var currentTask))
         {
+            if (tasksProcessed++ > _rootTask.MaximumTasks)
+                throw new Exception("HTN Planner exceeded maximum tasks");
+
             switch (currentTask)
             {
                 case HTNCompoundTask compound:
index 0f7c0a377ea27836283dbb7a096d0f109710a351..c09849d079f6d278b10e113bb7d46fbaf936257a 100644 (file)
@@ -3,4 +3,10 @@ namespace Content.Server.NPC.HTN;
 [ImplicitDataDefinitionForInheritors]
 public abstract partial class HTNTask
 {
+    /// <summary>
+    /// Limit the amount of tasks the planner considers. Exceeding this value sleeps the NPC and throws an exception.
+    /// The expected way to hit this limit is with badly written recursive tasks.
+    /// </summary>
+    [DataField]
+    public int MaximumTasks = 1000;
 }