Index: framspy/evolalg/base/experiment_abc.py
===================================================================
--- framspy/evolalg/base/experiment_abc.py	(revision 1283)
+++ framspy/evolalg/base/experiment_abc.py	(revision 1289)
@@ -23,7 +23,7 @@
     current_generation = 0
     time_elapsed = 0
-    
-
-    def __init__(self, popsize, hof_size, save_only_best=True) -> None:
+
+
+    def __init__(self, popsize, hof_size, save_only_best) -> None:
         self.hof = HallOfFame(hof_size)
         self.popsize = popsize
@@ -126,8 +126,6 @@
         # instead of single best, could add all individuals in population here, but then the outcome would depend on the order of adding
         self.hof.add(best)
-        self.stats.append(
-            best.rawfitness if self.save_only_best else best)
-        print("%d\t%d\t%g\t%g" % (generation, len(
-            all_individuals), worst.rawfitness, best.rawfitness))
+        self.stats.append(best.rawfitness if self.save_only_best else best)
+        print("%d\t%d\t%g\t%g" % (generation, len(all_individuals), worst.rawfitness, best.rawfitness))
 
     def initialize_evolution(self, initialgenotype):
@@ -149,7 +147,5 @@
             # saved generation has been completed, start with the next one
             self.current_generation += 1
-            print("...Resuming from saved state: population size = %d, hof size = %d, stats size = %d, archive size = %d, generation = %d/%d" % (len(self.population_structures.population), len(self.hof),
-                                                                                                                                                 len(self.stats),  (len(self.population_structures.archive)), self.current_generation, generations))  # self.current_generation (and g) are 0-based, parsed_args.generations is 1-based
-
+            print("...Resuming from saved state: population size = %d, hof size = %d, stats size = %d, archive size = %d, generation = %d/%d" % (len(self.population_structures.population), len(self.hof), len(self.stats), (len(self.population_structures.archive)), self.current_generation, generations))  # self.current_generation (and g) are 0-based, parsed_args.generations is 1-based
         else:
             self.initialize_evolution(initialgenotype)
@@ -192,20 +188,22 @@
     def get_args_for_parser():
         parser = argparse.ArgumentParser()
