protected override void EvaluateObjective(TuringController controller, int iterations, ref EvaluationInfo evaluation)
        {
            Utility.Debug.DLogHeader("STARTING EVAULATION", true);

            double totalScore = 0;

            // Iteration loop
            for (int i = 0; i < iterations; i++)
            {
                Utility.Debug.DLogHeader($"EVALUATION ITERATION {i}", true);

                Reset();

                double[] enviromentOutput = Environment.InitialObservation;

                // Environment loop
                while (!Environment.IsTerminated)
                {
                    // Activate the controller with the environment output.
                    // The turing controller will handle the turing machine I/O
                    double[] environmentInput = controller.ActivateNeuralNetwork(enviromentOutput);

                    // Activate the environment with the output from the controller (NN)
                    enviromentOutput = Environment.PerformAction(environmentInput);
                }

                totalScore += Environment.NormalizedScore;

                Utility.Debug.DLog($"EVALUATION Total Score: {totalScore}, Iteration Score: {Environment.CurrentScore}", true);
            }

            // Calculate the total normalized score (0-1)
            evaluation.ObjectiveFitness = Math.Max(0d, totalScore / iterations);
        }
        protected override void EvaluateObjective(TuringController controller, int iterations, ref EvaluationInfo evaluation)
        {
            Utility.Debug.DLogHeader("STARTING EVAULATION", true);

            double totalScore = 0;

            evaluation.TapeSizes = new int[iterations];

            // Iteration loop
            for (int i = 0; i < iterations; i++)
            {
                Utility.Debug.DLogHeader($"EVALUATION ITERATION {i}", true);

                Reset();

                double[] enviromentOutput = Environment.InitialObservation;

                // Environment loop
                while (!Environment.IsTerminated)
                {
                    // Activate the controller with the environment output.
                    // The turing controller will handle the turing machine I/O
                    double[] environmentInput = controller.ActivateNeuralNetwork(enviromentOutput);

                    if (_turingMachineProps.MemorySizeHardLimit > 0 &&
                        controller.TuringMachine.TapeSize > _turingMachineProps.MemorySizeHardLimit)
                    {
                        evaluation.ObjectiveFitness = 0d;

                        // Phenome is disqualified, no need to do any further evaluation.
                        return;
                    }

                    // Activate the environment with the output from the controller (NN)
                    enviromentOutput = Environment.PerformAction(environmentInput);
                }

                totalScore += Environment.NormalizedScore;
                evaluation.TapeSizes[i] = controller.TuringMachine.TapeSize;

                Utility.Debug.DLog($"EVALUATION Total Score: {totalScore}, Iteration Score: {Environment.CurrentScore}", true);
            }

            // Calculate the total normalized score (0-1)
            evaluation.ObjectiveFitness = Math.Max(0d, totalScore / iterations);
        }
        protected override void EvaluateRecord(TuringController controller, int iterations, ref EvaluationInfo evaluation)
        {
            // Iteration loop
            for (int i = 0; i < iterations; i++)
            {
                Reset();

                // Only record first iteration, as subsequent ones will overwrite
                if (i == 0)
                {
                    Recorder = new Recorder();
                    Recorder.Start();

                    controller.TuringMachine.RecordTimeSteps = true;
                    Environment.RecordTimeSteps = true;

                    Recorder.Record(Environment.InitialTimeStep, controller.TuringMachine.InitialTimeStep);
                }

                double[] enviromentOutput = Environment.InitialObservation;

                // Environment loop
                while (!Environment.IsTerminated)
                {
                    double[] environmentInput = controller.ActivateNeuralNetwork(enviromentOutput);

                    enviromentOutput = Environment.PerformAction(environmentInput);

                    if (i == 0)
                    {
                        // Record the state of the environment and turing machine
                        Recorder.Record(Environment.PreviousTimeStep, controller.TuringMachine.PreviousTimeStep);
                    }
                }

                evaluation.ObjectiveFitnessIt[i] = Environment.NormalizedScore;

                if (i == 0)
                {
                    // Record the final state of the turing machine tape
                    Recorder.FinalTuringTape = Controller.TuringMachine.TapeValues;
                }
            }
        }
        protected override void EvaluateNovelty(TuringController controller, ref EvaluationInfo evaluation)
        {
            Reset();
            double[] enviromentOutput = Environment.InitialObservation;

            // Environment loop
            while (!Environment.IsTerminated)
            {
                // Activate the controller with the environment output.
                // The turing controller will handle the turing machine I/O
                double[] environmentInput = controller.ActivateNeuralNetwork(enviromentOutput);

                // Activate the environment with the output from the controller (NN)
                enviromentOutput = Environment.PerformAction(environmentInput);
            }

            evaluation.NoveltyVectors  = NoveltySearchInfo.NoveltyVectors;
            evaluation.MinimumCriteria = NoveltySearchInfo.MinimumCriteria;
        }