-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_behavior_tree.js
More file actions
157 lines (152 loc) · 5.52 KB
/
test_behavior_tree.js
File metadata and controls
157 lines (152 loc) · 5.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// poor man's unit test framework
// TODO: dress this up with Jasmine or QUnit or something
function testBehaviorTree(behavior_tree) {
function assert_equal(left, right) {
if (left !== right) {
throw new Error("assertion failure: "+
left+
' does not equal '+
right)
}
}
var Branch = behavior_tree.Branch
var Leaf = behavior_tree.Leaf
var Delay = behavior_tree.Delay
var Prioritized = behavior_tree.Prioritized
var Sequence = behavior_tree.Sequence
var Rule = behavior_tree.Rule
var success = behavior_tree.success
var failure = behavior_tree.failure
var sequential_and = behavior_tree.sequential_and
var sequential_or = behavior_tree.sequential_or
var reactive_and = behavior_tree.reactive_and
var reactive_or = behavior_tree.reactive_or
function test_success_is_success() {
var tree = new Leaf(success)
assert_equal(tree.start(), success)
}
function test_sequential_and_does_not_short_cut_on_success() {
assert_equal(false, sequential_and.shortCutsOn(success))
}
function test_success_is_done() {
assert_equal(true, success.done())
}
function test_success_is_sequential_and_id() {
assert_equal(success, sequential_and.id())
}
function test_success_and_success_is_success() {
var tree = new Branch(new Leaf(success),
sequential_and,
new Leaf(success))
assert_equal(tree.start(), success)
}
function test_success_and_failure_is_failure() {
var tree = new Branch(new Leaf(success),
sequential_and,
new Leaf(failure))
assert_equal(tree.start(), failure)
}
function test_sequential_one_step_cases() {
var cases = [
{ l: success, op: sequential_and, r: success, is: success },
{ l: success, op: sequential_and, r: failure, is: failure },
{ l: failure, op: sequential_and, r: {}, is: failure },
{ l: failure, op: sequential_or, r: failure, is: failure },
{ l: failure, op: sequential_or, r: success, is: success },
{ l: success, op: sequential_or, r: {}, is: success }
]
for (var i in cases) {
var tree = new Branch(new Leaf(cases[i].l),
cases[i].op,
new Leaf(cases[i].r))
assert_equal(tree.start(), cases[i].is)
}
}
function test_two_step_cases() {
var cases = [
{ l: success, op: sequential_and, r: success, is: success },
{ l: success, op: sequential_and, r: failure, is: failure },
{ l: success, op: reactive_and, r: success, is: success },
{ l: success, op: reactive_and, r: failure, is: failure },
{ l: failure, op: sequential_or, r: failure, is: failure },
{ l: failure, op: sequential_or, r: success, is: success },
{ l: failure, op: reactive_or, r: failure, is: failure },
{ l: failure, op: reactive_or, r: success, is: success }
]
for (i in cases) {
var tree = new Delay(new Branch(new Leaf(cases[i].l),
cases[i].op,
new Leaf(cases[i].r)))
assert_equal(tree.start().step(tree), cases[i].is)
var tree = new Branch(new Delay(new Leaf(cases[i].l)),
cases[i].op,
new Leaf(cases[i].r))
assert_equal(tree.start().step(tree), cases[i].is)
var tree = new Branch(new Leaf(cases[i].l),
cases[i].op,
new Delay(new Leaf(cases[i].r)))
assert_equal(tree.start().step(tree), cases[i].is)
}
}
function test_changing_cases() {
var ops = [ sequential_and, reactive_and, sequential_or, reactive_or ]
for (i in ops) {
var op = ops[i];
var identity = op.id()
var killer = op.killer
var initially = new Branch(new Leaf(identity),
op,
new Delay(new Leaf(identity)))
var mind_state = initially.start()
var later = new Branch(new Leaf(killer),
op,
new Delay(new Leaf(identity)))
var result = mind_state.step(later)
if (op.reactive()) {
assert_equal(result, killer);
} else {
assert_equal(result, identity);
}
}
}
// TODO: this is not really sufficient exercise of
// Prioritized, Sequence, and Rule
function test_tree_builders_insufficiently() {
// first the agent ses a path to the left
var clear_left = new Leaf(success)
var clear_ahead = new Leaf(failure)
var clear_right = new Leaf(failure)
var advance = new Delay(new Leaf(success))
var turn_left = new Delay(new Leaf(success))
var turn_right = new Delay(new Leaf(success))
var policy = Prioritized([
Rule(clear_ahead, advance),
Rule(clear_left, Sequence([turn_left, advance])),
Rule(clear_right, Sequence([turn_right, advance]))])
var mind_state = policy.start()
assert_equal(mind_state.toString(), 'lrrl')
// if nothing changes, then the agent goes on to advance
mind_state = mind_state.step(policy)
assert_equal(mind_state.toString(), 'lrrr')
// but if the agent now sees a path forward
clear_ahead = new Leaf(success)
policy = Prioritized([Rule(clear_ahead, advance),
Rule(clear_left, Sequence([turn_left, advance])),
Rule(clear_right, Sequence([turn_right, advance]))
])
// then the agent instead follows the clear_ahead => advance rule
mind_state = mind_state.step(policy)
assert_equal(mind_state.toString(), 'llr')
}
// actually run the tests
test_success_is_success()
test_sequential_and_does_not_short_cut_on_success()
test_success_is_sequential_and_id()
test_success_is_done()
test_success_and_success_is_success()
test_success_and_failure_is_failure()
test_sequential_one_step_cases()
test_two_step_cases()
test_changing_cases()
test_tree_builders_insufficiently()
}