Script #1 [Main Script] "-- Script Parent --
local ScriptsFolder = script.Parent

-- Environment Folder and Contents --
local EnvironmentsFolder = game.Workspace.Environment
local Hazards = EnvironmentsFolder.Hazards
local Rewards = EnvironmentsFolder.Rewards
local Robot = EnvironmentsFolder.Robot"

Script #2 [Robot Script] "-- Game Services --
local RunService = game:GetService("RunService")

-- Script Variables -- 
local visionSleep = 2
local currentRod = 0
local rayCastInUse = false

-- Script Parent --
local ScriptsFolder = script.Parent

-- Robot --
local Robot = game.Workspace.Environment.Robot.Organism

-- Robot Head and Properties --
local RH = Robot.Head
local RHLV = RH.CFrame.LookVector

--print(RHLV)

-- Vision Ray Cast Array Table -- 
local visionArrayTable = {
	-- rod# = { Color3.new( R, G, B ) }
	
}

local function resetCR()
	currentRod = 0
end

-- Ray Cast Function --
local function rayCast(Origin, Direction, currentRod)
	local ray = Ray.new(RH.Position, RHLV * 100)
	local part, position = workspace:FindPartOnRay(ray, Robot)
	local rod_limit = 450
	if currentRod == rod_limit then
		--print(visionArrayTable)
		resetCR()
		table.clear(visionArrayTable)
		rayCastInUse = false
	end
	if part then
		table.insert(visionArrayTable, {rod = "rod"..currentRod, part.Color.R} )
		table.insert(visionArrayTable, {rod = "rod"..currentRod, part.Color.B} )
		table.insert(visionArrayTable, {rod = "rod"..currentRod, part.Color.G} )
	else
		return
	end
end

-- Heartbeat function --
RunService.Heartbeat:Connect(function()
	print(rayCastInUse)
	if visionSleep <= 0  and rayCastInUse ==  false then
		rayCastInUse = true
		visionSleep = 10
		-- ray cast variables 
		local Origin = RH.Position
		local Direction = nil
		
		for x = -15, 15 do
			for y = -7,7 do
				currentRod = currentRod + 1
				Direction  = Vector3.new(RHLV.X + x, RHLV.Y + y, RHLV.Z)
				rayCast(Origin, Direction, currentRod)
			end
		end
		--rayCast()
	else if visionSleep > 0 then
			visionSleep = visionSleep - 1
		end
	end
end)"

Script #3 [Create Neural Network] "--==<< Temp Neural Net >>==--

local InputNeuronNodeModule = require(game.ServerScriptService["Neuron Types"].InputNeuronNode)
local OutputNeuronNodeModule = require(game.ServerScriptService["Neuron Types"].OutputNeuronNode)
local NeuronNodeModule = require(game.ServerScriptService["Neuron Types"].NeuronNode)
local PrimordialNeuronNodeModule = require(game.ServerScriptService["Neuron Types"].PrimordialNeuron)
local NeuralNetwork = require(game.ServerScriptService.NeuralNetwork)

-- Initialize Input Neurons
for i = 1, 1350 do
	local neuronData = InputNeuronNodeModule.new(
		nil, nil, 0, false, nil, false, nil
	)
	table.insert(NeuralNetwork.NeuralNetTable, {Neuron = "InputNeuron"..i, Data = neuronData})
end

-- Initialize Output Neurons
for i = 1, 6 do
	local neuronData = OutputNeuronNodeModule.new(
		nil, nil, 0, false, nil, false, nil
	)
	table.insert(NeuralNetwork.NeuralNetTable, {Neuron = "OutputNeuron"..i, Data = neuronData})

	if i == 6 then
		NeuralNetwork.printTable()
		NeuralNetwork.reorganize()
	end
end "

Script #4 [Input Neuron] "local InputNeuronNode = {}

InputNeuronNode._index = InputNeuronNode

function InputNeuronNode.new(Position, Age, SignalStrength, Reproduction, Type, Activated, OutputTable)

	local self = setmetatable({}, InputNeuronNode)

	if Position == nil then
		self.position = Vector2.new(0,0)
	else 
		self.position = Position
	end

	if Age == nil then 
		self.age = 0
	else
		self.age = Age + 1
	end

	self.signalStrength = 0

	self.reproduction = Reproduction

	self.activated = false

	self.OutputTable = {}

	self.Type = "InputNeuron"

	return self

end

return InputNeuronNode "

