Index: cpp/frams/Makefile-GDK-files
===================================================================
--- cpp/frams/Makefile-GDK-files	(revision 144)
+++ cpp/frams/Makefile-GDK-files	(revision 145)
@@ -4,17 +4,17 @@
 ALL_DIRS={common,frams,frams/canvas,frams/config,frams/errmgr,frams/genetics,frams/genetics/f0,frams/genetics/f1,frams/genetics/f2,frams/genetics/f3,frams/genetics/f4,frams/genetics/f5,frams/genetics/f6,frams/genetics/f7,frams/genetics/f8,frams/genetics/f9,frams/genetics/fF,frams/model,frams/neuro,frams/neuro/impl,frams/param,frams/test,frams/util,frams/vm/classes,frams/virtfile,frams/_demos}
 
-GENOCONV_GDK_OBJS=frams/genetics/f1/conv_f1.o frams/genetics/f9/conv_f9.o frams/genetics/fF/conv_fF.o
+GENOCONV_GDK_OBJS=frams/genetics/defgenoconv.o frams/genetics/f1/conv_f1.o frams/genetics/f9/conv_f9.o frams/genetics/fF/conv_fF.o frams/genetics/fF/fF_genotype.o
 
 GENMAN_COMMON_OBJS=frams/genetics/genman.o frams/param/mutableparam.o frams/param/mutparamlist.o frams/neuro/geneticneuroparam.o frams/neuro/neurolibparam.o frams/vm/classes/genoobj.o frams/model/autoname.o
 GENMAN_GDK_OBJS=$(GENMAN_COMMON_OBJS) frams/genetics/f9/oper_f9.o frams/genetics/fF/oper_fF.o
 
-GDK_OBJS=frams/util/list.o frams/util/advlist.o frams/param/param.o frams/util/sstring.o frams/util/sstringutils.o frams/util/3d.o frams/vm/classes/3dobject.o frams/model/model.o frams/model/modelparts.o frams/neuro/neurolibrary.o frams/genetics/geno.o frams/genetics/genoconv.o frams/util/extvalue.o frams/vm/classes/collectionobj.o frams/util/hashtable.o common/framsg.o frams/util/callbacks.o frams/param/syntparam.o frams/util/multirange.o frams/util/multimap.o frams/param/paramtabobj.o frams/genetics/defgenoconv.o frams/errmgr/errmanager.o frams/param/paramobj.o frams/genetics/oper_fx.o common/nonstd_math.o frams/errmgr/stderrors.o common/Convert.o frams/util/rndutil.o
+GDK_OBJS=frams/util/list.o frams/util/advlist.o frams/param/param.o frams/util/sstring.o frams/util/sstringutils.o frams/util/3d.o frams/vm/classes/3dobject.o frams/model/model.o frams/model/modelparts.o frams/neuro/neurolibrary.o frams/genetics/geno.o frams/genetics/genoconv.o frams/util/extvalue.o frams/vm/classes/collectionobj.o frams/util/hashtable.o common/framsg.o frams/util/callbacks.o frams/param/syntparam.o frams/util/multirange.o frams/util/multimap.o frams/param/paramtabobj.o frams/errmgr/errmanager.o frams/param/paramobj.o frams/genetics/oper_fx.o common/nonstd_math.o frams/errmgr/stderrors.o common/Convert.o frams/util/rndutil.o
 
 
 #### gdk_tests
 
-GDK_TEST_OBJS= frams/_demos/gdk_test.o frams/errmgr/stdouterr.o frams/virtfile/virtfile.o  $(GDK_OBJS) $(GENOCONV_GDK_OBJS)
+GDK_TEST_OBJS= frams/_demos/gdk_test.o frams/errmgr/stdouterr.o frams/virtfile/virtfile.o  $(GDK_OBJS) $(GENOCONV_GDK_OBJS) $(GENMAN_GDK_OBJS)
 
-MULTILINE_F0_OBJS=frams/_demos/multiline_f0_test.o frams/virtfile/stringfile.o frams/virtfile/virtfile.o frams/errmgr/stdouterr.o $(GDK_OBJS) $(GENOCONV_GDK_OBJS)
+MULTILINE_F0_OBJS=frams/_demos/multiline_f0_test.o frams/virtfile/stringfile.o frams/virtfile/virtfile.o frams/errmgr/stdouterr.o $(GDK_OBJS) $(GENOCONV_GDK_OBJS) $(GENMAN_GDK_OBJS)
 
 F0_VARIANTS_OBJS=frams/_demos/f0_variants_test.o frams/virtfile/stringfile.o frams/virtfile/virtfile.o frams/errmgr/stdouterr.o   $(GDK_OBJS) $(GENOCONV_GDK_OBJS)
@@ -28,7 +28,7 @@
 NEURO_TEST_OBJS= frams/_demos/neuro_test.o frams/errmgr/stdouterr.o frams/virtfile/virtfile.o \
 	frams/neuro/neuroimpl.o frams/neuro/neurofactory.o frams/neuro/impl/neuroimpl-simple.o frams/neuro/impl/neuroimpl-channels.o \
-	frams/neuro/impl/neuroimpl-fuzzy.o frams/neuro/impl/neuroimpl-fuzzy-f0.o  $(GDK_OBJS) $(GENOCONV_GDK_OBJS)
+	frams/neuro/impl/neuroimpl-fuzzy.o frams/neuro/impl/neuroimpl-fuzzy-f0.o  $(GDK_OBJS) $(GENOCONV_GDK_OBJS) $(GENMAN_GDK_OBJS)
 
-FULL_PROPS_OBJS= frams/_demos/full_props.o frams/errmgr/stdouterr.o frams/virtfile/virtfile.o  frams/virtfile/stdiofile.o common/nonstd_stdio.o $(GDK_OBJS) $(GENOCONV_GDK_OBJS)
+FULL_PROPS_OBJS= frams/_demos/full_props.o frams/errmgr/stdouterr.o frams/virtfile/virtfile.o  frams/virtfile/stdiofile.o common/nonstd_stdio.o $(GDK_OBJS) $(GENOCONV_GDK_OBJS) $(GENMAN_GDK_OBJS)
 
 SERIAL_TEST_OBJS= frams/_demos/serial_test.o frams/virtfile/virtfile.o  $(GDK_OBJS) $(GENOCONV_GDK_OBJS)
@@ -36,5 +36,5 @@
 PART_SHAPES_OBJS= frams/_demos/part_shapes.o frams/virtfile/virtfile.o  $(GDK_OBJS) $(GENOCONV_GDK_OBJS)
 
-NEURO_LAYOUT_TEST_OBJS= frams/_demos/neuro_layout_test.o frams/virtfile/virtfile.o frams/errmgr/stdouterr.o $(GDK_OBJS) $(GENOCONV_GDK_OBJS) frams/canvas/nn_layout_model.o frams/canvas/nn_simple_layout.o frams/canvas/nn_smart_layout.o
+NEURO_LAYOUT_TEST_OBJS= frams/_demos/neuro_layout_test.o frams/virtfile/virtfile.o frams/errmgr/stdouterr.o $(GDK_OBJS) $(GENOCONV_GDK_OBJS) $(GENMAN_GDK_OBJS) frams/canvas/nn_layout_model.o frams/canvas/nn_simple_layout.o frams/canvas/nn_smart_layout.o
 
 GENOOPER_TEST_OBJS=frams/_demos/genooper_test.o frams/virtfile/virtfile.o frams/errmgr/stdouterr.o $(GDK_OBJS) $(GENOCONV_GDK_OBJS) $(GENMAN_GDK_OBJS)
