text: /*
    Machine.js
    by mary rose cook
    http://github.com/maryrosecook/machinejs
  
    Make behaviour trees in JavaScript.
    See index.html for an example.
  
    Uses Base.js by Dean Edwards.  Thanks, Dean.
  */
  
  /*
    The tree generator.  Instantiate and then call generateTree(),
    passing the JSON definition of the tree and the object the tree controls.
  */
  var Machine = Base.extend({
    constructor: function() { },
  
    // makes behaviour tree from passed json and returns the root node
    generateTree: function(treeJson, actor) {
      return this.read(treeJson, null, actor);
    },
  
    // reads in all nodes in passed json, constructing a tree of nodes as it goes
    read: function(subTreeJson, parent, actor) {
      var node = null;
      if(subTreeJson.pointer == true)
        node = new Pointer(subTreeJson.identifier,
                           subTreeJson.test,
                           subTreeJson.strategy,
                           parent,
                           actor);
      else
        node = new State(subTreeJson.identifier,
                         subTreeJson.test,
                         subTreeJson.strategy,
                         parent,
                         actor);
  
      node.report = subTreeJson.report;
  
      for(var i in subTreeJson.children)
        node.children[node.children.length] = this.read(subTreeJson.children[i], node, actor);
  
      return node;
    },
  }, {
    getClassName: function() { return "Machine"; }
  
  });
  
  /*
    The object for nodes in the tree.
  */
  var Node = Base.extend({
    identifier: null,
    test: null,
    strategy: null,
    parent: null,
    children: null,
    actor: null,
    report: null,
  
    constructor: function(identifier, test, strategy, parent, actor) {
      this.identifier = identifier;
      this.test = test;
      this.strategy = strategy;
      this.parent = parent;
      this.actor = actor;
      this.children = [];
    },
  
    // A tick of the clock.  Returns the next state.
    tick: function() {
      if(this.isAction()) // run an actual action
        this.run();
  
      var potentialNextState = this.nextState();
      if(potentialNextState !== null)
        return potentialNextState.transition();
      else if(this.can()) // no child state, try and stay in this one
        return this;
      else // can't stay in this one, so back up the tree
        return this.nearestRunnableAncestor().transition();
    },
  
    // gets next state that would be moved to from current state
    nextState: function() {
      var strategy = this.strategy;
      if(strategy === undefined)
      {
        var ancestor = this.nearestAncestorWithStrategy();
        if(ancestor !== null)
          strategy = ancestor.strategy;
      }
  
      if(strategy !== null)
        return this[strategy].call(this);
      else
        return null;
    },
  
    isTransition: function() { return this.children.length > 0 || this instanceof Pointer; },
    isAction: function() { return !this.isTransition(); },
  
    // returns true if actor allowed to enter this state
    can: function() {
      var functionName = this.test; // can specify custom test function name
      if(functionName === undefined) // no override so go with default function name
        functionName = "can" + this.identifier[0].toUpperCase() + this.identifier.substring(1, this.identifier.length);
  
      if(this.actor[functionName] !== undefined)
        return this.actor[functionName].call(this.actor);
      else // no canX() function defined - assume can
        return true;
    },
  
    // returns first child that can run
    prioritised: function() {
      return this.nextRunnable(this.children);
    },
  
    // gets next runnable node in passed list
    nextRunnable: function(nodes) {
      for(var i in nodes)
        if(nodes[i].can())
          return nodes[i];
  
      return null;
    },
  
    // runs all runnable children in order, then kicks up to children's closest runnable ancestor
    sequential: function() {
      var nextState = null;
      if(this.isAction()) // want to get next runnable child or go back up to grandparent
      {
        var foundThis = false;
        for(var i in this.parent.children)
        {
          var sibling = this.parent.children[i];
          if(this.identifier == sibling.identifier)
            foundThis = true;
          else if(foundThis && sibling.can())
            return sibling;
        }
      }
      else // at a sequential parent so try to run first runnable child
      {
        var firstRunnableChild = this.nextRunnable(this.children);
        if(firstRunnableChild !== null)
          return firstRunnableChild;
      }
  
      return this.nearestRunnableAncestor(); // no more runnable children in the sequence so return first runnable ancestor
    },
  
    // returns first namesake forebear encountered when going directly up tree
    nearestAncestor: function(test) {
      if(this.parent === null)
        return null;
      else if(test.call(this.parent) === true)
        return this.parent;
      else
        return this.parent.nearestAncestor(test);
    },
  
    nearestAncestorWithStrategy: function() {
      return this.nearestAncestor(function() {
        return this.strategy !== undefined && this.strategy !== null;
      });
    },
  
    // returns nearest ancestor that can run
    nearestRunnableAncestor: function() {
      return this.nearestAncestor(function() {
        return this.can();
      });
    },
  
    nearestNamesakeAncestor: function(identifier) {
      return this.nearestAncestor(function() {
        return this.identifier == identifier;
      });
    },
  }, {
    getClassName: function() { return "Node"; },
  
  });
  
  
  /*
    A normal state in the tree.
  */
  var State = Node.extend({
    transition: function() {
      return this;
    },
  
    // run the behaviour associated with this state
    run: function() {
      this.actor[this.identifier].call(this.actor); // run the action
    },
  }, {
    getClassName: function() { return "State"; }
  
  });
  
  /*
    A pointer state in the tree.  Directs the actor to a synonymous state
    further up the tree.  Which synonymous state the actor transitions to
    is dependent on the pointer's strategy.
  */
  var Pointer = Node.extend({
    // transition out of this state using the state's strategy
    transition: function() {
      return this[this.strategy].call(this);
    },
  
    // a strategy that moves to the first synonymous ancestor
    hereditory: function() {
      return this.nearestNamesakeAncestor(this.identifier);
    },
  }, {
    getClassName: function() { return "Pointer"; }
  });