← Natura·Docs/Modules/Source

verbs/forage.js

26 lines · in natura-src-1.0.0.zip as natura/verbs/forage.js · a module · its entry in the module reference

// verbs/forage.js -- ONE life ontology verb, one concern: move toward the best LOCAL source of a resource when you
// need it. Pure and RENDER-FREE. Universal -- a butterfly seeks nectar, a monkey a fruiting tree, a bat an insect
// swarm, a snail an algal patch, a grazer fresh grass: the entity supplies WHAT the resource is and HOW it moves;
// this supplies WHICH source, scored richest-over-nearest (a full source right here beats a fuller one far off). UMD.
(function (root, factory) {
  if (typeof module !== 'undefined' && module.exports) module.exports = factory();
  else (root.NaturaVerbs = root.NaturaVerbs || {}).forage = factory();
})(typeof self !== 'undefined' ? self : this, function () {
  'use strict';
  // forage(pos, sources, opts) -> { target: bestSource|null, dist, atSource }
  //   pos = {x,y} ; sources = [{x,y,amount}] ; opts = { reach:0.03 (AT it), min:0.05 (ignore below) }
  //   null target = nothing worth going to (the caller wanders / rests instead).
  function forage(pos, sources, opts) {
    opts = opts || {};
    const reach = opts.reach != null ? opts.reach : 0.03, min = opts.min != null ? opts.min : 0.05;
    let best = null, bestScore = -1, bd = Infinity;
    for (let i = 0; i < sources.length; i++) {
      const s = sources[i], amt = s.amount || 0; if (amt <= min) continue;
      const dx = s.x - pos.x, dy = s.y - pos.y, d = Math.sqrt(dx * dx + dy * dy);
      const score = amt / (0.04 + d);                         // richest AND nearest wins
      if (score > bestScore) { bestScore = score; best = s; bd = d; }
    }
    return { target: best, dist: bd, atSource: best != null && bd <= reach };
  }
  return { forage };
});