-        parser.add_argument('-popsize',type= int, default= 50,
+        parser.add_argument('-popsize', type=int, default=50,
                             help="Population size, default: 50.")
-        parser.add_argument('-generations',type= int, default= 5,
+        parser.add_argument('-generations', type=int, default=5,
                                 help="Number of generations, default: 5.")
-        parser.add_argument('-tournament',type= int, default= 5,
+        parser.add_argument('-tournament', type=int, default=5,
                             help="Tournament size, default: 5.")
-        parser.add_argument('-pmut',type= float, default= 0.7,
+        parser.add_argument('-pmut', type=float, default=0.7,
                         help="Probability of mutation, default: 0.7")
-        parser.add_argument('-pxov',type= float, default= 0.2,
+        parser.add_argument('-pxov', type=float, default=0.2,
                         help="Probability of crossover, default: 0.2")
-        parser.add_argument('-hof_size',type= int, default= 10,
+        parser.add_argument('-hof_size', type=int, default=10,
                             help="Number of genotypes in Hall of Fame. Default: 10.")
-        parser.add_argument('-hof_savefile',type= str, required= False,
+        parser.add_argument('-hof_savefile', type=str, required=False,
                                 help= 'If set, Hall of Fame will be saved in Framsticks file format (recommended extension *.gen. This also activates saving state (checpoint} file and auto-resuming from the saved state, if this file exists.')
-        parser.add_argument('-save_only_best',type= bool, default= True, required= False,
+        parser.add_argument('-save_only_best', type=bool, default=True, required=False,
                             help="")
+        parser.add_argument('-fitness_set_negative_to_zero', action='store_true',
+                            help="This flag forces fitness to become max(0,fitness), so it is always made non-negative. Using niching or novelty techniques without this flag (thus allowing negative fitness values) requires verifying/improving fitness diversification formulas to work as intended for both positive and negative fitness values.")
         
         return parser
Index: framspy/evolalg/base/experiment_niching_abc.py
===================================================================
--- framspy/evolalg/base/experiment_niching_abc.py	(revision 1283)
+++ framspy/evolalg/base/experiment_niching_abc.py	(revision 1289)
@@ -24,5 +24,5 @@
     archive_size: int = None
 
-    def __init__(self, fit, normalize, popsize, hof_size, save_only_best=True, knn_niching=5, knn_nslc=10, archive_size=0) -> None:
+    def __init__(self, fit, normalize, popsize, hof_size, save_only_best, knn_niching, knn_nslc, archive_size) -> None:
         ExperimentABC.__init__(self,popsize=popsize, hof_size=hof_size, save_only_best=save_only_best)
         self.fit = fit
@@ -51,5 +51,5 @@
             divide_by = np.sum(dissim_matrix)
         else:
-            raise Exception(f"Wrong normalization method,", self.normalize)
+            raise ValueError("Wrong normalization method: '%s'" % self.normalize)
         if divide_by != 0:
             return dissim_matrix/divide_by
@@ -65,4 +65,7 @@
             dissim_list = np.mean(np.partition(
                 self.normalize_dissim(dissim_matrix), self.knn_niching)[:, :self.knn_niching], axis=1)
+
+        if Individual.fitness_set_negative_to_zero is False and ("niching" in self.fit or "novelty" in self.fit):
+        	raise ValueError("Negative fitness values not tested in combination with niching or novelty. When using these techniques, verify formulas or consider using the flag -fitness_set_negative_to_zero") # once the formulas are verified/improved, the command-line flag and this conditional check can be removed.
 
         if "niching" in self.fit:
@@ -73,6 +76,5 @@
                 i.fitness = d
         else:
-            raise Exception("Wrong fit type: ", self.fit,
-                            f" choose the correct one or implement a new behavior.")
+            raise ValueError("Unsupported fit type: '%s'. Use the correct type or implement a new behavior." % self.fit)
         population_structures.update_archive(dissim_matrix, population_archive)
 
Index: framspy/evolalg/run_frams_islands.py
===================================================================
--- framspy/evolalg/run_frams_islands.py	(revision 1283)
+++ framspy/evolalg/run_frams_islands.py	(revision 1289)
@@ -1,4 +1,4 @@
 from FramsticksLib import FramsticksLib
-
+from .structures.individual import Individual
 from .frams_base.experiment_frams_islands import ExperimentFramsIslands
 
@@ -8,5 +8,6 @@
     # must be set before FramsticksLib() constructor call
     FramsticksLib.DETERMINISTIC = False
-    parsed_args =ExperimentFramsIslands.get_args_for_parser().parse_args()
+    parsed_args = ExperimentFramsIslands.get_args_for_parser().parse_args()
+    Individual.fitness_set_negative_to_zero = parsed_args.fitness_set_negative_to_zero # setting the "static" field once
     print("Argument values:", ", ".join(
         ['%s=%s' % (arg, getattr(parsed_args, arg)) for arg in vars(parsed_args)]))
@@ -22,5 +23,4 @@
                   }
 
-    print('Best individuals:')
     experiment = ExperimentFramsIslands(frams_lib=framsLib,
                                         optimization_criteria=opt_criteria,
Index: framspy/evolalg/run_frams_niching.py
===================================================================
--- framspy/evolalg/run_frams_niching.py	(revision 1283)
+++ framspy/evolalg/run_frams_niching.py	(revision 1289)
@@ -1,3 +1,4 @@
 from FramsticksLib import FramsticksLib
+from .structures.individual import Individual
 
 from .frams_base.experiment_frams_niching import ExperimentFramsNiching
@@ -9,4 +10,5 @@
     FramsticksLib.DETERMINISTIC = False
     parsed_args = ExperimentFramsNiching.get_args_for_parser().parse_args()
+    Individual.fitness_set_negative_to_zero = parsed_args.fitness_set_negative_to_zero # setting the "static" field once
     print("Argument values:", ", ".join(
         ['%s=%s' % (arg, getattr(parsed_args, arg)) for arg in vars(parsed_args)]))
@@ -22,5 +24,4 @@
                   }
 
-    print('Best individuals:')
     experiment = ExperimentFramsNiching(frams_lib=framsLib,
                                         optimization_criteria=opt_criteria,
Index: framspy/evolalg/run_numerical_example.py
===================================================================
--- framspy/evolalg/run_numerical_example.py	(revision 1283)
+++ framspy/evolalg/run_numerical_example.py	(revision 1289)
@@ -1,12 +1,14 @@
+import numpy as np
 from .numerical_example.numerical_example import ExperimentNumerical
+from .structures.individual import Individual
 
 
 def main():
     parsed_args = ExperimentNumerical.get_args_for_parser().parse_args()
+    Individual.fitness_set_negative_to_zero = parsed_args.fitness_set_negative_to_zero # setting the "static" field once
     print("Argument values:", ", ".join(
         ['%s=%s' % (arg, getattr(parsed_args, arg)) for arg in vars(parsed_args)]))
 
-    initialgenotype = [100, 100, 100, 100]
-    print('Best individuals:')
+    initialgenotype = np.array([100, 100, 100, 100])
     experiment = ExperimentNumerical(
         hof_size=parsed_args.hof_size,
@@ -20,7 +22,7 @@
                                    pxov=parsed_args.pxov,
                                    tournament_size=parsed_args.tournament)
-    print(len(hof))
+    print('Best individuals:')
     for ind in hof:
-        print(ind.genotype, ind.rawfitness)
+        print(ind.rawfitness, '\t-->\t', ind.genotype)
 
 
Index: framspy/evolalg/run_numerical_islands_example.py
===================================================================
--- framspy/evolalg/run_numerical_islands_example.py	(revision 1283)
+++ framspy/evolalg/run_numerical_islands_example.py	(revision 1289)
@@ -1,13 +1,14 @@
-from .numerical_example.numerical_islands_example import \
-    ExperimentNumericalIslands
+import numpy as np
+from .numerical_example.numerical_islands_example import ExperimentNumericalIslands
+from .structures.individual import Individual
 
 
 def main():
     parsed_args = ExperimentNumericalIslands.get_args_for_parser().parse_args()
+    Individual.fitness_set_negative_to_zero = parsed_args.fitness_set_negative_to_zero # setting the "static" field once
     print("Argument values:", ", ".join(
         ['%s=%s' % (arg, getattr(parsed_args, arg)) for arg in vars(parsed_args)]))
 
-    initialgenotype = [100, 100, 100, 100]
-    print('Best individuals:')
+    initialgenotype = np.array([100, 100, 100, 100])
     experiment = ExperimentNumericalIslands(
         hof_size=parsed_args.hof_size,
@@ -23,7 +24,7 @@
                                    pxov=parsed_args.pxov,
                                    tournament_size=parsed_args.tournament)
-    print(len(hof))
+    print('Best individuals:')
     for ind in hof:
-        print(ind.genotype, ind.rawfitness)
+        print(ind.rawfitness, '\t-->\t', ind.genotype)
 
 
Index: framspy/evolalg/structures/individual.py
===================================================================
--- framspy/evolalg/structures/individual.py	(revision 1283)
+++ framspy/evolalg/structures/individual.py	(revision 1289)
@@ -3,5 +3,5 @@
 
 class Individual:
-    only_positive_fitness = True # Note: when using diversification techniques (e.g. niching), setting this to False and allowing negative fitness values requires verifying/improving diversification formulas. Dividing fitness by similarity (or multiplying by diversity) may have undesired consequences when fitness can be both positive and negative (e.g. low similarity may make positive fitness values higher and negative fitness values lower, while the intention would be to improve fitness for low similarity).
+    fitness_set_negative_to_zero = False # "static" field. Note: when using diversification techniques (e.g. niching or novelty), leaving this as False and allowing negative fitness values requires verifying/improving diversification formulas. Dividing fitness by similarity (or multiplying by diversity) may have undesired consequences when fitness can be both positive and negative (e.g. low similarity may make positive fitness values higher and negative fitness values lower, while the intention would be to improve fitness for low similarity).
 
     def __init__(self):
@@ -29,7 +29,6 @@
         fitness = evaluate(genotype)
         if fitness is not BAD_FITNESS:  # BAD_FITNESS indicates that the genotype was not valid or some other problem occurred during evaluation
-            if self.only_positive_fitness:
-                if fitness < 0:
-                    fitness = 0
+            if Individual.fitness_set_negative_to_zero and fitness < 0:
+                fitness = 0
         self.fitness = self.rawfitness = fitness
 
Index: framspy/run-evolalg-examples.cmd
===================================================================
--- framspy/run-evolalg-examples.cmd	(revision 1283)
+++ framspy/run-evolalg-examples.cmd	(revision 1289)
@@ -9,5 +9,5 @@
 
 rem evolution with niching
-python -m evolalg.run_frams_niching  -path %DIR_WITH_FRAMS_LIBRARY%  -sim "eval-allcriteria.sim;deterministic.sim;sample-period-longest.sim" -opt velocity -genformat 0 -dissim 1 -fit knn_niching -archive 50 -max_numparts 15 -max_numneurons 15 -max_numjoints 30 -max_numconnections 30  -max_numgenochars 10000 -popsize 50 -generations 10 -normalize none -hof_savefile HoF-niching.gen 
+python -m evolalg.run_frams_niching  -path %DIR_WITH_FRAMS_LIBRARY%  -sim "eval-allcriteria.sim;deterministic.sim;sample-period-longest.sim" -opt velocity -genformat 0 -dissim 1 -fit knn_niching -archive 50 -fitness_set_negative_to_zero  -max_numparts 15 -max_numneurons 15 -max_numjoints 30 -max_numconnections 30  -max_numgenochars 10000 -popsize 50 -generations 10 -normalize none -hof_savefile HoF-niching.gen 
 
 rem a generic island model example