Script #5 [Neuron Node] "local NeuronNode = {}

NeuronNode._index = NeuronNode

function NeuronNode.new(Position, Age, SignalStrength, SignalThreshold, Stability, Reproduction, Type, Activated, InputTable, OutputTable)
	
	local self = setmetatable({}, NeuronNode)
	
	if Position == nil then
		self.position = Vector2.new(0,0)
	else 
		self.position = Position
	end
	
	if Age == nil then 
		self.age = 0
	else
		self.age = Age + 1
	end
	
	if SignalStrength == nil then
		self.signalStrength = 0.001 * (math.random(1, 100))
	else
		self.signalStrength = SignalStrength
	end
	
	if SignalThreshold == nil then
		self.signalThreshold = 0.001 * (math.random(1, 100))
	else
		self.signalThreshold = SignalThreshold
	end
	
	if Stability == nil then
		self.stability = 0.001 * (math.random(1, 100))
	else
		self.stability = Stability
	end
	
	self.reproduction = Reproduction
	
	self.activated = false
	
	self.InputTable = {}
	
	self.OutputTable = {}
	
	self.Type = "Neuron"
	
	return self
	
end

return NeuronNode "

Script #6 [Output Neuron Node] "local InputNeuronNode = {}

InputNeuronNode._index = InputNeuronNode

function InputNeuronNode.new(Position, Age, SignalStrength, Reproduction, Type, Activated, InputTable)

	local self = setmetatable({}, InputNeuronNode)

	if Position == nil then
		self.position = Vector2.new(0,0)
	else 
		self.position = Position
	end

	if Age == nil then 
		self.age = 0
	else
		self.age = Age + 1
	end

	self.signalStrength = 0

	self.reproduction = Reproduction

	self.activated = false

	self.OutputTable = {}

	self.Type = "OutputNeuron"

	return self

end

return InputNeuronNode "

Script #7 [Primordial Neuron] "local NeuronNode = {}

NeuronNode._index = NeuronNode

function NeuronNode.new(Position, Age, SignalStrength, SignalThreshold, Stability, Reproduction, Type, Activated, InputTable, OutputTable)
	
	local self = setmetatable({}, NeuronNode)
	
	if Position == nil then
		self.position = Vector2.new(0,0)
	else 
		self.position = Position
	end
	
	if Age == nil then 
		self.age = 0
	else
		self.age = Age + 1
	end
	
	if SignalStrength == nil then
		self.signalStrength = 0.001 * (math.random(1, 100))
	else
		self.signalStrength = SignalStrength
	end
	
	if SignalThreshold == nil then
		self.signalThreshold = 0.001 * (math.random(1, 100))
	else
		self.signalThreshold = SignalThreshold
	end
	
	if Stability == nil then
		self.stability = 0.001 * (math.random(1, 100))
	else
		self.stability = Stability
	end
	
	self.reproduction = Reproduction
	
	self.activated = false
	
	self.InputTable = {}
	
	self.OutputTable = {}
	
	self.Type = "PrimordialNeuron"
	
	return self
	
end

return NeuronNode "

Script #8 [Neural Network] "local RS = game:GetService("RunService") 

local organizeInUse = false

local NetworkModule = {}

NetworkModule.NeuralNetTable = {}

function NetworkModule.printTable()
	print(NetworkModule.NeuralNetTable)
end


function NetworkModule.reorganize()
	organizeInUse = true
	for i, neuron1 in ipairs(NetworkModule.NeuralNetTable) do
		wait()
		for j, neuron2 in ipairs(NetworkModule.NeuralNetTable) do
			-- Don't compare a neuron with itself
			if i ~= j then
				-- Check if two neurons share the same position
				if neuron1.Data.position == neuron2.Data.position then
					-- Resolve overlap by moving one of the neurons
					NetworkModule.moveNeuron(neuron2)
				end
			end
		end
	end
	organizeInUse = false
	--print(NetworkModule.NeuralNetTable)
end 

function NetworkModule.moveNeuron(neuron2)
	local newPosition = Vector2.new(
		neuron2.Data.position.X + math.random(-10, 10),  -- Move it in a random direction
		neuron2.Data.position.Y + math.random(-10, 10)
	)
	neuron2.Data.position = newPosition
end


RS.Heartbeat:Connect(function()
	if organizeInUse == true then
		return
	else
		NetworkModule.reorganize()
	end
end)

return NetworkModule