Eater Experiment
Each creature is driven by a random neural architecture.
The more food eaten, the higher the chance to mate.
After 500 ticks, a new population is generated by genetically crossbreeding the neural architectures of the most successful.
import React, { useRef } from 'react';import _ from 'lodash';import { Layers, Vector3 } from 'three';import { NodeGene, NodeType } from '@alenaksu/neatjs';import {Box,OrbitControls,PerspectiveCamera,Sphere,} from '@react-three/drei';import { Canvas } from '@react-three/fiber';import { Teleporter } from '@react-ecs/boids';import {Entity,rad,useAnimationFrame,useECS,} from '@react-ecs/core';import {CollisionSystem,Eater,Evolver,EvolverSystem,FollowingSystem,RaycastingSystem,Rewarding,RewardSystem,SensingSystem,ThrustingSystem,TurningSystem,} from '@react-ecs/neat'import { ThreeView } from '@react-ecs/three';import { Indexed, Quadtree } from '../hooks/useQuadtree';import { MeshResetSystem } from '../systems/MeshResetSystem';import { SeenSystem } from '../systems/SeenSystem';const Scenery = ({ size }) => {const lightRef = useRef()// useHelper(lightRef, DirectionalLightHelper, 'royalblue', 1)// useHelper(lightRef, DirectionalLightShadow,)return (<group><directionalLightref={lightRef}position={[10, 10, 10]}castShadowshadow-mapSize-width={2048}shadow-mapSize-height={2048}shadow-camera-far={100}shadow-camera-left={-100}shadow-camera-right={100}shadow-camera-top={100}shadow-camera-bottom={-100}/><OrbitControlsminDistance={30}maxPolarAngle={rad(60)}minPolarAngle={rad(20)} /><Box scale={[size * 2, 1, size * 2]} position={[0, -1, 0]} receiveShadow><meshPhongMaterial color='white' /></Box></group>);}export const BasicEaterScene = () => {const ECS = useECS()useAnimationFrame(ECS.update)const size = 100;const randomPosition = () => {return new Vector3(Math.random() * size * 2 - size, 0, Math.random() * size * 2 - size);}// enable camera for sim and debug layersconst layers = new Layers();layers.enable(0)layers.enable(1)return (<Canvas shadows><PerspectiveCamera makeDefault layers={layers} /><Scenery size={size} /><ECS.Provider><Quadtree size={size}>{/* generate food on the board */}{_.times(600, (i) => (<Entity key={i}><Indexed /><Rewarding /><ThreeView><Sphere name="food" position={randomPosition()}><meshPhongMaterial color='blue' /></Sphere></ThreeView></Entity>))}{/* systems to run before network activation */}<MeshResetSystem /><RaycastingSystem />{/* <SmellingSystem /> */}<SensingSystem />{/* evolver for the creatures */}<EvolverpopulationSize={30}feedForwardOnly={false}fitnessThreshold={45}survivalThreshold={0.95}ageSignificance={0}dropoffAge={999}addConnectionTries={20}adjustCompatibilityThreshold={false}compatibilityModifier={0.3}compatibilityModifierTarget={10}compatibilityThreshold={3.0}interspeciesMateRate={0.001}disjointCoefficient={1.0}excessCoefficient={1.0}weightDifferenceCoefficient={1}genomeWeightPerturbated={0.9}mutateAddConnectionProbability={0.05}mutateAddNodeProbability={0.03}mutateConnectionWeightsProbability={1}mutateOnlyProbability={.5}mutateToggleEnableProbability={0}mutationPower={.05}reEnableGeneProbability={0.05}inputs={[new NodeGene(NodeType.Input, 'hitDistance0'),new NodeGene(NodeType.Input, 'hitGood0'),new NodeGene(NodeType.Input, 'hitBad0'),new NodeGene(NodeType.Input, 'hitDistance1'),new NodeGene(NodeType.Input, 'hitGood1'),new NodeGene(NodeType.Input, 'hitBad1'),new NodeGene(NodeType.Input, 'hitDistance2'),new NodeGene(NodeType.Input, 'hitGood2'),new NodeGene(NodeType.Input, 'hitBad2'),new NodeGene(NodeType.Input, 'hitDistance3'),new NodeGene(NodeType.Input, 'hitGood3'),new NodeGene(NodeType.Input, 'hitBad3'),new NodeGene(NodeType.Input, 'hitDistance4'),new NodeGene(NodeType.Input, 'hitGood4'),new NodeGene(NodeType.Input, 'hitBad4'),new NodeGene(NodeType.Input, 'hitDistance5'),new NodeGene(NodeType.Input, 'hitGood5'),new NodeGene(NodeType.Input, 'hitBad5'),new NodeGene(NodeType.Input, 'hitDistance6'),new NodeGene(NodeType.Input, 'hitGood6'),new NodeGene(NodeType.Input, 'hitBad6'),]}outputs={[new NodeGene(NodeType.Output, 'turnAmount'),new NodeGene(NodeType.Output, 'thrustAmount'),]}><EvolverSystem ticks={250} />{(o, i) => {return <Eaterkey={Math.random()}organism={o}rotation={[0, Math.random() * Math.PI, 0]}position={randomPosition()} />}}</Evolver>{/* systems to run after network activation */}<TurningSystem multiplier={3} /><ThrustingSystem multiplier={60} /><CollisionSystem /><RewardSystem /><Teleporter size={size} /><FollowingSystem /><SeenSystem /></Quadtree></ECS.Provider></Canvas>)}