From 4532fef46fcfedb9222e665476a4675ef391d0d1 Mon Sep 17 00:00:00 2001 From: That-Madman <144173821+That-Madman@users.noreply.github.com> Date: Sat, 10 Jan 2026 10:50:56 -0500 Subject: [PATCH 01/11] Update Not.java Cleaned up Not.java to properly Java best practices. This includes a minor change to the constructor to properly fit the this/arg dichotomy, and also replaced tick's return method to be more efficient through switch statements, also making it easier to read. --- .../java/com/ftcteams/behaviortrees/Not.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Not.java b/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Not.java index b7a86f8..15bc586 100644 --- a/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Not.java +++ b/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Not.java @@ -6,20 +6,21 @@ public class Not extends Node { Node child; - public Not(Node a) { - this.child = a; + public Not(Node child) { + this.child = child; } @Override public State tick(DebugTree debug, Object obj) { State state = child.tick(debug, obj); - - if (state == State.FAILURE) { - return State.SUCCESS; - } else if (state == State.SUCCESS) { - return State.FAILURE; + + switch (state) { + case State.SUCCESS: + return State.FAILURE; + case State.FAILURE: + return State.SUCCESS; + case State.RUNNING: + return State.RUNNING; } - - return state; } } From fa6042e2fd0909ab4a6db32a4853c1c1e5148ee8 Mon Sep 17 00:00:00 2001 From: That-Madman <144173821+That-Madman@users.noreply.github.com> Date: Sat, 10 Jan 2026 11:05:01 -0500 Subject: [PATCH 02/11] Update Sequence.java Move around the code for a more idiomatic format, and also allowing hopefully for a more opportunistic memory efficiency. --- .../main/java/com/ftcteams/behaviortrees/Sequence.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Sequence.java b/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Sequence.java index 4642ebe..c349ec0 100644 --- a/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Sequence.java +++ b/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Sequence.java @@ -16,18 +16,17 @@ public Sequence(Node ... a) { @Override public State tick(DebugTree debug, Object obj) { debug.startParent(this); + State state = State.SUCCESS; for (Node child : children) { debug.addNode(child); State state = child.tick(debug, obj); debug.updateNode(child, state); - if (state == State.FAILURE) { - return State.FAILURE; - } else if (state == State.RUNNING) { - return State.RUNNING; + if (state == State.FAILURE || state == State.RUNNING) { + break; } } - return State.SUCCESS; + return state; } } From 750a47d6975a969f0e847561af37b4456b484fa5 Mon Sep 17 00:00:00 2001 From: That-Madman <144173821+That-Madman@users.noreply.github.com> Date: Sat, 10 Jan 2026 11:07:01 -0500 Subject: [PATCH 03/11] Update Failover.java Applied to the same fixes of Sequence to Failover. --- .../java/com/ftcteams/behaviortrees/Failover.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Failover.java b/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Failover.java index 644da0a..b3659fd 100644 --- a/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Failover.java +++ b/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Failover.java @@ -17,17 +17,17 @@ public Failover(Node ... a) { @Override public State tick(DebugTree debug, Object obj) { debug.startParent(this); + State state = State.FAILURE; + for (Node child : children) { debug.addNode(child); - State state = child.tick(debug, obj); + state = child.tick(debug, obj); debug.updateNode(child, state); - if (state == State.SUCCESS) { - return State.SUCCESS; - } else if (state == State.RUNNING) { - return State.RUNNING; + if (state == State.SUCCESS || state == State.RUNNING) { + break; } } - return State.FAILURE; + return state; } } From 9b23e03adaa20d6d301f87ec99d5598e86efc127 Mon Sep 17 00:00:00 2001 From: That-Madman <144173821+That-Madman@users.noreply.github.com> Date: Sat, 10 Jan 2026 11:07:48 -0500 Subject: [PATCH 04/11] Update Sequence.java Fixed For loop to not have redundant variables --- .../src/main/java/com/ftcteams/behaviortrees/Sequence.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Sequence.java b/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Sequence.java index c349ec0..bee9b0e 100644 --- a/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Sequence.java +++ b/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Sequence.java @@ -20,7 +20,7 @@ public State tick(DebugTree debug, Object obj) { for (Node child : children) { debug.addNode(child); - State state = child.tick(debug, obj); + state = child.tick(debug, obj); debug.updateNode(child, state); if (state == State.FAILURE || state == State.RUNNING) { From baf60b939cccea0dccc483fd6f5374bfed8dba1d Mon Sep 17 00:00:00 2001 From: That-Madman <144173821+That-Madman@users.noreply.github.com> Date: Sat, 10 Jan 2026 11:14:07 -0500 Subject: [PATCH 05/11] Update Parallel.java Made the code cleaner with a tenary operator --- .../src/main/java/com/ftcteams/behaviortrees/Parallel.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Parallel.java b/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Parallel.java index 0a2d29d..e4deb22 100644 --- a/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Parallel.java +++ b/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Parallel.java @@ -37,9 +37,7 @@ public State tick(DebugTree debug, Object obj) { anyRunning = true; } } - if (anyRunning){ - return State.RUNNING; - } - return State.FAILURE; + + return (anyRunning) ? State.RUNNING : State.FAILURE; } } From 4be0805ed75c3452ad04ea0c0ba5092be2ea5d53 Mon Sep 17 00:00:00 2001 From: That-Madman <144173821+That-Madman@users.noreply.github.com> Date: Sat, 10 Jan 2026 12:20:41 -0500 Subject: [PATCH 06/11] Update DebugTree.java Mainly just some cosmetic shifts to properly indent. --- .../com/ftcteams/behaviortrees/DebugTree.java | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/behaviortrees/src/main/java/com/ftcteams/behaviortrees/DebugTree.java b/behaviortrees/src/main/java/com/ftcteams/behaviortrees/DebugTree.java index 55499c2..20847d2 100644 --- a/behaviortrees/src/main/java/com/ftcteams/behaviortrees/DebugTree.java +++ b/behaviortrees/src/main/java/com/ftcteams/behaviortrees/DebugTree.java @@ -8,14 +8,15 @@ public class DebugTree { static class NodeInfo { int indent; public Node node; - Node.State state = Node.State.RUNNING; + Node.State state; - NodeInfo(int indent, Node node){ + NodeInfo(int indent, Node node) { this.indent = indent; this.node = node; + state = Node.State.RUNNING; } - public String toString(){ + public String toString() { String prefix = new String(new char[indent]).replace("\0", "-"); String name = node.getClass().getSimpleName(); @@ -26,32 +27,36 @@ public String toString(){ return prefix + name + ":S\n"; case RUNNING: return prefix + name + ":R\n"; + default: + return ""; } - return ""; } } List nodeInfoList; Stack parents = new Stack<>(); - public DebugTree(){ + public DebugTree() { reset(); } - public void reset(){ + + public void reset() { nodeInfoList = new LinkedList<>(); parents = new Stack<>(); } - public void startParent(Node parent){ + + public void startParent(Node parent) { parents.push(parent); } - public void addNode(Node node){ + public void addNode(Node node) { nodeInfoList.add(new NodeInfo(parents.size(), node)); } - public void updateNode(Node node, Node.State newState){ + public void updateNode(Node node, Node.State newState) { if (node == parents.peek()){ parents.pop(); } + for (NodeInfo nodeInfo : nodeInfoList){ if(nodeInfo.node == node){ nodeInfo.state = newState; @@ -59,11 +64,12 @@ public void updateNode(Node node, Node.State newState){ } } - public String toString(){ + public String toString() { StringBuilder retString = new StringBuilder(); - for(NodeInfo nodeInfo : nodeInfoList){ + for(NodeInfo nodeInfo : nodeInfoList) { retString.append(nodeInfo.toString()); } + return retString.toString(); } } From ae355398586d2c4c6a8544d3698ea65b6c414d20 Mon Sep 17 00:00:00 2001 From: That-Madman <144173821+That-Madman@users.noreply.github.com> Date: Sat, 10 Jan 2026 12:56:16 -0500 Subject: [PATCH 07/11] Update Parallel.java Added formatting to be more legible. --- .../src/main/java/com/ftcteams/behaviortrees/Parallel.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Parallel.java b/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Parallel.java index e4deb22..2f9c3e4 100644 --- a/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Parallel.java +++ b/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Parallel.java @@ -22,14 +22,16 @@ public Parallel(int requiredSuccesses, Node ... a) { public State tick(DebugTree debug, Object obj) { int numSuccessful = 0; boolean anyRunning = false; + debug.startParent(this); + for (Node child : children) { debug.addNode(child); State state = child.tick(debug, obj); debug.updateNode(child, state); if (state == State.SUCCESS) { - numSuccessful += 1; + numSuccessful++; if (numSuccessful >= requiredSuccesses){ return State.SUCCESS; } From 7b43b0d1b3f9f2da154bdebfb5f890614068d000 Mon Sep 17 00:00:00 2001 From: That-Madman <144173821+That-Madman@users.noreply.github.com> Date: Sat, 10 Jan 2026 13:53:25 -0500 Subject: [PATCH 08/11] Update Parallel.java Added the ability for Parallel to bail early if it cannot meet the required successes --- .../com/ftcteams/behaviortrees/Parallel.java | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Parallel.java b/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Parallel.java index 2f9c3e4..7b987e3 100644 --- a/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Parallel.java +++ b/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Parallel.java @@ -7,7 +7,7 @@ * This executes all of the children and if more than the required succcesses are successful it returns * SUCCESS. Otherwise it returns RUNNING until all are done and then it returns FAILURE. * - * NOTE: right now it will keep running even if there is no way it could be successful + * If it is impossible the required number of successes to be met, it will return FAILURE early. */ public class Parallel extends Node { List children; @@ -21,7 +21,7 @@ public Parallel(int requiredSuccesses, Node ... a) { @Override public State tick(DebugTree debug, Object obj) { int numSuccessful = 0; - boolean anyRunning = false; + int numFailed = 0; debug.startParent(this); @@ -30,16 +30,23 @@ public State tick(DebugTree debug, Object obj) { State state = child.tick(debug, obj); debug.updateNode(child, state); - if (state == State.SUCCESS) { - numSuccessful++; - if (numSuccessful >= requiredSuccesses){ - return State.SUCCESS; - } - } else if (state == State.RUNNING) { - anyRunning = true; + switch (state) { + case SUCCESS: + numSuccessful++; + if (numSuccesful >= requiredSuccesses) { + return State.SUCCESS; + } + break; + + case FAILURE: + numFailed++; + if (children.size() - numFailed > requiredSuccesses) { + return State.FAILURE; + } + break; } } - return (anyRunning) ? State.RUNNING : State.FAILURE; + return State.RUNNING; } } From bedcf83398d9cb45fb8f734356170e5241e5c84a Mon Sep 17 00:00:00 2001 From: That-Madman <144173821+That-Madman@users.noreply.github.com> Date: Sat, 10 Jan 2026 15:17:32 -0500 Subject: [PATCH 09/11] Create ParallelNoBail.java Added an secondary Parallel version that maintains old functionality so as to allow for if a user needs to finish all running Nodes still. --- .../behaviortrees/ParallelNoBail.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 behaviortrees/src/main/java/com/ftcteams/behaviortrees/ParallelNoBail.java diff --git a/behaviortrees/src/main/java/com/ftcteams/behaviortrees/ParallelNoBail.java b/behaviortrees/src/main/java/com/ftcteams/behaviortrees/ParallelNoBail.java new file mode 100644 index 0000000..2c337dc --- /dev/null +++ b/behaviortrees/src/main/java/com/ftcteams/behaviortrees/ParallelNoBail.java @@ -0,0 +1,46 @@ +package com.ftcteams.behaviortrees; + +import java.util.Arrays; +import java.util.List; + +/** + * This executes all of the children and if more than the required succcesses are successful it returns + * SUCCESS. Otherwise it returns RUNNING until all are done and then it returns FAILURE. + * + * It will keep running even if there is no way it could be successful. If you want the program to bail early + * if it cannot succeed, use Parallel instead. + */ +public class ParallelNoBail extends Node { + List children; + int requiredSuccesses; + + public ParallelNoBail(int requiredSuccesses, Node ... a) { + this.children = Arrays.asList(a); + this.requiredSuccesses = requiredSuccesses; + } + + @Override + public State tick(DebugTree debug, Object obj) { + int numSuccessful = 0; + boolean anyRunning = false; + debug.startParent(this); + for (Node child : children) { + debug.addNode(child); + State state = child.tick(debug, obj); + debug.updateNode(child, state); + + if (state == State.SUCCESS) { + numSuccessful += 1; + if (numSuccessful >= requiredSuccesses){ + return State.SUCCESS; + } + } else if (state == State.RUNNING) { + anyRunning = true; + } + } + if (anyRunning){ + return State.RUNNING; + } + return State.FAILURE; + } +} From 2fe612ab3cde8d1d4826f2fffeec14ad1f68b079 Mon Sep 17 00:00:00 2001 From: That-Madman <144173821+That-Madman@users.noreply.github.com> Date: Sat, 10 Jan 2026 15:19:24 -0500 Subject: [PATCH 10/11] Update Parallel.java updated Javadoc --- .../src/main/java/com/ftcteams/behaviortrees/Parallel.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Parallel.java b/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Parallel.java index 7b987e3..98ae6c3 100644 --- a/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Parallel.java +++ b/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Parallel.java @@ -8,6 +8,8 @@ * SUCCESS. Otherwise it returns RUNNING until all are done and then it returns FAILURE. * * If it is impossible the required number of successes to be met, it will return FAILURE early. + * + * If you need RUNNING children to finish even if Paralle will return FAILURE, instead use ParallelNoBail. */ public class Parallel extends Node { List children; From 830545441530d41403128e150405a8e027103245 Mon Sep 17 00:00:00 2001 From: That-Madman <144173821+That-Madman@users.noreply.github.com> Date: Sat, 10 Jan 2026 15:23:33 -0500 Subject: [PATCH 11/11] Update and rename Failover.java to Fallback.java Changed the name of Failover to Fallback to both fit with the Quantum Quacks behavior tree website and also the original ideas of the Behavior Trees --- .../ftcteams/behaviortrees/{Failover.java => Fallback.java} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename behaviortrees/src/main/java/com/ftcteams/behaviortrees/{Failover.java => Fallback.java} (91%) diff --git a/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Failover.java b/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Fallback.java similarity index 91% rename from behaviortrees/src/main/java/com/ftcteams/behaviortrees/Failover.java rename to behaviortrees/src/main/java/com/ftcteams/behaviortrees/Fallback.java index b3659fd..097e316 100644 --- a/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Failover.java +++ b/behaviortrees/src/main/java/com/ftcteams/behaviortrees/Fallback.java @@ -7,10 +7,10 @@ * Failover means that as soon as it hits a child with SUCCESS it returns SUCCESS. If a child is RUNNING, * it returns RUNNING. If all children return FAILURE, it returns FAILURE */ -public class Failover extends Node { +public class Fallback extends Node { List children; - public Failover(Node ... a) { + public Fallback(Node ... a) { this.children = Arrays.asList(a); }