Index: cpp/frams/_demos/f0_variants_test.cpp
===================================================================
--- cpp/frams/_demos/f0_variants_test.cpp	(revision 144)
+++ cpp/frams/_demos/f0_variants_test.cpp	(revision 145)
@@ -8,10 +8,7 @@
 #include <frams/virtfile/stdiofile.h>
 
+#include <frams/genetics/defgenoconv.h>
 #include <frams/model/model.h>
-#include <frams/genetics/defgenoconv.h>
 #include <frams/errmgr/stdouterr.h>
-
-StdoutErrorHandler err; //redirect model-related errors to stdout
-DefaultGenoConvManager gcm; //without this object the application would only handle "format 0" genotypes
 
 void save_as_f0(SString &gen,Model &m,bool omit_default_values)
@@ -77,4 +74,14 @@
 int main(int argc,char*argv[])
 {
+StdoutErrorHandler err;//the default ErrorHandler constructor automatically registers this object to receive framsg messages (and in this case, redirect them to standard output)
+
+//without converters the application would only handle "format 0" genotypes
+DefaultGenoConvManager gcm;
+gcm.addDefaultConverters();
+Geno::useConverters(gcm);
+
+ModelGenoValidator model_validator;
+Geno::addValidator(&model_validator); //This simple validator handles all cases where a converter for a particular format is available but there is no genetic operator. Converters may be less strict in detecting invalid genotypes but it is better than nothing
+
 SString gen(argc>1?argv[1]:"X[|G:1.23]");
 if (!strcmp(gen,"-"))
Index: cpp/frams/_demos/full_props.cpp
===================================================================
--- cpp/frams/_demos/full_props.cpp	(revision 144)
+++ cpp/frams/_demos/full_props.cpp	(revision 145)
@@ -9,6 +9,6 @@
 
 #include <frams/model/model.h>
-#include <frams/genetics/defgenoconv.h>
 #include <frams/errmgr/stdouterr.h>
+#include <frams/genetics/preconfigured.h>
 
 /**
@@ -47,11 +47,10 @@
 */
 
-//optional:
-DefaultGenoConvManager gcm; //without this object the application would only handle "format 0" genotypes
-
 int main(int argc,char*argv[])
 {
 StdioFILE::setStdio();//setup VirtFILE::Vstdin/out/err
 StdoutErrorHandler err(ErrorHandlerBase::DontBlock,VirtFILE::Vstderr); //errors -> stderr, don't interfere with stdout
+
+PreconfiguredGenetics genetics;
 
 bool reverse=false;
Index: cpp/frams/_demos/gdk_test.cpp
===================================================================
--- cpp/frams/_demos/gdk_test.cpp	(revision 144)
+++ cpp/frams/_demos/gdk_test.cpp	(revision 145)
@@ -9,5 +9,5 @@
 
 #include <frams/model/model.h>
-#include <frams/genetics/defgenoconv.h>
+#include <frams/genetics/preconfigured.h>
 #include <frams/errmgr/stdouterr.h>
 
@@ -18,5 +18,5 @@
 
 StdoutErrorHandler err; //redirect model-related errors to stdout
-DefaultGenoConvManager gcm; //without this object the application would only handle "format 0" genotypes
+PreconfiguredGenetics genetics;
 
 void printNiceBanner(const char* title)
@@ -258,8 +258,8 @@
 void findingConverters()
 {
-GenoConverter *gc=gcm.findConverters(0,'1');
+GenoConverter *gc=Geno::getConverters().findConverters(0,'1');
 if (gc) printf("found converter accepting f1: \"%s\"\n",gc->name);
 SListTempl<GenoConverter*> found;
-gcm.findConverters(&found,-1,'0');
+Geno::getConverters().findConverters(&found,-1,'0');
 printf("found %d converter(s) producing f0\n",found.size());
 }
Index: cpp/frams/_demos/geno_test.cpp
===================================================================
--- cpp/frams/_demos/geno_test.cpp	(revision 144)
+++ cpp/frams/_demos/geno_test.cpp	(revision 145)
@@ -3,9 +3,7 @@
 // Refer to http://www.framsticks.com/ for further information.
 
-#include <frams/genetics/geno.h>
 #include <frams/virtfile/stdiofile.h>
 #include <frams/util/sstringutils.h>
-#include <frams/genetics/defgenoconv.h>
-#include <frams/genetics/genman.h>
+#include <frams/genetics/preconfigured.h>
 
 /**
@@ -16,12 +14,8 @@
 */
 
-DefaultGenoConvManager gcm; //without this object the application would only handle "format 0" genotypes
-
 int main(int argc,char*argv[])
 {
-GenMan gm;
-Geno::validators.insert(0,&gm); //GenMan is available in this application so let's use the extended validity checking!
-// Note: insert() makes it the first validator in the list, this is important for formats that rely on genetic operators to perform reasonable validation,
-// otherwise the default validator (genotype converter) would "win" and most converters are less strict in detecting invalid genotypes.
+PreconfiguredGenetics genetics;
+
 if (argc<=1)
 	{
Index: cpp/frams/_demos/genoconv_test.cpp
===================================================================
--- cpp/frams/_demos/genoconv_test.cpp	(revision 144)
+++ cpp/frams/_demos/genoconv_test.cpp	(revision 145)
@@ -10,6 +10,4 @@
 #include "printconvmap.h"
 #include <frams/errmgr/stdouterr.h>
-
-StdoutErrorHandler err;
 
 /**
@@ -119,8 +117,15 @@
 int main(int argc,char *argv[])
 {
+StdoutErrorHandler err;//the default ErrorHandler constructor automatically registers this object to receive framsg messages (and in this case, redirect them to standard output)
+
 DefaultGenoConvManager gcm;
+gcm.addDefaultConverters();
 gcm.addConverter(new GenoConv_Test());
 gcm.addConverter(new GenoConv_Test2());
 gcm.addConverter(new GenoConv_Test3());
+Geno::useConverters(gcm);
+
+ModelGenoValidator model_validator;
+Geno::addValidator(&model_validator);
 
 const char* src=(argc>1)?argv[1]:"X";
Index: cpp/frams/_demos/genooper_test.cpp
===================================================================
--- cpp/frams/_demos/genooper_test.cpp	(revision 144)
+++ cpp/frams/_demos/genooper_test.cpp	(revision 145)
@@ -3,10 +3,6 @@
 // Refer to http://www.framsticks.com/ for further information.
 
-#include <frams/genetics/genman.h>
 #include <frams/errmgr/stdouterr.h>
-#include <frams/genetics/defgenoconv.h>
-
-StdoutErrorHandler err;
-DefaultGenoConvManager gcm; //without this object the application would only handle "format 0" genotypes
+#include <frams/genetics/preconfigured.h>
 
 void printGen(Geno &g)
@@ -25,30 +21,31 @@
 int main(int argc, char *argv[])
 {
-	GenMan gm;
-	Geno::validators.insert(0,&gm); //GenMan is available in this application so let's use the extended validity checking!
-	// Note: insert() makes it the first validator in the list, this is important for formats that rely on genetic operators to perform reasonable validation,
-	// otherwise the default validator (genotype converter) would "win" and most converters are less strict in detecting invalid genotypes.
-	gm.p_report(NULL, NULL);
+	StdoutErrorHandler err;//the default ErrorHandler constructor automatically registers this object to receive framsg messages (and in this case, redirect them to standard output)
+	PreconfiguredGenetics genetics;
+
+	rndGetInstance().randomize();
+	genetics.genman.p_report(NULL, NULL);
 
 	const char* src = (argc > 1) ? argv[1] : "/*9*/UUU";
 	Geno gsrc(src, -1, "First");
 	printGenAndTitle(gsrc, "source genotype (gsrc)");
+	char format = gsrc.getFormat();
 
-	Geno gmut = gm.Mutate(gsrc);
+	Geno gmut = genetics.genman.Mutate(gsrc);
 	printGenAndTitle(gmut, "mutated (gmut)");
 
-	Geno gxover = gm.CrossOver(gsrc, gmut);
+	Geno gxover = genetics.genman.CrossOver(gsrc, gmut);
 	printGenAndTitle(gxover, "crossed over (gsrc and gmut)");
 
-	Geno gsimplest = gm.GetSimplest('9');
+	Geno gsimplest = genetics.genman.GetSimplest(format);
 	printGenAndTitle(gsimplest, "simplest");
 
-	Geno ginvalid("IT'S REALLY WRONG", '9');
+	Geno ginvalid("IT'S REALLY WRONG", format);
 	printGenAndTitle(ginvalid, "invalid");
 
-	Geno gvalidated = gm.Validate(ginvalid);
+	Geno gvalidated = genetics.genman.Validate(ginvalid);
 	printGenAndTitle(gvalidated, "validated");
 
-	printf("\nHTMLized: %s\n", (const char*)gm.HTMLize((const char*)gvalidated.getGene()));
+	printf("\nHTMLized: %s\n", (const char*)genetics.genman.HTMLize((const char*)gvalidated.getGene()));
 
 	return 0;
Index: cpp/frams/_demos/multiline_f0_test.cpp
===================================================================
--- cpp/frams/_demos/multiline_f0_test.cpp	(revision 144)
+++ cpp/frams/_demos/multiline_f0_test.cpp	(revision 145)
@@ -8,14 +8,14 @@
 #include <frams/virtfile/stdiofile.h>
 
+#include <frams/genetics/preconfigured.h>
 #include <frams/model/model.h>
-#include <frams/genetics/defgenoconv.h>
 #include <frams/errmgr/stdouterr.h>
 #include <frams/virtfile/stringfile.h>
 
-StdoutErrorHandler err; //redirect model-related errors to stdout
-DefaultGenoConvManager gcm; //without this object the application would only handle "format 0" genotypes
-
 int main(int argc,char*argv[])
 {
+StdoutErrorHandler err;//the default ErrorHandler constructor automatically registers this object to receive framsg messages (and in this case, redirect them to standard output)
+PreconfiguredGenetics genetics;
+
 SString gen(argc>1?argv[1]:"X[|G:1.23]");
 if (!strcmp(gen,"-"))
Index: cpp/frams/_demos/neuro_layout_test.cpp
===================================================================
--- cpp/frams/_demos/neuro_layout_test.cpp	(revision 144)
+++ cpp/frams/_demos/neuro_layout_test.cpp	(revision 145)
@@ -3,8 +3,7 @@
 // Refer to http://www.framsticks.com/ for further information.
 
-#include <frams/genetics/geno.h>
 #include <frams/virtfile/stdiofile.h>
 #include <frams/util/sstringutils.h>
-#include <frams/genetics/defgenoconv.h>
+#include <frams/genetics/preconfigured.h>
 #include <frams/model/model.h>
 #include <frams/errmgr/stdouterr.h>
@@ -20,7 +19,4 @@
  loader_test "data/walking.gen" "Walking Lizard" | neuro_layout_test -
 */
-
-StdoutErrorHandler err; //redirect model-related errors to stdout
-DefaultGenoConvManager gcm; //without this object the application would only handle "format 0" genotypes
 
 // stl is fun? ;-) ForwardIterator implementation for element coordinates (required by min_element/max_element)
@@ -87,4 +83,7 @@
 int main(int argc,char*argv[])
 {
+StdoutErrorHandler err;//the default ErrorHandler constructor automatically registers this object to receive framsg messages (and in this case, redirect them to standard output)
+PreconfiguredGenetics genetics;
+
 if (argc<=1)
 	{
Index: cpp/frams/_demos/neuro_test.cpp
===================================================================
--- cpp/frams/_demos/neuro_test.cpp	(revision 144)
+++ cpp/frams/_demos/neuro_test.cpp	(revision 145)
@@ -6,5 +6,5 @@
 #include <frams/virtfile/stdiofile.h>
 #include <frams/util/sstringutils.h>
-#include <frams/genetics/defgenoconv.h>
+#include <frams/genetics/preconfigured.h>
 #include <frams/neuro/neuroimpl.h>
 #include <frams/neuro/neurofactory.h>
@@ -15,7 +15,4 @@
  Sample code: Neural network tester (can run your custom neurons)
 */
-
-StdoutErrorHandler err; //redirect model-related errors to stdout
-DefaultGenoConvManager gcm; //without this object the application would only handle "format 0" genotypes
 
 #ifndef GDK_WITHOUT_FRAMS
@@ -63,4 +60,7 @@
 int main(int argc,char*argv[])
 {
+StdoutErrorHandler err;//the default ErrorHandler constructor automatically registers this object to receive framsg messages (and in this case, redirect them to standard output)
+PreconfiguredGenetics genetics;
+
 if (argc<=1)
 	{
Index: cpp/frams/genetics/defgenoconv.cpp
===================================================================
--- cpp/frams/genetics/defgenoconv.cpp	(revision 144)
+++ cpp/frams/genetics/defgenoconv.cpp	(revision 145)
@@ -41,5 +41,5 @@
 #endif
 
-DefaultGenoConvManager::DefaultGenoConvManager()
+void DefaultGenoConvManager::addDefaultConverters()
 {
 #ifdef USE_GENCONV_f10
Index: cpp/frams/genetics/defgenoconv.h
===================================================================
--- cpp/frams/genetics/defgenoconv.h	(revision 144)
+++ cpp/frams/genetics/defgenoconv.h	(revision 145)
@@ -8,11 +8,9 @@
 #include "genoconv.h"
 
-/// This GenoConvManager automatically registers the "standard" converters available in the GDK.
-/// All you have to do is create a single instance of this class somewhere in your application.
-/// @see genotest.cpp
+/// This GenoConvManager subclass allows you to add all "standard" converters in one go
 class DefaultGenoConvManager: public GenoConvManager
 {
   public:
-DefaultGenoConvManager();
+void addDefaultConverters();///< add all converters configured in gen-config file
 };
 
Index: cpp/frams/genetics/f9/oper_f9.cpp
===================================================================
--- cpp/frams/genetics/f9/oper_f9.cpp	(revision 144)
+++ cpp/frams/genetics/f9/oper_f9.cpp	(revision 145)
@@ -4,5 +4,5 @@
 
 #include "oper_f9.h"
-#include <frams/genetics/f9/conv_f9.h>
+#include "conv_f9.h"
 #include <common/nonstd.h> //randomN, rnd01
 
Index: cpp/frams/genetics/fF/fF_genotype.cpp
===================================================================
--- cpp/frams/genetics/fF/fF_genotype.cpp	(revision 145)
+++ cpp/frams/genetics/fF/fF_genotype.cpp	(revision 145)
@@ -0,0 +1,20 @@
+// This file is a part of the Framsticks GDK.
+// Copyright (C) 2002-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
+// Refer to http://www.framsticks.com/ for further information.
+
+#include "fF_genotype.h"
+
+#define FIELDSTRUCT fF_growth_params
+ParamEntry fF_growth_params::paramtab[] =
+{
+	{ "fF", 1, 7, "fF" },
+	{ "n", 0, PARAM_CANOMITNAME, "number of chambers", "d 1 15 1", FIELD(number_of_chambers), },
+	{ "sx", 0, PARAM_CANOMITNAME, "scale x", "f 0.5 1.0 0.9", FIELD(scalex), },
+	{ "sy", 0, PARAM_CANOMITNAME, "scale y", "f 0.5 1.0 0.9", FIELD(scaley), },
+	{ "sz", 0, PARAM_CANOMITNAME, "scale z", "f 0.5 1.0 0.9", FIELD(scalez), },
+	{ "tr", 0, PARAM_CANOMITNAME, "translation factor", "f 0 1 0.5", FIELD(translation), }, //formally -1..1, but let's avoid redundancy and elliminate symmetrical constructs
+	{ "a1", 0, PARAM_CANOMITNAME, "angle 1", "f -3.1415926 3.1415926 0", FIELD(angle1), },
+	{ "a2", 0, PARAM_CANOMITNAME, "angle 2", "f -3.1415926 3.1415926 0", FIELD(angle2), },
+	{ 0, 0, 0, },
+};
+#undef FIELDSTRUCT
Index: cpp/frams/genetics/fF/fF_genotype.h
===================================================================
--- cpp/frams/genetics/fF/fF_genotype.h	(revision 144)
+++ cpp/frams/genetics/fF/fF_genotype.h	(revision 145)
@@ -8,14 +8,18 @@
 #include <stdio.h>
 #include "common/stl-util.h"
-
+#include <frams/param/param.h>
 
 struct fF_growth_params
 {
 	int number_of_chambers;
-	double scalex, scaley, scalez; //scaling factors
-	double translation; //translation factor, TF range [−1; 1]
+	double scalex, scaley, scalez;
+	double translation;
 	double angle1, angle2;
 
+	static ParamEntry paramtab[];
+	Param param;
+
 	fF_growth_params()
+		:param(paramtab, this)
 	{
 		reset();
@@ -24,18 +28,19 @@
 	void reset()
 	{
-		number_of_chambers = 1;
-		scalex = scaley = scalez = 1;
-		translation = 1;
-		angle1 = angle2 = 0;
+		param.setDefault();
 	}
 
 	bool load(const char* serialized)
 	{
-		return sscanf(serialized, "%d %lf %lf %lf %lf %lf %lf", &number_of_chambers, &scalex, &scaley, &scalez, &translation, &angle1, &angle2) == 7;
+		SString s = serialized;
+		int p = 0; //position in string
+		return ((param.load2(s, p)==7) && (p==s.len()));
 	}
 
 	string save()
 	{
-		return ssprintf("%d %f %f %f %f %f %f", number_of_chambers, scalex, scaley, scalez, translation, angle1, angle2);
+		SString tmp;
+		param.save2(tmp, NULL/*object containing default values for comparison*/, false/*add CR*/, false/*force field names*/);
+		return string((const char*)tmp);
 	}
 };
Index: cpp/frams/genetics/fF/oper_fF.cpp
===================================================================
--- cpp/frams/genetics/fF/oper_fF.cpp	(revision 144)
+++ cpp/frams/genetics/fF/oper_fF.cpp	(revision 145)
@@ -4,16 +4,14 @@
 
 #include "oper_fF.h"
-#include <frams/genetics/f9/conv_f9.h>
+#include "fF_genotype.h"
 #include <common/nonstd.h> //randomN, rnd01
 
 
-//THIS FILE NEEDS UPDATE. OLD, UNRELATED SOURCES BELOW (COPIED FROM f9).
-
 #define FIELDSTRUCT GenoOper_fF
-static ParamEntry GENOf9param_tab[]=
+static ParamEntry GENOfFparam_tab[] =
 {
-	{"Genetics: fF",1,1,},
-	{"fF_mut",0,0,"Mutation probability","f 0 1 0.1",FIELD(mut_prob),"How many genes should be mutated during single mutation (1=all genes, 0.1=ten percent)",},
-	{0,},
+	{ "Genetics: fF", 1, 1, },
+	{ "fF_xover", 0, 0, "Averaging crossover proportion", "f 0 0.5 0.5", FIELD(xover_proportion), "0.5 => children are averaged parents.\n0.2 => children are only 20% different from parents.\n0 => each child is identical to one parent (no crossover).", },
+	{ 0, },
 };
 #undef FIELDSTRUCT
@@ -22,89 +20,69 @@
 GenoOper_fF::GenoOper_fF()
 {
-	par.setParamTab(GENOf9param_tab);
+	par.setParamTab(GENOfFparam_tab);
 	par.select(this);
 	par.setDefault();
-	supported_format='F';
+	supported_format = 'F';
 }
 
 int GenoOper_fF::checkValidity(const char* gene)
 {
-	return GENOPER_OK;
-	if (!gene[0]) return 1; //empty is not valid
-	bool ok=true;
-	int i;
-	for(i=0;i<strlen(gene);i++) if (!strchr(turtle_commands_f9,gene[i])) {ok=false; break;}
-	return ok ? GENOPER_OK : i+1;
+	fF_growth_params par;
+	return par.load(gene) ? GENOPER_OK : 1;
 }
 
-///Remove all invalid letters from the genotype
 int GenoOper_fF::validate(char *&gene)
 {
-	SString validated; //new genotype (everything except turtle_commands_f9 is skipped)
-	for(int i=0;i<strlen(gene);i++)
-		if (strchr(turtle_commands_f9,gene[i])) validated+=gene[i];  //validated contains only turtle_commands_f9
+	fF_growth_params par; //is initialized with default values
+	par.load(gene); //loads as much as possible, other fields remain with default values
+	string validated = par.save();
 	free(gene);
-	gene=strdup(validated); //reallocate
+	gene = strdup(validated.c_str()); //reallocate
 	return GENOPER_OK;
 }
 
-///Very simple mutation
-int GenoOper_fF::mutate(char *&gene,float &chg,int &method)
+//Creep-mutate one property
+int GenoOper_fF::mutate(char *&gene, float &chg, int &method)
 {
-	method=0;
-	int changes=0,len=strlen(gene);
-	int symbols=strlen(turtle_commands_f9);
-
-	for(int i=0;i<len;i++)
+	method = 0;
+	fF_growth_params par;
+	par.load(gene);
+	int which = randomN(par.param.getPropCount());
+	bool mutated_ok = GenoOperators::mutatePropertyNaive(par.param, which);
+	if (mutated_ok)
 	{
-		if (rnd01<mut_prob) //normalize prob with the length of the genotype
-		{
-			char oldgene=gene[i];
-			gene[i]=turtle_commands_f9[randomN(symbols)];
-			if (gene[i]!=oldgene) changes++;
-		}
+		string saved = par.save();
+		free(gene);
+		gene = strdup(saved.c_str()); //reallocate
+		chg = 1.0f / par.param.getPropCount();
+		return GENOPER_OK;
 	}
-
-	if (rnd01<mut_prob) //add or delete a random char
+	else
 	{
-		SString newgeno(gene);
-		if (randomN(2)==0) //add
-		{
-			int symbols=strlen(turtle_commands_f9);
-			int p=randomN(len+1);  //random location
-			//printf("before add: %s\n",(const char*)newgeno);
-			newgeno=newgeno.substr(0,p)+SString(turtle_commands_f9+randomN(symbols),1)+newgeno.substr(p);
-			//printf("after add: %s\n",(const char*)newgeno);
-			changes++;
-		} else if (len>1) //delete
-		{
-			int p=randomN(len);  //random location
-			//printf("before delete: %s\n",(const char*)newgeno);
-			newgeno=newgeno.substr(0,p)+newgeno.substr(p+1);
-			//printf("after delete: %s\n",(const char*)newgeno);
-			changes++;
-		}
-		free(gene);
-		gene=strdup(newgeno); //reallocate
+		chg = 0;
+		return GENOPER_OPFAIL;
 	}
-
-	chg=(float)changes/len;
-	return changes>0?GENOPER_OK:GENOPER_OPFAIL; //no changes => OPFAIL so that genman will call mutate again
 }
 
-///A simple one-point crossover
-int GenoOper_fF::crossOver(char *&g1,char *&g2,float& chg1,float& chg2)
+///Averaging crossover
+int GenoOper_fF::crossOver(char *&g1, char *&g2, float& chg1, float& chg2)
 {
-	int len1=strlen(g1),len2=strlen(g2);
-	int p1=randomN(len1);  //random cut point for first genotype
-	int p2=randomN(len2);  //random cut point for second genotype
-	char *child1=(char*)malloc(p1+len2-p2+1);
-	char *child2=(char*)malloc(p2+len1-p1+1);
-	strncpy(child1,g1,p1);   strcpy(child1+p1,g2+p2);
-	strncpy(child2,g2,p2);   strcpy(child2+p2,g1+p1);
-	free(g1); g1=child1;
-	free(g2); g2=child2;
-	chg1=(float)p1/strlen(child1);
-	chg2=(float)p2/strlen(child2);
+	//g1 = strdup("1,0.5,0.5,0.5,0.5,1,1"); //testing...
+	//g2 = strdup("4,1,  1,  1,  1,  2,2"); //testing...
+	//xover_proportion = 0.1; //testing...
+	fF_growth_params par1;
+	par1.load(g1);
+	fF_growth_params par2;
+	par2.load(g2);
+	chg1 = xover_proportion;
+	chg2 = 1 - xover_proportion;
+	for (int i = 0; i < par1.param.getPropCount(); i++)
+		GenoOperators::linearMix(par1.param, i, par2.param, i, xover_proportion);
+	string saved = par1.save();
+	free(g1);
+	g1 = strdup(saved.c_str()); //reallocate
+	saved = par2.save();
+	free(g2);
+	g2 = strdup(saved.c_str()); //reallocate
 	return GENOPER_OK;
 }
@@ -113,13 +91,10 @@
 unsigned long GenoOper_fF::style(const char *g, int pos)
 {
-	char ch=g[pos];
-	unsigned long style=GENSTYLE_CS(0,GENSTYLE_INVALID); //default, should be changed below
-	char *ptr=strchr((char*)turtle_commands_f9,ch);
-	if (ptr)
-	{
-		int pos=ptr-turtle_commands_f9;
-		int axis=pos/2;
-		style=GENSTYLE_RGBS(axis==0?200:0,axis==1?200:0,axis==2?200:0,GENSTYLE_NONE);
-	}
+	char ch = g[pos];
+	unsigned long style = GENSTYLE_CS(0, GENSTYLE_INVALID); //default, should be changed below
+	if (strchr("-.e 0123456789", ch) != NULL)
+		style = GENSTYLE_CS(GENCOLOR_NUMBER, GENSTYLE_NONE);
+	else if (ch == ',')
+		style = GENSTYLE_RGBS(0, 0, 0, GENSTYLE_BOLD);
 	return style;
 }
Index: cpp/frams/genetics/fF/oper_fF.h
===================================================================
--- cpp/frams/genetics/fF/oper_fF.h	(revision 144)
+++ cpp/frams/genetics/fF/oper_fF.h	(revision 145)
@@ -18,7 +18,7 @@
 	int crossOver(char *&g1, char *&g2, float& chg1, float& chg2);
 	unsigned long style(const char *g, int pos);
-	const char* getSimplest() { return "5 0.9 0.8 0.7 0.7 0.3 0.7"; }
+	const char* getSimplest() { return "6,0.8,0.85,0.9,0.6,0.3,0.7"; }
 
-	double mut_prob; //mutation probability
+	double xover_proportion;
 };
 
Index: cpp/frams/genetics/genman.cpp
===================================================================
--- cpp/frams/genetics/genman.cpp	(revision 144)
+++ cpp/frams/genetics/genman.cpp	(revision 145)
@@ -105,61 +105,61 @@
 
 #ifdef USE_GENMAN_f0
-	geno_fx_list.push_back(new Geno_f0);
+	oper_fx_list.push_back(new Geno_f0);
 #endif
 #ifdef USE_GENMAN_f0FUZZY
-	geno_fx_list.push_back(new Geno_f0Fuzzy);
+	oper_fx_list.push_back(new Geno_f0Fuzzy);
 #endif
 #ifdef USE_GENMAN_f1
-	geno_fx_list.push_back(new Geno_f1);
+	oper_fx_list.push_back(new Geno_f1);
 #endif
 #ifdef USE_GENMAN_f2
-	geno_fx_list.push_back(new Geno_f2);
+	oper_fx_list.push_back(new Geno_f2);
 #endif
 #ifdef USE_GENMAN_f3
-	geno_fx_list.push_back(new Geno_f3);
+	oper_fx_list.push_back(new Geno_f3);
 #endif
 #ifdef USE_GENMAN_f4
-	geno_fx_list.push_back(new Geno_f4);
+	oper_fx_list.push_back(new Geno_f4);
 #endif
 #ifdef USE_GENMAN_f5
-	geno_fx_list.push_back(new Geno_f5);
+	oper_fx_list.push_back(new Geno_f5);
 #endif
 #ifdef USE_GENMAN_f6
-	geno_fx_list.push_back(new Geno_f6);
+	oper_fx_list.push_back(new Geno_f6);
 #endif
 #ifdef USE_GENMAN_f7
-	geno_fx_list.push_back(new Geno_f7);
+	oper_fx_list.push_back(new Geno_f7);
 #endif
 #ifdef USE_GENMAN_f8
-	geno_fx_list.push_back(new Geno_f8);
+	oper_fx_list.push_back(new Geno_f8);
 #endif
 #ifdef USE_GENMAN_f9
-	geno_fx_list.push_back(new GenoOper_f9);
+	oper_fx_list.push_back(new GenoOper_f9);
 #endif
 #ifdef USE_GENMAN_fF
-	geno_fx_list.push_back(new GenoOper_fF);
-#endif
-
-	seloper = new int[geno_fx_list.size()]; //may result in a little overhead if some of the operators on the geno_fx_list concern the same genetic format
+	oper_fx_list.push_back(new GenoOper_fF);
+#endif
+
+	seloper = new int[oper_fx_list.size()]; //may result in a little overhead if some of the operators on the oper_fx_list concern the same genetic format
 	int selopercount = 0;
-	for (unsigned int i = 0; i < geno_fx_list.size(); i++)
-	{
-		if (operformats.find(geno_fx_list[i]->supported_format) != -1) continue;
+	for (unsigned int i = 0; i < oper_fx_list.size(); i++)
+	{
+		if (operformats.find(oper_fx_list[i]->supported_format) != -1) continue;
 		char tmp[10];
 		SString id, name, type = "~";
-		type += geno_fx_list[i]->name;
+		type += oper_fx_list[i]->name;
 		int dup = 0;
-		for (unsigned int j = i + 1; j < geno_fx_list.size(); j++)
-			if (geno_fx_list[i]->supported_format == geno_fx_list[j]->supported_format)
+		for (unsigned int j = i + 1; j < oper_fx_list.size(); j++)
+			if (oper_fx_list[i]->supported_format == oper_fx_list[j]->supported_format)
 			{
-				type += "~"; type += geno_fx_list[j]->name; dup++;
+				type += "~"; type += oper_fx_list[j]->name; dup++;
 			}
 		sprintf(tmp, "d 0 %d ", dup);
 		type = SString(tmp) + type;
-		sprintf(tmp, "%c", geno_fx_list[i]->supported_format);
+		sprintf(tmp, "%c", oper_fx_list[i]->supported_format);
 		id = "genoper_f"; id += tmp;
 		name = "Operators for f"; name += tmp;
 		seloper[selopercount] = 0;
-		operformats += geno_fx_list[i]->supported_format;
+		operformats += oper_fx_list[i]->supported_format;
 		//printf("%x %s %s %s\n",&seloper[selopercount],(const char*)id,(const char*)type,(const char*)name);
 		seloperpar.addProperty(&seloper[selopercount++], id, type, name, "", PARAM_READONLY*(dup == 0));
@@ -169,11 +169,11 @@
 	par += &seloperpar;
 	par += &neuronsparam;
-	for (unsigned int i = 0; i < geno_fx_list.size(); i++)
-		if (geno_fx_list[i]->par.getParamTab()) par += &geno_fx_list[i]->par;
+	for (unsigned int i = 0; i < oper_fx_list.size(); i++)
+		if (oper_fx_list[i]->par.getParamTab()) par += &oper_fx_list[i]->par;
 }
 
 GenMan::~GenMan()
 {
-	for (unsigned int i = 0; i < geno_fx_list.size(); i++) delete geno_fx_list[i];
+	for (unsigned int i = 0; i < oper_fx_list.size(); i++) delete oper_fx_list[i];
 	delete[] seloper;
 }
@@ -181,8 +181,8 @@
 void GenMan::setDefaults()
 {
-	for (unsigned int i = 0; i < geno_fx_list.size(); i++)
-	{
-		geno_fx_list[i]->par.setDefault();
-		geno_fx_list[i]->setDefaults();
+	for (unsigned int i = 0; i < oper_fx_list.size(); i++)
+	{
+		oper_fx_list[i]->par.setDefault();
+		oper_fx_list[i]->setDefaults();
 	}
 	localpar.setDefault();
@@ -194,5 +194,5 @@
 {
 	const char *gg = g.getGene();
-	GenoOperators *gf = getGeno_f(g.getFormat());
+	GenoOperators *gf = getOper_f(g.getFormat());
 	int check1;
 	if (!gf) { canvalidate = false; return GENOPER_NOOPER; }
@@ -228,5 +228,5 @@
 {
 	char format=geny.getFormat();
-	GenoOperators *gf=getGeno_f(format);
+	GenoOperators *gf=getOper_f(format);
 	if (gf==NULL)
 		return Geno(SString::empty(),-1,SString::empty(),SString::sprintf("GENOPER_NOOPER: Validate(): don't know how to handle genetic format %c",format));
@@ -246,5 +246,5 @@
 	int method; //mutation method
 	char format=g.getFormat();
-	GenoOperators *gf=getGeno_f(format);
+	GenoOperators *gf=getOper_f(format);
 	if (gf==NULL)
 		return Geno(SString::empty(),-1,SString::empty(),SString::sprintf("GENOPER_NOOPER: Mutate(): don't know how to handle genetic format %c",format));
@@ -292,5 +292,5 @@
 	char format = g1.getFormat();
 	if (format != g2.getFormat()) return Geno(SString::empty(), -1, SString::empty(), SString::sprintf("GENOPER_NOOPER: CrossOver() does not know how to handle parents with differing genetic formats (%c and %c)", format, g2.getFormat()));
-	GenoOperators *gf = getGeno_f(format);
+	GenoOperators *gf = getOper_f(format);
 	if (gf == NULL)
 		return Geno(SString::empty(), -1, SString::empty(), SString::sprintf("GENOPER_NOOPER: CrossOver(): don't know how to handle genetic format %c", format));
@@ -358,5 +358,5 @@
 	char format = g1.getFormat();
 	if (format != g2.getFormat()) return GENOPER_NOOPER;
-	GenoOperators *gf = getGeno_f(format);
+	GenoOperators *gf = getOper_f(format);
 	if (!gf) return GENOPER_NOOPER; else return gf->similarity(g1.getGene(), g2.getGene());
 }
@@ -366,5 +366,5 @@
 	Geno G(g);
 	if ((pos = G.mapStringToGen(pos)) == -1) return GENSTYLE_COMMENT;
-	GenoOperators *gf = getGeno_f(G.getFormat());
+	GenoOperators *gf = getOper_f(G.getFormat());
 	if (!gf) return GENSTYLE_CS(0, 0); //black & valid
 	else return gf->style(G.getGene(), pos);
@@ -374,5 +374,5 @@
 {
 	Geno G(g);
-	GenoOperators *gf = getGeno_f(G.getFormat());
+	GenoOperators *gf = getOper_f(G.getFormat());
 	SString geny = G.getGene();
 	for (unsigned int pos = 0; pos < strlen(g); pos++)
@@ -448,5 +448,5 @@
 Geno GenMan::GetSimplest(char format)
 {
-	GenoOperators *gf = getGeno_f(format);
+	GenoOperators *gf = getOper_f(format);
 	if (!gf) return Geno();
 	SString info = "The simplest genotype of format f"; info += format;
@@ -458,5 +458,5 @@
 {
 	int format = args[0].getInt() + 48;
-	if (!getGeno_f(format))
+	if (!getOper_f(format))
 		ret->setEmpty();
 	else
@@ -466,16 +466,16 @@
 const char *GenMan::GetOpName(char format)
 {
-	GenoOperators *gf = getGeno_f(format);
+	GenoOperators *gf = getOper_f(format);
 	if (!gf) return "n/a"; else return gf->name;
 }
 
-GenoOperators* GenMan::getGeno_f(char format)
+GenoOperators* GenMan::getOper_f(char format)
 {
 	int ind = operformats.find(format);
 	if (ind == -1) return NULL;
 	int ktoryopformatu = seloper[ind];
-	for (unsigned int i = 0; i < geno_fx_list.size(); i++)
-		if (geno_fx_list[i]->supported_format == format)
-			if (ktoryopformatu == 0) return geno_fx_list[i]; else ktoryopformatu--;
+	for (unsigned int i = 0; i < oper_fx_list.size(); i++)
+		if (oper_fx_list[i]->supported_format == format)
+			if (ktoryopformatu == 0) return oper_fx_list[i]; else ktoryopformatu--;
 	return NULL; //should never happen
 }
@@ -519,23 +519,24 @@
 {                      //should be updated to handle multiple operators for a single format
 	char *g, *g2;
-	float f; int m;
+	float f1, f2;
+	int m;
 	FramMessage("GenMan", "Report", "The following genetic operators are available:", 0);
-	for (unsigned int i = 0; i < geno_fx_list.size(); i++)
+	for (unsigned int i = 0; i < oper_fx_list.size(); i++)
 	{
 		SString l;
-		if (geno_fx_list[i]->checkValidity("") != GENOPER_NOOPER) l += " checkValidity";
-		if (geno_fx_list[i]->getSimplest())
-		{
-			g = strdup(geno_fx_list[i]->getSimplest());
+		if (oper_fx_list[i]->checkValidity("") != GENOPER_NOOPER) l += " checkValidity";
+		if (oper_fx_list[i]->getSimplest())
+		{
+			g = strdup(oper_fx_list[i]->getSimplest());
 			g2 = strdup(g);
-			if (geno_fx_list[i]->validate(g) != GENOPER_NOOPER) l += " validate";
-			if (geno_fx_list[i]->mutate(g, f, m) != GENOPER_NOOPER) l += " mutate";
-			if (geno_fx_list[i]->crossOver(g, g2, f, f) != GENOPER_NOOPER) l += " crossover";
+			if (oper_fx_list[i]->validate(g) != GENOPER_NOOPER) l += " validate";
+			if (oper_fx_list[i]->mutate(g, f1, m) != GENOPER_NOOPER) l += " mutate";
+			if (oper_fx_list[i]->crossOver(g, g2, f1, f2) != GENOPER_NOOPER) l += " crossover";
 			l += " getSimplest";
 			free(g); free(g2);
 		}
-		//      if (geno_fx_list[i]->similarity("","")!=GENOPER_NOOPER) l+=" similarity";
+		//      if (oper_fx_list[i]->similarity("","")!=GENOPER_NOOPER) l+=" similarity";
 		FMprintf("GenMan", "Report", 0, "format f%c (%s):%s",
-			geno_fx_list[i]->supported_format, (const char*)geno_fx_list[i]->name, (const char*)l);
+			oper_fx_list[i]->supported_format, (const char*)oper_fx_list[i]->name, (const char*)l);
 	}
 }
Index: cpp/frams/genetics/genman.h
===================================================================
--- cpp/frams/genetics/genman.h	(revision 144)
+++ cpp/frams/genetics/genman.h	(revision 145)
@@ -7,4 +7,5 @@
 
 #include <common/nonstd.h>
+#include <common/nonstd_stl.h>
 #include <frams/param/mutableparam.h>
 #include <frams/param/mutparamlist.h>
@@ -12,6 +13,4 @@
 #include "geno.h"
 #include "oper_fx.h"
-#include <string>
-#include <vector>
 
 #define GENSTYLE_COMMENT GENSTYLE_RGBS(0,150,0,GENSTYLE_BOLD)
@@ -20,5 +19,5 @@
 {
 	int count;
-	std::string g1, g2;
+	string g1, g2;
 	float chg;
 	float fit;
@@ -53,11 +52,12 @@
 	Geno GetSimplest(char format); ///<returns pointer to the simplest genotype of \e format or empty Geno()
 	const char *GetOpName(char format); ///<returns pointer to the active operator set for \e format
+	const vector<GenoOperators*>& GetOperators() const { return oper_fx_list; } ///<returns the list of available genetic operators
 private:
-	std::vector<GenoOperators*> geno_fx_list;
-	void saveLink(std::string prz, std::string pot, float& chg);
-	GenoOperators* getGeno_f(char format);
+	vector<GenoOperators*> oper_fx_list;
+	void saveLink(string prz, string pot, float& chg);
+	GenoOperators* getOper_f(char format);
 	SString HTMLize(const char *g, bool shorten);
 public:
-	std::vector<GenoLink> GenoLinkList;
+	vector<GenoLink> GenoLinkList;
 	int history; //remember history?
 	int hilite; //syntax highlighting (Style)
@@ -66,5 +66,5 @@
 	int valid_m, valid_xo, validated_m, validated_xo, invalid_m, invalid_xo, failed_m, failed_xo;
 	double mutchg, xochg;
-	SListTempl<char> operformats; //the list of supported_format, in the order same as in seloperpar
+	SListTempl<char> operformats; //the list of supported_format, in the same order as in seloperpar
 	int* seloper; //fields for seloperpar
 	Param localpar, localstats;
Index: cpp/frams/genetics/geno.cpp
===================================================================
--- cpp/frams/genetics/geno.cpp	(revision 144)
+++ cpp/frams/genetics/geno.cpp	(revision 145)
@@ -4,7 +4,9 @@
 
 #include "geno.h"
+#include "genoconv.h"
 #include <frams/model/model.h>
 
 SListTempl<GenoValidator*> Geno::validators;
+GenoConvManager *Geno::converters=NULL;
 
 void Geno::init(const SString& genstring,char genformat,const SString& genname,const SString& comment)
@@ -209,16 +211,4 @@
 SString Geno::getComment(void) const {return txt;}
 
-class ModelGenoValidator: public GenoValidator
-{
-public:
-	ModelGenoValidator();
-	int testGenoValidity(Geno& g);
-};
-
-ModelGenoValidator::ModelGenoValidator()
-{
-Geno::validators+=this;
-}
-
 int ModelGenoValidator::testGenoValidity(Geno& g)
 {
@@ -234,6 +224,4 @@
 	}
 }
-
-static ModelGenoValidator default_validator;
 
 void Geno::validate()
@@ -256,15 +244,17 @@
 if (otherformat==getFormat()) return *this;
 #ifndef NO_GENOCONVMANAGER
-if ((otherformat=='0')&&(!m))
-	{
-	if (!f0gen)
-		f0gen=new Geno(GenoConvManager::globalConvert(*this,otherformat));
-	return *f0gen;
-	}
-else
-	return GenoConvManager::globalConvert(*this,otherformat,m);
-#else
+if (converters)
+	{
+	if ((otherformat=='0')&&(!m))
+		{
+		if (!f0gen)
+			f0gen=new Geno(converters->convert(*this,otherformat));
+		return *f0gen;
+	}
+	else
+		return converters->convert(*this,otherformat,m);
+	}
+#endif
 return (otherformat==getFormat())?*this:Geno(0,0,0,"GenConvManager not available");
-#endif
 }
 
Index: cpp/frams/genetics/geno.h
===================================================================
--- cpp/frams/genetics/geno.h	(revision 144)
+++ cpp/frams/genetics/geno.h	(revision 145)
@@ -11,4 +11,5 @@
 class MultiMap;
 class Geno;
+class GenoConvManager;
 
 class GenoValidator
@@ -18,7 +19,16 @@
 };
 
+/// basic GenoValidator that works by building a Model from any Geno (by converting to f0)
+/// validation fails when the model can't be built or the genotype can't be converted
+class ModelGenoValidator: public GenoValidator
+{
+public:
+	int testGenoValidity(Geno& g);
+};
+
 /// basic information about a single genotype.
 class Geno: public DestrBase
 {
+friend class Simulator;//needs to access validators directly
 SString gen;
 SString name;
@@ -103,4 +113,12 @@
 
 void* owner;
+
+// managing global Geno-related objects (used for validation and conversion)
+static void addValidator(GenoValidator* gv) {validators+=gv;}
+static void removeValidator(GenoValidator* gv) {validators-=gv;}
+static void useConverters(GenoConvManager& gcm) {converters=&gcm;}
+static GenoConvManager &getConverters() {return *converters;}
+  protected:
+static GenoConvManager *converters;
 static SListTempl<GenoValidator*> validators;
 };
Index: cpp/frams/genetics/genoconv.cpp
===================================================================
--- cpp/frams/genetics/genoconv.cpp	(revision 144)
+++ cpp/frams/genetics/genoconv.cpp	(revision 145)
@@ -82,5 +82,4 @@
 	:param(this)
 {
-if (!globalobject) globalobject=this;
 }
 
@@ -89,8 +88,5 @@
 GenoConverter *gc;
 for (converters.start();gc=(GenoConverter*)converters();) delete gc;
-if (globalobject==this) globalobject=NULL;
-}
-
-GenoConvManager *GenoConvManager::globalobject=NULL;
+}
 
 void GenoConvManager::addConverter(GenoConverter *gc)
@@ -217,11 +213,2 @@
 return Geno(tmp, format, in.getName(), in.getComment());
 }
-
-Geno GenoConvManager::globalConvert(Geno &in,char format,MultiMap *map)
-{
-if (globalobject) return globalobject->convert(in,format,map);
-if (format==in.getFormat()) return in;
-return Geno(0,0,0,"GenConvManager not initialized");
-}
-
-/////////////////////////////////
Index: cpp/frams/genetics/genoconv.h
===================================================================
--- cpp/frams/genetics/genoconv.h	(revision 144)
+++ cpp/frams/genetics/genoconv.h	(revision 145)
@@ -73,19 +73,12 @@
 friend class GenoConvParam;
 SList converters;
-static GenoConvManager *globalobject;
 public:
 GenoConvManager();
 ~GenoConvManager();
 class GenoConvParam param;
-/// select an object for use as global GenoConvManager
-void useManager(GenoConvManager *m) {globalobject=m;}
-/// get global converter
-static GenoConvManager *getGlobalObject() {return globalobject;}
 /// make a genotype in other format. genotype will be invalid
 /// if GenoConvManager cannot convert it.
 Geno convert(Geno &in,char format,MultiMap *map=0);
-/// static conversion function (uses global GenoConvManager)
-static Geno globalConvert(Geno &in,char format,MultiMap *map=0);
-/// register GenoConverter
+/// register GenoConverter, the added object will be automatically deleted when GenoConvManager is destructed (call removeConverter() if this is not desirable)
 void addConverter(GenoConverter *conv);
 /// unregister GenoConverter
Index: cpp/frams/genetics/oper_fx.h
===================================================================
--- cpp/frams/genetics/oper_fx.h	(revision 144)
+++ cpp/frams/genetics/oper_fx.h	(revision 145)
@@ -81,5 +81,5 @@
  public:
    Param par;
-   char supported_format; ///<genotype format which is supported by this class ('6' for Geno_f6, etc.). Must be initialized in constructor
+   char supported_format; ///<genotype format which is supported by this class ('6' for GenoOper_f6, 'F' for GenoOper_fF, etc.). Must be initialized in constructor
    SString name; ///<name of this set of genetic operators
    char **mutation_method_names; ///<array of names for mutation methods. If initialized (by new char*[]), must have entries for each method index returned by mutate(geno,chg,METHOD).  If initialized, it is automatically freed by this destructor.
@@ -187,4 +187,6 @@
    static double mutateCreepNoLimit(char type,double current,double mn,double mx); ///<returns \e current value creep-mutated with Gaussian distribution within [ \e mn , \e mx ] interval. Forced precision: 3 digits after comma. \e type must be either 'd' (integer) or 'f' (float/double).
    static double mutateCreep(char type,double current,double mn,double mx); ///<just as mutateCreepNoLimit(), but forces mutated value into the [mn,mx] range using the 'reflect' approach.
+   static void setIntFromDoubleWithProbabilisticDithering(ParamInterface &p, int index, double value); ///<sets a double value in an integer field; when a value is non-integer, applies random "dithering" so that both lower and higher integer value have some chance to be set.
+   static void linearMix(ParamInterface &p1, int i1, ParamInterface &p2, int i2, double proportion); ///<mixes i1'th and i2'th properties of p1 and p2; proportion should be within [0,1]; 0.5 causes both properties to become their average. For integer properties applies random "dithering" when necessary.
    static NeuroClass* getRandomNeuroClass(); ///<returns random neuroclass or NULL when no active classes.
    static NeuroClass* parseNeuroClass(char *&s); ///<returns neuroclass or NULL if the string does not begin with a valid name. Advance \e s pointer.
Index: cpp/frams/genetics/preconfigured.h
===================================================================
--- cpp/frams/genetics/preconfigured.h	(revision 145)
+++ cpp/frams/genetics/preconfigured.h	(revision 145)
@@ -0,0 +1,29 @@
+#ifndef _PRECONFIGURED_GENETICS_H_
+#define _PRECONFIGURED_GENETICS_H_
+
+#include "genman.h"
+#include "defgenoconv.h"
+
+/** This class handles a typical initialization procedure and configuration of genetics:
+- adds converters between genetic formats as configured by gen-config.h,
+- validation of genotypes by dedicated genetic operators, or by conversion to f0 if no genetic operator is found that can validate a genotype.
+*/
+class PreconfiguredGenetics
+{
+  public:
+DefaultGenoConvManager gcm;
+GenMan genman;
+ModelGenoValidator model_validator; //validation through conversion
+
+PreconfiguredGenetics()
+	{
+	gcm.addDefaultConverters(); //without converters, the application would only handle "format 0" genotypes
+	Geno::useConverters(gcm);
+
+	Geno::addValidator(&genman); //primary validation: use the extended validity checking (through dedicated genetic operators)
+	Geno::addValidator(&model_validator); //secondary validation: this simple validator handles all cases when there is no dedicated genetic validation operator, but a converter for a particular format is available. Converters may be less strict in detecting invalid genotypes but using them and checking whether they produced a valid f0 genotype is also some way to tell whether the initial genotype was valid. Otherwise, without dedicated genetic validation operator, we would have no validity check at all.
+	}
+};
+
+#endif
+
