整理桌面
This commit is contained in:
		
							
								
								
									
										99
									
								
								node_modules/neataptic/docs/js/articles/target-seekingai/field.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								node_modules/neataptic/docs/js/articles/target-seekingai/field.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,99 @@
 | 
			
		||||
/* Global vars */
 | 
			
		||||
var players = [];
 | 
			
		||||
var walker = new Walker();
 | 
			
		||||
var iteration = 0;
 | 
			
		||||
var highestScore = 0;
 | 
			
		||||
 | 
			
		||||
/** Setup the canvas */
 | 
			
		||||
function setup(){
 | 
			
		||||
  var canvas = createCanvas(WIDTH, HEIGHT);
 | 
			
		||||
  canvas.parent('field');
 | 
			
		||||
  initNeat();
 | 
			
		||||
 | 
			
		||||
  // Do some initial mutation
 | 
			
		||||
  if(!USE_TRAINED_POP){
 | 
			
		||||
    for(var i = 0; i < 1; i++) neat.mutate();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  startEvaluation();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function draw(){
 | 
			
		||||
  clear();
 | 
			
		||||
  squareGrid();
 | 
			
		||||
 | 
			
		||||
  // Check if evaluation is done
 | 
			
		||||
  if(iteration == ITERATIONS){
 | 
			
		||||
    endEvaluation();
 | 
			
		||||
    iteration = 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Update and visualise players
 | 
			
		||||
  for(var i = players.length - 1; i >= 0; i--){
 | 
			
		||||
    var player = players[i];
 | 
			
		||||
 | 
			
		||||
    // Some players are eaten during the iteration
 | 
			
		||||
    player.update();
 | 
			
		||||
    player.show();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  walker.update();
 | 
			
		||||
  walker.show();
 | 
			
		||||
 | 
			
		||||
  iteration++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Draw a square grid with grey lines */
 | 
			
		||||
function squareGrid(){
 | 
			
		||||
  stroke(204, 204, 204, 160);
 | 
			
		||||
  strokeWeight(1);
 | 
			
		||||
  fill(255);
 | 
			
		||||
  for(var x = 0; x < WIDTH/40; x++){
 | 
			
		||||
    line(x * 40, 0, x * 40, HEIGHT);
 | 
			
		||||
  }
 | 
			
		||||
  for(var y = 0; y < HEIGHT/40; y++){
 | 
			
		||||
    line(0, y * 40, WIDTH, y * 40);
 | 
			
		||||
  }
 | 
			
		||||
  noStroke();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Calculate distance between two points */
 | 
			
		||||
function distance(x1, y1, x2, y2){
 | 
			
		||||
  var dx = x1 - x2;
 | 
			
		||||
  var dy = y1 - y2;
 | 
			
		||||
 | 
			
		||||
  return Math.sqrt(dx * dx + dy * dy);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Get a relative color between red and green */
 | 
			
		||||
var activationColor = function(value, max){
 | 
			
		||||
  var power = 1 - Math.min(value/max, 1);
 | 
			
		||||
  var color = [255, 255, 0]
 | 
			
		||||
 | 
			
		||||
  if(power < 0.5){
 | 
			
		||||
    color[0] = 2 * power * 255;
 | 
			
		||||
  } else {
 | 
			
		||||
    color[1] = (1.0 - 2 * (power - 0.5)) * 255;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return color;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Get the angle from one point to another */
 | 
			
		||||
function angleToPoint(x1, y1, x2, y2){
 | 
			
		||||
  d = distance(x1, y1, x2, y2);
 | 
			
		||||
  dx = (x2-x1) / d;
 | 
			
		||||
  dy = (y2-y1) / d;
 | 
			
		||||
 | 
			
		||||
  a = Math.acos(dx);
 | 
			
		||||
  a = dy < 0 ? 2 * Math.PI - a : a;
 | 
			
		||||
  return a;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Set the walker to a new location */
 | 
			
		||||
function mouseClicked(){
 | 
			
		||||
  if(mouseX >= 0 && mouseX <= WIDTH && mouseY >= 0 && mouseY <= HEIGHT){
 | 
			
		||||
    walker.x = mouseX;
 | 
			
		||||
    walker.y = mouseY;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										158
									
								
								node_modules/neataptic/docs/js/articles/target-seekingai/graph.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								node_modules/neataptic/docs/js/articles/target-seekingai/graph.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,158 @@
 | 
			
		||||
var colorTable = [
 | 
			
		||||
  '#2124FF', // input
 | 
			
		||||
  '#FF2718', // output
 | 
			
		||||
  '#1F22C1', // logistic sigmoid
 | 
			
		||||
  '#EE8A2A', // tanh
 | 
			
		||||
  '#B17516', // identity
 | 
			
		||||
  '#B1B0AA', // hlim
 | 
			
		||||
  '#2CB11F', // relu
 | 
			
		||||
  '#C5B12C', // softsign
 | 
			
		||||
  '#E685E7', // sinusoid
 | 
			
		||||
  '#257580', // gaussian
 | 
			
		||||
  '#B0484B', // softplus
 | 
			
		||||
  '#4CB148',  // bent_identity
 | 
			
		||||
  '#000000'  // GATE
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
var NODE_RADIUS = 7;
 | 
			
		||||
var REPEL_FORCE = 10;
 | 
			
		||||
var LINK_DISTANCE = 100;
 | 
			
		||||
 | 
			
		||||
var drawGraph = function(graph, panel, activation) {
 | 
			
		||||
  var d3cola = cola.d3adaptor()
 | 
			
		||||
        .avoidOverlaps(true)
 | 
			
		||||
        .size([$('.best').width(), $('.best').height()]);
 | 
			
		||||
 | 
			
		||||
    var svg = d3.select(panel);
 | 
			
		||||
 | 
			
		||||
    d3.selectAll(panel + "> *").remove();
 | 
			
		||||
 | 
			
		||||
    // define arrow markers for graph links
 | 
			
		||||
    svg.append('svg:defs').append('svg:marker')
 | 
			
		||||
        .attr('id', 'end-arrow')
 | 
			
		||||
        .attr('viewBox', '0 -5 10 10')
 | 
			
		||||
        .attr('refX', 6)
 | 
			
		||||
        .attr('markerWidth', 5)
 | 
			
		||||
        .attr('markerHeight', 5)
 | 
			
		||||
        .attr('orient', 'auto')
 | 
			
		||||
        .append('svg:path')
 | 
			
		||||
        .attr('d', 'M0,-5L10,0L0,5')
 | 
			
		||||
        .attr('fill', '#000');
 | 
			
		||||
 | 
			
		||||
    graph.nodes.forEach(function (v) { v.height = v.width = 2 * NODE_RADIUS; });
 | 
			
		||||
 | 
			
		||||
    d3cola
 | 
			
		||||
        .nodes(graph.nodes)
 | 
			
		||||
        .links(graph.links)
 | 
			
		||||
        .symmetricDiffLinkLengths(REPEL_FORCE)
 | 
			
		||||
        .linkDistance(LINK_DISTANCE)
 | 
			
		||||
        .start(10, 15, 20);
 | 
			
		||||
 | 
			
		||||
    var path = svg.selectAll(".link")
 | 
			
		||||
        .data(graph.links)
 | 
			
		||||
        .enter().append('svg:path')
 | 
			
		||||
        .attr('class', 'link')
 | 
			
		||||
        .style("stroke-width", function (d) {
 | 
			
		||||
          if(activation){
 | 
			
		||||
            return 1.5;
 | 
			
		||||
          } else {
 | 
			
		||||
            return 1.5 + Math.sqrt(d.weight * 5);
 | 
			
		||||
          }
 | 
			
		||||
          })
 | 
			
		||||
        .style("stroke", function (d) {
 | 
			
		||||
              if(activation){
 | 
			
		||||
                return activationColor(d.source.activation * d.weight, graph.main.maxActivation * graph.main.maxWeight);
 | 
			
		||||
              } else if(d.gate){
 | 
			
		||||
                if(d.source.activation){
 | 
			
		||||
                  return activationColor(d.source.activation, graph.main.maxActivation);
 | 
			
		||||
                } else{
 | 
			
		||||
                  return 'rgb(255,0,0)';
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
          });
 | 
			
		||||
 | 
			
		||||
    var node = svg.selectAll(".node")
 | 
			
		||||
        .data(graph.nodes)
 | 
			
		||||
        .enter().append("circle")
 | 
			
		||||
        .attr("class", "node")
 | 
			
		||||
        .attr("r", function(d) { return NODE_RADIUS; })
 | 
			
		||||
        .style("fill", function (d) {
 | 
			
		||||
              if(activation){
 | 
			
		||||
                return activationColor(d.activation, graph.main.maxActivation);
 | 
			
		||||
              } else {
 | 
			
		||||
                return colorTable[d.type];
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
          })
 | 
			
		||||
        .call(d3cola.drag);
 | 
			
		||||
 | 
			
		||||
    node.append("title")
 | 
			
		||||
        .text(function (d) { return d.id; });
 | 
			
		||||
 | 
			
		||||
    var label = svg.selectAll(".label")
 | 
			
		||||
          .data(graph.nodes)
 | 
			
		||||
          .enter().append("text")
 | 
			
		||||
          .attr("class", "label")
 | 
			
		||||
          .text(function (d) { return '(' + d.index + ') ' + d.name; })
 | 
			
		||||
          .call(d3cola.drag)
 | 
			
		||||
 | 
			
		||||
    d3cola.on("tick", function () {
 | 
			
		||||
        // draw directed edges with proper padding from node centers
 | 
			
		||||
        path.attr('d', function (d) {
 | 
			
		||||
            var deltaX = d.target.x - d.source.x,
 | 
			
		||||
                deltaY = d.target.y - d.source.y,
 | 
			
		||||
                dist = Math.sqrt(deltaX * deltaX + deltaY * deltaY),
 | 
			
		||||
                normX = deltaX / dist,
 | 
			
		||||
                normY = deltaY / dist;
 | 
			
		||||
 | 
			
		||||
                if(isNaN(normX)) normX = 0;
 | 
			
		||||
                if(isNaN(normY)) normY = 0;
 | 
			
		||||
 | 
			
		||||
                sourcePadding = NODE_RADIUS,
 | 
			
		||||
                targetPadding = NODE_RADIUS + 2,
 | 
			
		||||
                sourceX = d.source.x + (sourcePadding * normX),
 | 
			
		||||
                sourceY = d.source.y + (sourcePadding * normY),
 | 
			
		||||
                targetX = d.target.x - (targetPadding * normX),
 | 
			
		||||
                targetY = d.target.y - (targetPadding * normY);
 | 
			
		||||
 | 
			
		||||
                // Defaults for normal edge.
 | 
			
		||||
                drx = 0,
 | 
			
		||||
                dry = 0,
 | 
			
		||||
                xRotation = 0, // degrees
 | 
			
		||||
                largeArc = 0, // 1 or 0
 | 
			
		||||
                sweep = 1; // 1 or 0
 | 
			
		||||
 | 
			
		||||
                // Self edge.
 | 
			
		||||
                if (d.source.x === d.target.x && d.source.y === d.target.y) {
 | 
			
		||||
                  drx = dist;
 | 
			
		||||
                  dry = dist;
 | 
			
		||||
                  // Fiddle with this angle to get loop oriented.
 | 
			
		||||
                  xRotation = -45;
 | 
			
		||||
 | 
			
		||||
                  // Needs to be 1.
 | 
			
		||||
                  largeArc = 1;
 | 
			
		||||
 | 
			
		||||
                  // Change sweep to change orientation of loop.
 | 
			
		||||
                  //sweep = 0;
 | 
			
		||||
 | 
			
		||||
                  // Make drx and dry different to get an ellipse
 | 
			
		||||
                  // instead of a circle.
 | 
			
		||||
                  drx = 20;
 | 
			
		||||
                  dry = 20;
 | 
			
		||||
 | 
			
		||||
                  // For whatever reason the arc collapses to a point if the beginning
 | 
			
		||||
                  // and ending points of the arc are the same, so kludge it.
 | 
			
		||||
                  targetX = targetX + 1;
 | 
			
		||||
                  targetY = targetY + 1;
 | 
			
		||||
                }
 | 
			
		||||
            return 'M' + sourceX + ',' + sourceY + "A" + drx + "," + dry + " " + xRotation + "," + largeArc + "," + sweep + " " + targetX + ',' + targetY;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        node.attr("cx", function (d) { return d.x; })
 | 
			
		||||
            .attr("cy", function (d) { return d.y; })
 | 
			
		||||
 | 
			
		||||
        label
 | 
			
		||||
          .attr("x", function (d) { return d.x + 10; })
 | 
			
		||||
          .attr("y", function (d) { return d.y - 10; });
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										37
									
								
								node_modules/neataptic/docs/js/articles/target-seekingai/import.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								node_modules/neataptic/docs/js/articles/target-seekingai/import.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
var scripts = [
 | 
			
		||||
  { type: 'script', url: "https://cdn.rawgit.com/wagenaartje/neataptic/a7610e38/dist/neataptic.js"},
 | 
			
		||||
  { type: 'script', url: "https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.10/p5.js"},
 | 
			
		||||
  { type: 'script', url: "../../js/articles/target-seekingai/main.js"},
 | 
			
		||||
  { type: 'script', url: "../../js/articles/target-seekingai/population.js"},
 | 
			
		||||
  { type: 'script', url: "../../js/articles/target-seekingai/player.js"},
 | 
			
		||||
  { type: 'script', url: "../../js/articles/target-seekingai/walker.js"},
 | 
			
		||||
  { type: 'script', url: "../../js/articles/target-seekingai/field.js"}
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
/** https://stackoverflow.com/questions/33330636/load-javascript-dynamically-and-sequentially **/
 | 
			
		||||
function require(list) {
 | 
			
		||||
  function loadScript(link) {
 | 
			
		||||
    return new Promise(function(fulfill, reject) {
 | 
			
		||||
      if(link.type == 'script'){
 | 
			
		||||
        var script = document.createElement("script");
 | 
			
		||||
        script.addEventListener("load", fulfill);
 | 
			
		||||
        script.src = link.url;
 | 
			
		||||
        document.head.appendChild(script);
 | 
			
		||||
      } else if(link.type == 'css'){
 | 
			
		||||
        var stylesheet  = document.createElement('link');
 | 
			
		||||
        stylesheet.rel  = 'stylesheet';
 | 
			
		||||
        stylesheet.type = 'text/css';
 | 
			
		||||
        stylesheet.href = link.url;
 | 
			
		||||
        stylesheet.media = "screen,print";
 | 
			
		||||
        document.head.appendChild(stylesheet);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
  loadScript(list.shift()).then(function() {
 | 
			
		||||
    if (list.length > 0) {
 | 
			
		||||
      require(list);
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
require(scripts);
 | 
			
		||||
							
								
								
									
										108
									
								
								node_modules/neataptic/docs/js/articles/target-seekingai/main.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								node_modules/neataptic/docs/js/articles/target-seekingai/main.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,108 @@
 | 
			
		||||
/** Rename vars */
 | 
			
		||||
var Neat    = neataptic.Neat;
 | 
			
		||||
var Methods = neataptic.Methods;
 | 
			
		||||
var Config  = neataptic.Config;
 | 
			
		||||
var Architect = neataptic.Architect;
 | 
			
		||||
 | 
			
		||||
/** Turn off warnings */
 | 
			
		||||
Config.warnings = false;
 | 
			
		||||
 | 
			
		||||
/** Settings */
 | 
			
		||||
var WIDTH            = $('#field').width();
 | 
			
		||||
var HEIGHT           = 500;
 | 
			
		||||
var MAX_SPEED        = 5;
 | 
			
		||||
var START_X          = WIDTH/2;
 | 
			
		||||
var START_Y          = HEIGHT/2;
 | 
			
		||||
var SCORE_RADIUS     = 100;
 | 
			
		||||
 | 
			
		||||
// GA settings
 | 
			
		||||
var PLAYER_AMOUNT    = Math.round(2.3e-4 * WIDTH * HEIGHT);
 | 
			
		||||
var ITERATIONS       = 10e6; // should be ~250 for real use
 | 
			
		||||
var MUTATION_RATE    = 0.3;
 | 
			
		||||
var ELITISM          = Math.round(0.1 * PLAYER_AMOUNT);
 | 
			
		||||
 | 
			
		||||
// Trained population
 | 
			
		||||
var USE_TRAINED_POP = true;
 | 
			
		||||
 | 
			
		||||
/** Global vars */
 | 
			
		||||
var neat;
 | 
			
		||||
 | 
			
		||||
/** Construct the genetic algorithm */
 | 
			
		||||
function initNeat(){
 | 
			
		||||
  neat = new Neat(
 | 
			
		||||
    6, 1,
 | 
			
		||||
    null,
 | 
			
		||||
    {
 | 
			
		||||
      mutation: [
 | 
			
		||||
        Methods.Mutation.ADD_NODE,
 | 
			
		||||
        Methods.Mutation.SUB_NODE,
 | 
			
		||||
        Methods.Mutation.ADD_CONN,
 | 
			
		||||
        Methods.Mutation.SUB_CONN,
 | 
			
		||||
        Methods.Mutation.MOD_WEIGHT,
 | 
			
		||||
        Methods.Mutation.MOD_BIAS,
 | 
			
		||||
        Methods.Mutation.MOD_ACTIVATION,
 | 
			
		||||
        Methods.Mutation.ADD_GATE,
 | 
			
		||||
        Methods.Mutation.SUB_GATE,
 | 
			
		||||
        Methods.Mutation.ADD_SELF_CONN,
 | 
			
		||||
        Methods.Mutation.SUB_SELF_CONN,
 | 
			
		||||
        Methods.Mutation.ADD_BACK_CONN,
 | 
			
		||||
        Methods.Mutation.SUB_BACK_CONN
 | 
			
		||||
      ],
 | 
			
		||||
      popsize: PLAYER_AMOUNT,
 | 
			
		||||
      mutationRate: MUTATION_RATE,
 | 
			
		||||
      elitism: ELITISM
 | 
			
		||||
    }
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  if(USE_TRAINED_POP){
 | 
			
		||||
    neat.population = population;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Start the evaluation of the current generation */
 | 
			
		||||
function startEvaluation(){
 | 
			
		||||
  players = [];
 | 
			
		||||
  highestScore = 0;
 | 
			
		||||
 | 
			
		||||
  for(var genome in neat.population){
 | 
			
		||||
    genome = neat.population[genome];
 | 
			
		||||
    new Player(genome);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  walker.reset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** End the evaluation of the current generation */
 | 
			
		||||
function endEvaluation(){
 | 
			
		||||
  console.log('Generation:', neat.generation, '- average score:', Math.round(neat.getAverage()));
 | 
			
		||||
  console.log('Fittest score:', Math.round(neat.getFittest().score));
 | 
			
		||||
 | 
			
		||||
  // Networks shouldn't get too big
 | 
			
		||||
  for(var genome in neat.population){
 | 
			
		||||
    genome = neat.population[genome];
 | 
			
		||||
    genome.score -= genome.nodes.length * SCORE_RADIUS / 10;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Sort the population by score
 | 
			
		||||
  neat.sort();
 | 
			
		||||
 | 
			
		||||
  // Init new pop
 | 
			
		||||
  var newPopulation = [];
 | 
			
		||||
 | 
			
		||||
  // Elitism
 | 
			
		||||
  for(var i = 0; i < neat.elitism; i++){
 | 
			
		||||
    newPopulation.push(neat.population[i]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Breed the next individuals
 | 
			
		||||
  for(var i = 0; i < neat.popsize - neat.elitism; i++){
 | 
			
		||||
    newPopulation.push(neat.getOffspring());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Replace the old population with the new population
 | 
			
		||||
  neat.population = newPopulation;
 | 
			
		||||
  neat.mutate();
 | 
			
		||||
 | 
			
		||||
  neat.generation++;
 | 
			
		||||
  startEvaluation();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										91
									
								
								node_modules/neataptic/docs/js/articles/target-seekingai/player.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								node_modules/neataptic/docs/js/articles/target-seekingai/player.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
			
		||||
function Player(genome){
 | 
			
		||||
  this.x = START_X;
 | 
			
		||||
  this.y = START_Y;
 | 
			
		||||
  this.vx = 0;
 | 
			
		||||
  this.vy = 0;
 | 
			
		||||
  this.r = 6;
 | 
			
		||||
 | 
			
		||||
  this.brain = genome;
 | 
			
		||||
  this.brain.score = 0;
 | 
			
		||||
 | 
			
		||||
  players.push(this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Player.prototype = {
 | 
			
		||||
  /** Update the stats */
 | 
			
		||||
  update: function(){
 | 
			
		||||
    var input = this.detect();
 | 
			
		||||
    var output = this.brain.activate(input);
 | 
			
		||||
 | 
			
		||||
    var moveangle = output[0] * 2 * PI;
 | 
			
		||||
 | 
			
		||||
    // Calculate next position
 | 
			
		||||
    this.ax = Math.cos(moveangle);
 | 
			
		||||
    this.ay = Math.sin(moveangle);
 | 
			
		||||
    this.vx += this.ax;
 | 
			
		||||
    this.vy += this.ay;
 | 
			
		||||
 | 
			
		||||
    // Limit speeds to maximum speed
 | 
			
		||||
    this.vx = this.vx > MAX_SPEED ? MAX_SPEED : this.vx < -MAX_SPEED ? -MAX_SPEED : this.vx;
 | 
			
		||||
    this.vy = this.vy > MAX_SPEED ? MAX_SPEED : this.vy < -MAX_SPEED ? -MAX_SPEED : this.vy;
 | 
			
		||||
 | 
			
		||||
    this.x += this.vx;
 | 
			
		||||
    this.y += this.vy;
 | 
			
		||||
 | 
			
		||||
    // Limit position to width and height
 | 
			
		||||
    this.x = this.x >= WIDTH  ? WIDTH  : this.x <= 0 ? 0 : this.x;
 | 
			
		||||
    this.y = this.y >= HEIGHT ? HEIGHT : this.y <= 0 ? 0 : this.y;
 | 
			
		||||
 | 
			
		||||
    if(this.x == 0 || this.x == WIDTH) this.vx = -this.vx;
 | 
			
		||||
    if(this.y == 0 || this.y == HEIGHT) this.vy = -this.vy;
 | 
			
		||||
 | 
			
		||||
    this.score();
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  /** Calculate fitness of this players genome **/
 | 
			
		||||
  score: function(){
 | 
			
		||||
    var dist = distance(this.x, this.y, walker.x, walker.y);
 | 
			
		||||
    if(!isNaN(dist) && dist < SCORE_RADIUS){
 | 
			
		||||
      this.brain.score += SCORE_RADIUS - dist;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Replace highest score to visualise
 | 
			
		||||
    highestScore = this.brain.score > highestScore ? this.brain.score : highestScore;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  /** Display the player on the field, parts borrowed from the CodingTrain */
 | 
			
		||||
  show: function(){
 | 
			
		||||
    // Draw a triangle rotated in the direction of velocity
 | 
			
		||||
    var angle = angleToPoint(this.x, this.y, this.x + this.vx, this.y + this.vy) + HALF_PI;
 | 
			
		||||
    var color = activationColor(this.brain.score, highestScore);
 | 
			
		||||
 | 
			
		||||
    push();
 | 
			
		||||
    translate(this.x, this.y);
 | 
			
		||||
    rotate(angle);
 | 
			
		||||
 | 
			
		||||
    fill(color);
 | 
			
		||||
    beginShape();
 | 
			
		||||
    vertex(0, -this.r * 2);
 | 
			
		||||
    vertex(-this.r, this.r * 2);
 | 
			
		||||
    vertex(this.r, this.r * 2);
 | 
			
		||||
    endShape(CLOSE);
 | 
			
		||||
 | 
			
		||||
    pop();
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  /** Detect and normalize inputs */
 | 
			
		||||
  detect: function(){
 | 
			
		||||
    var dist = Math.sqrt(this.x, this.y, walker.x, walker.y) / Math.sqrt(WIDTH**2 + HEIGHT**2);
 | 
			
		||||
    var targetAngle = angleToPoint(this.x, this.y, walker.x, walker.y) / TWO_PI;
 | 
			
		||||
    var vx = (this.vx + MAX_SPEED) / MAX_SPEED;
 | 
			
		||||
    var vy = (this.vy + MAX_SPEED) / MAX_SPEED;
 | 
			
		||||
    var tvx = (walker.vx + MAX_SPEED) / MAX_SPEED;
 | 
			
		||||
    var tvy = (walker.vy + MAX_SPEED) / MAX_SPEED;
 | 
			
		||||
 | 
			
		||||
    // NaN checking
 | 
			
		||||
    targetAngle = isNaN(targetAngle) ? 0 : targetAngle;
 | 
			
		||||
    dist = isNaN(dist) ? 0 : dist;
 | 
			
		||||
 | 
			
		||||
    return [vx, vy, tvx, tvy, targetAngle, dist];
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										50723
									
								
								node_modules/neataptic/docs/js/articles/target-seekingai/population.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										50723
									
								
								node_modules/neataptic/docs/js/articles/target-seekingai/population.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										68
									
								
								node_modules/neataptic/docs/js/articles/target-seekingai/walker.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								node_modules/neataptic/docs/js/articles/target-seekingai/walker.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
function Walker(){
 | 
			
		||||
  this.x = START_X;
 | 
			
		||||
  this.y = START_Y;
 | 
			
		||||
  this.vx = 0;
 | 
			
		||||
  this.vy = 0;
 | 
			
		||||
 | 
			
		||||
  this.r = 10;
 | 
			
		||||
 | 
			
		||||
  this.angle = Math.random() * Math.PI * 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Walker.prototype = {
 | 
			
		||||
  /** Update the stats */
 | 
			
		||||
  update: function(){
 | 
			
		||||
    if(Math.random() > 0.5){
 | 
			
		||||
      this.angle += Math.random()* 2 -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Calculate next position
 | 
			
		||||
    this.ax = Math.cos(this.angle);
 | 
			
		||||
    this.ay = Math.sin(this.angle);
 | 
			
		||||
    this.vx += this.ax;
 | 
			
		||||
    this.vy += this.ay;
 | 
			
		||||
 | 
			
		||||
    // Limit speeds to maximum speed
 | 
			
		||||
    this.vx = this.vx > MAX_SPEED/2 ? MAX_SPEED/2 : this.vx < -MAX_SPEED/2 ? -MAX_SPEED/2 : this.vx;
 | 
			
		||||
    this.vy = this.vy > MAX_SPEED/2 ? MAX_SPEED/2 : this.vy < -MAX_SPEED/2 ? -MAX_SPEED/2 : this.vy;
 | 
			
		||||
 | 
			
		||||
    this.x += this.vx;
 | 
			
		||||
    this.y += this.vy;
 | 
			
		||||
 | 
			
		||||
    // Limit position to width and height
 | 
			
		||||
    this.x = this.x >= WIDTH  ? WIDTH  : this.x <= 0 ? 0 : this.x;
 | 
			
		||||
    this.y = this.y >= HEIGHT ? HEIGHT : this.y <= 0 ? 0 : this.y;
 | 
			
		||||
 | 
			
		||||
    if(this.x == 0 || this.x == WIDTH){
 | 
			
		||||
      this.vx = -this.vx;
 | 
			
		||||
      this.angle += PI;
 | 
			
		||||
    }
 | 
			
		||||
    if(this.y == 0 || this.y == HEIGHT){
 | 
			
		||||
      this.vy = -this.vy;
 | 
			
		||||
      this.angle += PI;
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  reset: function(){
 | 
			
		||||
    this.x = START_X;
 | 
			
		||||
    this.y = START_Y;
 | 
			
		||||
    this.vx = 0;
 | 
			
		||||
    this.vy = 0;
 | 
			
		||||
 | 
			
		||||
    this.angle = Math.random() * Math.PI * 2;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  /** Display the walker on the field */
 | 
			
		||||
  show: function(){
 | 
			
		||||
    fill(0);
 | 
			
		||||
    ellipse(this.x, this.y, this.r*2);
 | 
			
		||||
 | 
			
		||||
    // Score radius
 | 
			
		||||
    noFill();
 | 
			
		||||
    stroke('lightgreen');
 | 
			
		||||
    strokeWeight(2);
 | 
			
		||||
    ellipse(this.x, this.y, SCORE_RADIUS*2);
 | 
			
		||||
    noStroke();
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
		Reference in New Issue
	
	Block a user