####planner w/ resource conservation, flow up deletion trees, tree flattening, internal movement gradient
#propagate state 0 (final) from seed outwards
(a); (a.isSeed == 1); a.state = 0 & a.depth = 0 & a.parent = -1;
(a,b); (a.state == 0) & (b.inside == 1) & (a.state != a.prev(1).state); b.state = 0 & b.depth = 0 & b.parent = -1;
(a); (a.state == 3); a.state = 0 & a.depth = 0 & a.parent = -1;

#if we can create, do so
(a); (a.state == 0) & (a.$freeSpaces->size > 0) & (a.rsc == 1); a.create(a.$freeSpaces->any);

#propagate state 1 (looking for path) outwards from boundary
(a,b); ((a.state == 0) | (a.state == 1)) & (b.inside == 0) & (b.curr.state == 2) & (a.state != a.prev(1).state); b.state = 1;

##find best parent for deletion trees
#if we can find a better parent, clear notChild set and trigger query to rebuild it
(a,b); (b.state != 0) & ((a.parent != -1) | (a.state == 0))  & (b.depth > a.depth + 1) & (b.deleteMe == 0); b.parent = a.id & b.depth = a.depth + 1 & b.clearNotChild(0) & b.repopulate = b.curr.repopulate + 1;

#rebuild notChild set from all neighbors in FINAL and neighbors with other parents with depth <= ours
(a,b); (a.repopulate != a.prev(1).repopulate) & ((b.state == 0) | ((b.parent != -1) & (b.parent != a.id) & (a.curr.depth >= b.depth -1))); a.addNotChild(b.id);

#if we switch state or depth, notify neighbors who may no longer be our parent
(a,b); (a.parent != -1) & (a.parent != b.id) & (a.depth != a.prev(1).depth) & (b.depth >= a.depth - 1); b.addNotChild(a.id);
#(a,b); (a.state == 0) & (b.id > -1) & (a.state != a.prev(1).state); b.addNotChild(a.id);
(a,b); (a.state == 0) & (b.id > -1); b.addNotChild(a.id);
(a,b); (a.parent != -1) & (a.parent == b.id); b.removeNotChild(a.id);

#if we have no neighbors that are our children, we can have a destroyer delete us (two-phase deletion-push)
(b,a); (a.state != 0) & (a.inside == 0) & (a.curr.rsc == 0) & (b.curr.rsc == 0) & (a.curr.$neighbors->size <= a.curr.$notChildOf->intersect(a.curr.$neighbors)->size); a.deleteMe = 1 & a.depth = 10000;
(b,a); (a.state != 0) & (a.inside == 0) & (a.curr.rsc == 0) & (b.curr.rsc == 0) & (a.curr.$neighbors->size <= a.curr.$notChildOf->intersect(a.curr.$neighbors)->size) & (a.deleteMe == 1); a.destroyTowards(b.id);
(a); (a.deleteMe == 1) & (a.curr.$neighbors->size <= a.curr.$notChildOf->intersect(a.curr.$neighbors)->size); a.deleteMe = 0;

#internal gradient for moving resources away from deletion boundary
(a,b); (a.state == 1) & (b.state == 0); b.gradient = 1;
(a,b); (a.gradient + 1 < b.gradient) & (a.gradient < 5) & (a.gradient != a.prev(1).gradient) & (b.state == 0); b.gradient = a.gradient + 1;

#New gradient from building sites
#(a); (a.dcond.state == 0) & (a.$dcond.freeSpaces->size != 0); a.dcond.gradient = 0;
#(a,b); (a.dcond.gradient != a.prev(1).dcond.gradient) & (b.dcond.state == 0); b.dcond.gradient = a.dcond.gradient + 1;

#resource movement (up tree, and then randomly)
(a,b); (a.rsc == 1) & (a.parent == b.id) ; b.takeRsc(a.id);
(a,b); (a.rsc == 1) & (a.random == 1) & (b.rsc == 0) & (b.state != 1); b.takeRsc(a.id);
(a,b); (a.rsc == 1) & (a.gradient <= b.gradient) & (b.rsc == 0) & (b.state != 1); b.takeRsc(a.id);

#various debug graphics conditions
(a); (a.dcond.parent != -1); a.arrow(a.dcond.parent);
(a); (a.id > 0); a.green = (a.dcond.inside * 127) + 128 - (a.dcond.rsc * 127)  & a.red = 255 - (a.dcond.inside * 127) - (a.dcond.rsc * 127)  & a.blue = (a.dcond.rsc * 127) + 128;