Index: cpp/frams/_demos/genoconv_test.cpp
===================================================================
--- cpp/frams/_demos/genoconv_test.cpp	(revision 730)
+++ cpp/frams/_demos/genoconv_test.cpp	(revision 732)
@@ -27,5 +27,5 @@
 		in_format = 'x';
 	}
-	SString convert(SString &i, MultiMap *map) { return SString("after conversion..."); }
+	SString convert(SString &i, MultiMap *map, bool using_checkpoints) { return SString("after conversion..."); }
 	~GenoConv_Test() {}
 };
@@ -42,5 +42,5 @@
 	}
 
-	SString convert(SString &i, MultiMap *map)
+	SString convert(SString &i, MultiMap *map, bool using_checkpoints)
 	{
 		Model mod;
@@ -53,5 +53,5 @@
 		return mod.getF0Geno().getGenes();
 	}
-	
+
 	~GenoConv_Test2() {}
 };
@@ -70,10 +70,10 @@
 		mapsupport = 1;
 	}
-	SString convert(SString &in, MultiMap *map);
+	SString convert(SString &in, MultiMap *map, bool using_checkpoints);
 	~GenoConv_Test3() {}
 };
 
 /** main converting routine - most important: direct conversion map example */
-SString GenoConv_Test3::convert(SString &in, MultiMap *map)
+SString GenoConv_Test3::convert(SString &in, MultiMap *map, bool using_checkpoints)
 {
 	SString dst;
@@ -116,4 +116,8 @@
 }
 
+// arguments:
+//     genotype (or - meaning "read from stdin") [default: X]
+//     target format [default: 0]
+//     "checkpoints" (just write this exact word) [default: not using checkpoints]
 int main(int argc, char *argv[])
 {
@@ -146,4 +150,5 @@
 		src = "X";
 	char dst = (argc > 2) ? *argv[2] : '0';
+	bool using_checkpoints = (argc > 3) ? (strcmp(argv[3], "checkpoints") == 0) : false;
 
 	printf("*** Source genotype:\n");
@@ -151,29 +156,51 @@
 	printGen(g1);
 	MultiMap m;
-	Geno g2 = g1.getConverted(dst, &m);
+	Geno g2 = g1.getConverted(dst, &m, using_checkpoints);
 	printf("*** Converted to f%c:\n", dst);
 	printGen(g2);
-	if (m.isEmpty())
-		printf("(conversion map not available)\n");
+
+	if (using_checkpoints)
+	{ // using Model with checkpoints
+		Model m1(g2, false, true);//true=using_checkpoints
+		printf("\nModel built from the converted f%c genotype has %d checkpoints\n", g2.getFormat(), m1.getCheckpointCount());
+		Model m2(g1, false, true);//true=using_checkpoints
+		printf("Model built from the source f%c genotype has %d checkpoints\n", g1.getFormat(), m2.getCheckpointCount());
+		// accessing individual checkpoint models (if available)
+		if (m1.getCheckpointCount() > 0)
+		{
+			int c = m1.getCheckpointCount() / 2;
+			Model *cm = m1.getCheckpoint(c);
+			printf("Checkpoint #%d (%d parts, %d joint, %d neurons)\n%s", c, cm->getPartCount(), cm->getJointCount(), cm->getNeuroCount(), cm->getF0Geno().getGenesAndFormat().c_str());
+		}
+	}
 	else
-	{
-		printf("Conversion map:\n");
-		m.print();
-		printConvMap(g1.getGenes(), g2.getGenes(), m);
-		printf("Reverse conversion map:\n");
-		MultiMap rm;
-		rm.addReversed(m);
-		rm.print();
-		printConvMap(g2.getGenes(), g1.getGenes(), rm);
-	}
-
-	Model mod1(g1, 1);
-	printf("\nModel map for f%c genotype:\n", g1.getFormat());
-	printModelMap(g1.getGenes(), mod1.getMap());
-	mod1.getMap().print();
-	Model mod2(g2, 1);
-	printf("\nModel map for f%c genotype:\n", g2.getFormat());
-	printModelMap(g2.getGenes(), mod2.getMap());
-	mod2.getMap().print();
+	{ // there is no mapping for checkpoints so it's nothing interesting to see here in the checkpoints mode
+		if (m.isEmpty())
+			printf("(conversion map not available)\n");
+		else
+		{
+			printf("Conversion map:\n");
+			m.print();
+			printConvMap(g1.getGenes(), g2.getGenes(), m);
+			printf("Reverse conversion map:\n");
+			MultiMap rm;
+			rm.addReversed(m);
+			rm.print();
+			printConvMap(g2.getGenes(), g1.getGenes(), rm);
+		}
+
+		Model mod1(g1, 1);
+		printf("\nModel map for f%c genotype:\n", g1.getFormat());
+		printModelMap(g1.getGenes(), mod1.getMap());
+		MultiMap mod1combined;
+		mod1combined.addCombined(mod1.getMap(), getModelDisplayMap());
+		mod1combined.print();
+		Model mod2(g2, 1);
+		printf("\nModel map for f%c genotype:\n", g2.getFormat());
+		printModelMap(g2.getGenes(), mod2.getMap());
+		MultiMap mod2combined;
+		mod2combined.addCombined(mod2.getMap(), getModelDisplayMap());
+		mod2combined.print();
+	}
 	return 0;
 }
Index: cpp/frams/_demos/genotypeloader.cpp
===================================================================
--- cpp/frams/_demos/genotypeloader.cpp	(revision 730)
+++ cpp/frams/_demos/genotypeloader.cpp	(revision 732)
@@ -5,59 +5,10 @@
 #include "genotypeloader.h"
 
-#define FIELDSTRUCT MiniGenotype
-ParamEntry minigenotype_paramtab[] =
-{
-	{ "Genotype", 1, 29, "org", },
 
-	{ "name", 0, 0, "Name", "s 0 40", FIELD(name), },
-	{ "genotype", 0, 0, "Genotype", "s 1", FIELD(genotype), "Genes as a string of characters.", },
+GenotypeMiniLoader::GenotypeMiniLoader() :genotype_param(genotypemini_paramtab, &genotype_object) { init(); }
+GenotypeMiniLoader::GenotypeMiniLoader(VirtFILE *f) : MultiParamLoader(f), genotype_param(genotypemini_paramtab, &genotype_object) { init(); }
+GenotypeMiniLoader::GenotypeMiniLoader(const char* filename) : MultiParamLoader(filename), genotype_param(genotypemini_paramtab, &genotype_object) { init(); }
 
-	{ "info_timestamp", 1, 0, "Last modified", "ft 0 -1 0", FIELD(info_timestamp), },
-	{ "info_author", 1, 0, "Author name", "s 0 100", FIELD(info_author), },
-	{ "info_author_ispublic", 1, 0, "Author name is public", "d 0 1 1", FIELD(info_author_ispublic), },
-	{ "info_email", 1, 0, "Author email", "s 0 100", FIELD(info_email), },
-	{ "info_email_ispublic", 1, 0, "Author email is public", "d 0 1 0", FIELD(info_email_ispublic), },
-	{ "info", 1, 0, "Description", "s 1 1000", FIELD(info), "Short description of key features of this creature.", },
-	{ "info_origin", 1, 0, "Origin", "d 0 4 0 ~Unspecified~Designed~Designed and evolved~Evolved under various conditions~Evolved using single, constant setup", FIELD(info_origin), "Declaration of how this genotype originated." },
-	{ "info_how_created", 1, 0, "How created", "s 1 1000", FIELD(info_how_created), "Description of the process of designing and/or evolving this genotype." },
-	{ "info_performance", 1, 0, "Performance notes", "s 1 1000", FIELD(info_performance), "Description of why this genotype is special/interesting and how it performs." }, 
-
-	{ "energy0", 0, 0, "Starting energy", "f 0 -1 0", FIELD(energy0), },
-	{ "numparts", 0, 0, "Body parts", "d", FIELD(numparts), },
-	{ "numjoints", 0, 0, "Body joints", "d", FIELD(numjoints), },
-	{ "numneurons", 0, 0, "Brain size", "d", FIELD(numneurons), },
-	{ "numconnections", 0, 0, "Brain connections", "d", FIELD(numconnections), },
-
-	{ "num", 0, 0, "Ordinal number", "d", FIELD(ordnumber), },
-	{ "gnum", 0, 0, "Generation", "d", FIELD(generation), },
-
-	{ "instances", 0, 0, "Instances", "d", FIELD(instances), "Copies of this genotype", },
-
-	{ "lifespan", 0, 0, "Life span", "f", FIELD(lifespan), "Average life span", },
-	{ "velocity", 0, 0, "Velocity", "f", FIELD(velocity), "Average velocity", },
-	{ "distance", 0, 0, "Distance", "f", FIELD(distance), },
-	{ "vertvel", 0, 0, "Vertical velocity", "f", FIELD(vertvel), },
-	{ "vertpos", 0, 0, "Vertical position", "f", FIELD(vertpos), },
-
-	{ "user1", 0, 0, "User field 1", "x", FIELD(user1), },
-	{ "user2", 0, 0, "User field 2", "x", FIELD(user2), },
-	{ "user3", 0, 0, "User field 3", "x", FIELD(user3), },
-
-	{ "is_valid", 0, 0, "Validity", "d -1 1 -1", FIELD(is_valid),
-	"0 = invalid genotype\n"
-	"1 = valid genotype\n"
-	"-1 = validity is not known." },
-
-	{ "uid", 0, 0, "#", "s", FIELD(uid), "Unique identifier" },
-
-	{ 0, 0, 0, },
-};
-#undef FIELDSTRUCT
-
-MiniGenotypeLoader::MiniGenotypeLoader() :genotype_param(minigenotype_paramtab, &genotype_object) { init(); }
-MiniGenotypeLoader::MiniGenotypeLoader(VirtFILE *f) : MultiParamLoader(f), genotype_param(minigenotype_paramtab, &genotype_object) { init(); }
-MiniGenotypeLoader::MiniGenotypeLoader(const char* filename) : MultiParamLoader(filename), genotype_param(minigenotype_paramtab, &genotype_object) { init(); }
-
-void MiniGenotypeLoader::init()
+void GenotypeMiniLoader::init()
 {
 	addObject(&genotype_param);
@@ -65,5 +16,5 @@
 }
 
-MiniGenotype* MiniGenotypeLoader::loadNextGenotype()
+GenotypeMini* GenotypeMiniLoader::loadNextGenotype()
 {
 	genotype_object.clear();
Index: cpp/frams/_demos/genotypeloader.h
===================================================================
--- cpp/frams/_demos/genotypeloader.h	(revision 730)
+++ cpp/frams/_demos/genotypeloader.h	(revision 732)
@@ -8,28 +8,5 @@
 #include <frams/util/sstring.h>
 #include <frams/param/multiparamload.h>
-
-/** Defines the association between "org:" object (found in genotype files)
-	and the MiniGenotype fields. MiniGenotypeLoader uses this definition
-	but you can also use it to make MultiParamLoader load genotype
-	*/
-extern ParamEntry minigenotype_paramtab[];
-
-/** Helper class, mostly useful with MultiParamLoader
-	or its specialized version: MiniGenotypeLoader.
-	MiniGenotype stores the subset of Genotype fields (the ones normally saved in .gen files)
-	*/
-class MiniGenotype
-{
-public:
-	SString name, genotype, info, uid;
-	double info_timestamp;
-	SString info_author, info_email;
-	paInt info_author_ispublic, info_email_ispublic, info_origin;
-	SString info_how_created, info_performance;
-	double energy0, lifespan, velocity, distance, vertvel, vertpos;
-	paInt numparts, numjoints, numneurons, numconnections, ordnumber, generation, instances, is_valid;
-	ExtValue user1, user2, user3;
-	void clear() { Param p(minigenotype_paramtab, this); p.setDefault(); }
-};
+#include "genotypemini.h"
 
 /** In most simple cases this is the class you would use to load a series of genotypes from
@@ -48,20 +25,20 @@
 	methods, or you can use it as a guide for creating your own specialized class.
 	*/
-class MiniGenotypeLoader : public MultiParamLoader
+class GenotypeMiniLoader : public MultiParamLoader
 {
-	MiniGenotype genotype_object;
+	GenotypeMini genotype_object;
 	Param genotype_param;
 	bool initialized;
 	void init();
 public:
-	MiniGenotypeLoader();
-	MiniGenotypeLoader(VirtFILE *f);
-	MiniGenotypeLoader(const char* filename);
+	GenotypeMiniLoader();
+	GenotypeMiniLoader(VirtFILE *f);
+	GenotypeMiniLoader(const char* filename);
 
 	/** @returns genotype object if one was loaded or NULL otherwise.
 
-		Returned MiniGenotype pointer always references the the same object (MiniGenotypeLoader::genotype_object)
+		Returned GenotypeMini pointer always references the the same object (GenotypeMiniLoader::genotype_object)
 		which means you may need to copy the data from it before calling loadNextGenotype() again.
-		In the default configuration (simple MiniGenotypeLoader) NULL is always final and should be used
+		In the default configuration (simple GenotypeMiniLoader) NULL is always final and should be used
 		to finish processing.
 
@@ -70,5 +47,5 @@
 		MultiParamLoader::finished() and other methods to determine the real cause of NULL.
 		*/
-	MiniGenotype* loadNextGenotype();
+	GenotypeMini* loadNextGenotype();
 };
 
Index: cpp/frams/_demos/genotypemini.cpp
===================================================================
--- cpp/frams/_demos/genotypemini.cpp	(revision 732)
+++ cpp/frams/_demos/genotypemini.cpp	(revision 732)
@@ -0,0 +1,108 @@
+#include "genotypemini.h"
+#include <frams/vm/classes/collectionobj.h>
+#include <common/log.h>
+
+#define FIELDSTRUCT GenotypeMini
+ParamEntry genotypemini_paramtab[] =
+{
+	{ "Genotype", 1, 31, "org", },
+
+	{ "name", 0, 0, "Name", "s 0 40", FIELD(name), },
+	{ "genotype", 0, 0, "Genotype", "s 1", FIELD(genotype), "Genes as a string of characters.", },
+
+	{ "info_timestamp", 1, 0, "Last modified", "ft 0 -1 0", FIELD(info_timestamp), },
+	{ "info_author", 1, 0, "Author name", "s 0 100", FIELD(info_author), },
+	{ "info_author_ispublic", 1, 0, "Author name is public", "d 0 1 1", FIELD(info_author_ispublic), },
+	{ "info_email", 1, 0, "Author email", "s 0 100", FIELD(info_email), },
+	{ "info_email_ispublic", 1, 0, "Author email is public", "d 0 1 0", FIELD(info_email_ispublic), },
+	{ "info", 1, 0, "Description", "s 1 1000", FIELD(info), "Short description of key features of this creature.", },
+	{ "info_origin", 1, 0, "Origin", "d 0 4 0 ~Unspecified~Designed~Designed and evolved~Evolved under various conditions~Evolved using single, constant setup", FIELD(info_origin), "Declaration of how this genotype originated." },
+	{ "info_how_created", 1, 0, "How created", "s 1 1000", FIELD(info_how_created), "Description of the process of designing and/or evolving this genotype." },
+	{ "info_performance", 1, 0, "Performance notes", "s 1 1000", FIELD(info_performance), "Description of why this genotype is special/interesting and how it performs." },
+
+	{ "energy0", 0, 0, "Starting energy", "f 0 -1 0", FIELD(energy0), },
+	{ "numparts", 0, 0, "Body parts", "d", FIELD(numparts), },
+	{ "numjoints", 0, 0, "Body joints", "d", FIELD(numjoints), },
+	{ "numneurons", 0, 0, "Brain size", "d", FIELD(numneurons), },
+	{ "numconnections", 0, 0, "Brain connections", "d", FIELD(numconnections), },
+
+	{ "num", 0, 0, "Ordinal number", "d", FIELD(ordnumber), },
+	{ "gnum", 0, 0, "Generation", "d", FIELD(generation), },
+
+	{ "instances", 0, 0, "Instances", "d", FIELD(instances), "Copies of this genotype", },
+
+	{ "lifespan", 0, 0, "Life span", "f", FIELD(lifespan), "Average life span", },
+	{ "velocity", 0, 0, "Velocity", "f", FIELD(velocity), "Average velocity", },
+	{ "distance", 0, 0, "Distance", "f", FIELD(distance), },
+	{ "vertvel", 0, 0, "Vertical velocity", "f", FIELD(vertvel), },
+	{ "vertpos", 0, 0, "Vertical position", "f", FIELD(vertpos), },
+
+	{ "user1", 0, 0, "User field 1", "x", FIELD(user1), },
+	{ "user2", 0, 0, "User field 2", "x", FIELD(user2), },
+	{ "user3", 0, 0, "User field 3", "x", FIELD(user3), },
+	{ "data", 3, PARAM_OBJECTSET, "Custom fields dictionary", "oDictionary", FIELD(data), },
+
+	{ "is_valid", 0, 0, "Validity", "d -1 1 -1", FIELD(is_valid),
+	"0 = invalid genotype\n"
+	"1 = valid genotype\n"
+	"-1 = validity is not known." },
+
+	{ "uid", 0, 0, "#", "s", FIELD(uid), "Unique identifier" },
+
+	{ "mutate", 0, 0, "Mutate", "p()", PROCEDURE(p_mutate), },
+
+	{ 0, 0, 0, },
+};
+#undef FIELDSTRUCT
+
+void GenotypeMini::initData()
+{
+	DictionaryObject *d = new DictionaryObject;
+	data = d->makeObject();
+}
+
+GenotypeMini::GenotypeMini()
+{
+	initData();
+}
+
+GenotypeMini::GenotypeMini(const GenotypeMini &src)
+{
+	initData();
+	name = src.name; genotype = src.genotype; info = src.info; uid = src.uid; info_timestamp = src.info_timestamp; info_author = src.info_author; info_email = src.info_email; info_author_ispublic = src.info_author_ispublic; info_email_ispublic = src.info_email_ispublic; info_origin = src.info_origin; info_how_created = src.info_how_created; info_performance = src.info_performance; energy0 = src.energy0; lifespan = src.lifespan; velocity = src.velocity; distance = src.distance; vertvel = src.vertvel; vertpos = src.vertpos; numparts = src.numparts; numjoints = src.numjoints; numneurons = src.numneurons; numconnections = src.numconnections; ordnumber = src.ordnumber; generation = src.generation; instances = src.instances; is_valid = src.is_valid; user1 = src.user1; user2 = src.user2; user3 = src.user3;
+
+	// special case for 'data' (Dictionary inside an ExtObject)
+	// 'data=src.data' would copy the Dictionary object reference (very wrong!)
+	// performing a shallow copy instead:
+	DictionaryObject *d = DictionaryObject::fromObject(data);
+	DictionaryObject *src_d = DictionaryObject::fromObject(src.data);
+	d->copyFrom(src_d);
+}
+
+void GenotypeMini::clear()
+{
+	Param p(genotypemini_paramtab, this);
+	p.setDefault();
+}
+
+static std::function<Geno(const Geno&)> genman_mutate;
+
+void GenotypeMini::useGenManMutate(std::function<Geno(const Geno&)> gmm)
+{
+	genman_mutate = gmm;
+}
+
+void GenotypeMini::p_mutate(ExtValue *args, ExtValue *ret)
+{
+	if (ret != NULL) ret->setEmpty();
+	if (!genman_mutate)
+	{
+		logPrintf("GenotypeMini", "mutate", LOG_ERROR, "No function for mutation provided. See GENOTYPEMINI_USE_GENMAN().");
+		return;
+	}
+	Geno in(genotype.c_str(), -1, name.c_str(), info.c_str());
+	Geno out = genman_mutate(in);
+	genotype = out.getGenesAndFormat();
+	name = out.getName();
+	info = out.getComment();
+}
Index: cpp/frams/_demos/genotypemini.h
===================================================================
--- cpp/frams/_demos/genotypemini.h	(revision 732)
+++ cpp/frams/_demos/genotypemini.h	(revision 732)
@@ -0,0 +1,48 @@
+#ifndef _GENOTYPEMINI_H_
+#define _GENOTYPEMINI_H_
+
+#include <frams/param/param.h>
+#include <frams/util/extvalue.h>
+#include <frams/genetics/geno.h>
+#include <functional>
+
+/** Defines the association between "org:" object (found in genotype files)
+	and the GenotypeMini fields. GenotypeMiniLoader uses this definition
+	but you can also use it to make MultiParamLoader load genotype
+	*/
+extern ParamEntry genotypemini_paramtab[];
+
+/** Helper class, mostly useful with MultiParamLoader
+	or its specialized version: MiniGenotypeLoader.
+	GenotypeMini stores the subset of Genotype fields (the ones normally saved in .gen files)
+	*/
+class GenotypeMini
+{
+public:
+	SString name, genotype, info, uid;
+	double info_timestamp;
+	SString info_author, info_email;
+	paInt info_author_ispublic, info_email_ispublic, info_origin;
+	SString info_how_created, info_performance;
+	double energy0, lifespan, velocity, distance, vertvel, vertpos;
+	paInt numparts, numjoints, numneurons, numconnections, ordnumber, generation, instances, is_valid;
+	ExtValue user1, user2, user3;
+	ExtObject data;
+	void clear();
+
+	GenotypeMini();
+	GenotypeMini(const GenotypeMini &src);
+	void initData();
+
+#define GENOTYPEMINI_USE_GENMAN(gm) GenotypeMini::useGenManMutate(std::bind(&GenMan::mutate,&(gm),std::placeholders::_1))
+	static void useGenManMutate(std::function<Geno(const Geno&)> gmm);
+	/** GenMan object must be provided before using the 'mutate()' operation, like this:
+		GENOTYPEMINI_USE_GENMAN(genetics.genman);
+		*/
+
+#define STATRICKCLASS GenotypeMini
+	PARAMPROCDEF(p_mutate);
+#undef STATRICKCLASS
+};
+
+#endif
Index: cpp/frams/_demos/geometry/geometrytestutils.cpp
===================================================================
--- cpp/frams/_demos/geometry/geometrytestutils.cpp	(revision 730)
+++ cpp/frams/_demos/geometry/geometrytestutils.cpp	(revision 732)
@@ -18,17 +18,17 @@
 	long count = 0;
 	long totalSize = 0;
-	MiniGenotypeLoader loader(file);
-	MiniGenotype *genotype;
-	
+	GenotypeMiniLoader loader(file);
+	GenotypeMini *genotype;
+
 	while (genotype = loader.loadNextGenotype())
 	{
 		count++;
 		totalSize += genotype->genotype.len();
-		
+
 		fprintf(stderr, "%d. (%6d chars) %s\n", count, genotype->genotype.len(),
 			genotype->name.c_str());
 	}
-	
-	if (loader.getStatus() == MiniGenotypeLoader::OnError)
+
+	if (loader.getStatus() == GenotypeMiniLoader::OnError)
 	{
 		fprintf(stderr, "Error: %s\n", loader.getError().c_str());
@@ -44,6 +44,6 @@
 class TestInvoker
 {
-	public:
-		virtual void operator()(Model &model) = 0;
+public:
+	virtual void operator()(Model &model) = 0;
 };
 
@@ -53,15 +53,15 @@
 	const int genoIndex = isdigit(genoId[0]) ? atol(genoId) : 0;
 	long count = 0;
-	MiniGenotypeLoader loader(file);
-	MiniGenotype *genotype;
-	
+	GenotypeMiniLoader loader(file);
+	GenotypeMini *genotype;
+
 	while (genotype = loader.loadNextGenotype())
 	{
 		count++;
-		
+
 		if ((genoIndex == count) || (strcmp(genotype->name.c_str(), genoName) == 0))
 		{
 			Model model(genotype->genotype);
-			
+
 			if (!model.isValid())
 			{
@@ -74,6 +74,6 @@
 		}
 	}
-	
-	if (loader.getStatus() == MiniGenotypeLoader::OnError)
+
+	if (loader.getStatus() == GenotypeMiniLoader::OnError)
 	{
 		fprintf(stderr, "Error: %s\n", loader.getError().c_str());
@@ -94,5 +94,5 @@
 	if ((shape < 1) || (shape > 3))
 	{
-		shape = (rand()%3) + 1;
+		shape = (rand() % 3) + 1;
 	}
 
@@ -106,24 +106,24 @@
 }
 
-class ModelBasedTestInvoker: public TestInvoker
-{
-	private:
-		void (*test)(Model &);
-	public:
-		ModelBasedTestInvoker(void (*_test)(Model &)):
-			test(_test)
-		{}
-		void operator()(Model &model)
-		{
-			test(model);
-		}
+class ModelBasedTestInvoker : public TestInvoker
+{
+private:
+	void(*test)(Model &);
+public:
+	ModelBasedTestInvoker(void(*_test)(Model &)) :
+		test(_test)
+	{}
+	void operator()(Model &model)
+	{
+		test(model);
+	}
 };
 
-int GeometryTestUtils::execute(const SString header, int argc, char *argv[], void (*test)(Model &))
+int GeometryTestUtils::execute(const SString header, int argc, char *argv[], void(*test)(Model &))
 {
 	LoggerToStdout messages_to_stdout(LoggerBase::Enable); //comment this object out to mute error/warning messages
 	StdioFileSystem_autoselect stdiofilesys;
 	PreconfiguredGenetics genetics;
-	
+
 	srand(time(NULL));
 
@@ -132,5 +132,5 @@
 		return printGenotypesList(argv[2]);
 	}
-	
+
 	if ((argc == 4) && (strcmp("-l", argv[1]) == 0))
 	{
@@ -138,5 +138,5 @@
 		return executeTestUsingLoadedModel(argv[2], argv[3], invoker);
 	}
-	
+
 	if ((argc == 2) && (strcmp("-c", argv[1]) == 0))
 	{
@@ -144,5 +144,5 @@
 		return executeTestUsingRandomModel(-1, invoker);
 	}
-	
+
 	if ((argc == 3) && (strcmp("-c", argv[1]) == 0) && isdigit(argv[2][0]))
 	{
@@ -151,5 +151,5 @@
 		return executeTestUsingRandomModel(shape, invoker);
 	}
-	
+
 	fprintf(stderr,
 		"%s\n\n"
@@ -165,28 +165,28 @@
 }
 
-class ModelAndDensityBasedTestInvoker: public TestInvoker
-{
-	private:
-		void (*test)(Model &, const double);
-		double density;
-	public:
-		ModelAndDensityBasedTestInvoker(void (*_test)(Model &, const double), double _density):
-			test(_test),
-			density(_density)
-		{}
-		
-		void operator()(Model &model)
-		{
-			test(model, density);
-		}
+class ModelAndDensityBasedTestInvoker : public TestInvoker
+{
+private:
+	void(*test)(Model &, const double);
+	double density;
+public:
+	ModelAndDensityBasedTestInvoker(void(*_test)(Model &, const double), double _density) :
+		test(_test),
+		density(_density)
+	{}
+
+	void operator()(Model &model)
+	{
+		test(model, density);
+	}
 };
 
 int GeometryTestUtils::execute(const SString header, int argc, char *argv[],
-	void (*test)(Model &, const double))
+	void(*test)(Model &, const double))
 {
 	LoggerToStdout messages_to_stdout(LoggerBase::Enable); //comment this object out to mute error/warning messages
 	StdioFileSystem_autoselect stdiofilesys;
 	PreconfiguredGenetics genetics;
-	
+
 	srand(time(NULL));
 
@@ -202,5 +202,5 @@
 		return executeTestUsingLoadedModel(argv[2], argv[3], invoker);
 	}
-	
+
 	if ((argc == 3) && (strcmp("-c", argv[1]) == 0) && isdigit(argv[2][0]))
 	{
@@ -209,5 +209,5 @@
 		return executeTestUsingRandomModel(-1, invoker);
 	}
-	
+
 	if ((argc == 4) && (strcmp("-c", argv[1]) == 0) && isdigit(argv[2][0]) && isdigit(argv[3][0]))
 	{
@@ -217,5 +217,5 @@
 		return executeTestUsingRandomModel(shape, invoker);
 	}
-	
+
 	fprintf(stderr,
 		"%s\n\n"
@@ -235,9 +235,9 @@
 {
 	Part *part = model.addNewPart(Part::SHAPE_ELLIPSOID);
-	
+
 	part->p = Pt3D(0);
 	part->scale = Pt3D(0.1);
 	part->vcolor = Pt3D(1.0, 0.0, 1.0);
-	
+
 	addAxesToModel(Pt3D(0.5), Orient(Orient_1), Pt3D(0.0), model);
 }
@@ -247,9 +247,9 @@
 	Part *anchor = model.getPart(0);
 	Part *part = model.addNewPart(Part::SHAPE_ELLIPSOID);
-	
+
 	part->p = Pt3D(markerLocation);
 	part->scale = Pt3D(0.05);
 	part->vcolor = Pt3D(1.0, 1.0, 0.0);
-	
+
 	model.addNewJoint(anchor, part, Joint::SHAPE_FIXED);
 }
@@ -260,5 +260,5 @@
 	Part *anchor = model.getPart(0);
 	Part *part;
-	
+
 	part = model.addNewPart(Part::SHAPE_CUBOID);
 	part->scale = Pt3D(sizes.x, 0.05, 0.05);
@@ -267,5 +267,5 @@
 	part->vcolor = Pt3D(1.0, 0.0, 0.0);
 	model.addNewJoint(anchor, part, Joint::SHAPE_FIXED);
-	
+
 	part = model.addNewPart(Part::SHAPE_CUBOID);
 	part->scale = Pt3D(0.05, sizes.y, 0.05);
@@ -274,5 +274,5 @@
 	part->vcolor = Pt3D(0.0, 1.0, 0.0);
 	model.addNewJoint(anchor, part, Joint::SHAPE_FIXED);
-	
+
 	part = model.addNewPart(Part::SHAPE_CUBOID);
 	part->scale = Pt3D(0.05, 0.05, sizes.z);
@@ -287,7 +287,7 @@
 	Part *targetAnchor = target.getPart(0);
 	Part *sourceAnchor = source.getPart(0);
-	
+
 	target.moveElementsFrom(source);
-	
+
 	target.addNewJoint(targetAnchor, sourceAnchor, Joint::SHAPE_FIXED);
 }
@@ -295,5 +295,5 @@
 double frand(double from, double width)
 {
-	return from + width * ((rand()%10000) / 10000.0);
+	return from + width * ((rand() % 10000) / 10000.0);
 }
 
Index: cpp/frams/_demos/loader_test_geno.cpp
===================================================================
--- cpp/frams/_demos/loader_test_geno.cpp	(revision 730)
+++ cpp/frams/_demos/loader_test_geno.cpp	(revision 732)
@@ -26,10 +26,10 @@
 	long count = 0, totalsize = 0;
 	StdioFileSystem_autoselect stdiofilesys;
-	MiniGenotypeLoader loader(argv[1]);
+	GenotypeMiniLoader loader(argv[1]);
 	const char* selected = (argc < 3) ? NULL : argv[2];
 	const char* field_name = (argc < 4) ? NULL : argv[3];
 	int selected_index = (selected&&isdigit(selected[0])) ? atol(selected) : 0;
 	// using char* constructor (passing the file name to open)
-	MiniGenotype *loaded;
+	GenotypeMini *loaded;
 	while (loaded = loader.loadNextGenotype())
 	{ // if loaded != NULL then the "org:" object data was
@@ -51,5 +51,5 @@
 			if (field_name)
 			{
-				Param p(minigenotype_paramtab, loaded);
+				Param p(genotypemini_paramtab, loaded);
 				int field_index = p.findId(field_name);
 				if (field_index < 0)
@@ -68,5 +68,5 @@
 	}
 	// the loop repeats until loaded==NULL, which could be beacause of error
-	if (loader.getStatus() == MiniGenotypeLoader::OnError)
+	if (loader.getStatus() == GenotypeMiniLoader::OnError)
 		fprintf(stderr, "Error: %s", loader.getError().c_str());
 	// (otherwise it was the end of the file)
Index: cpp/frams/_demos/paramtree_paramlist_test.cpp
===================================================================
--- cpp/frams/_demos/paramtree_paramlist_test.cpp	(revision 730)
+++ cpp/frams/_demos/paramtree_paramlist_test.cpp	(revision 732)
@@ -22,5 +22,5 @@
 	PreconfiguredGenetics genetics;
 
-	Param minigenotype_param(minigenotype_paramtab);
+	Param genotypemini_param(genotypemini_paramtab);
 	NeuroFactory neurofac;
 	neurofac.setStandardImplementation();
@@ -36,5 +36,5 @@
 	combined += &Pt3D_Ext::getStaticParam();
 	combined += &Orient_Ext::getStaticParam();
-	combined += &minigenotype_param;
+	combined += &genotypemini_param;
 	combined += &nn_config.par;
 	combined += &modelgeo.par;
Index: cpp/frams/_demos/printconvmap.cpp
===================================================================
--- cpp/frams/_demos/printconvmap.cpp	(revision 730)
+++ cpp/frams/_demos/printconvmap.cpp	(revision 732)
@@ -1,4 +1,4 @@
 // This file is a part of Framsticks SDK.  http://www.framsticks.com/
-// Copyright (C) 1999-2015  Maciej Komosinski and Szymon Ulatowski.
+// Copyright (C) 1999-2018  Maciej Komosinski and Szymon Ulatowski.
 // See LICENSE.txt for details.
 
@@ -6,91 +6,109 @@
 #include <stdio.h>
 #include <frams/util/multimap.h>
+#include <frams/model/model.h>
 
 #define GEN1MAX 15
 
-void printN(const char* t,int maxlen)
+void printN(const char* t, int maxlen)
 {
-while(maxlen-- > 0)
-	if (*t) putchar(*(t++));
-	else putchar(' ');
+	while (maxlen-- > 0)
+		if (*t) putchar(*(t++));
+		else putchar(' ');
 }
 
-void printN(char t,int maxlen)
+void printN(char t, int maxlen)
 {
-while(maxlen-- > 0) putchar(t);
+	while (maxlen-- > 0) putchar(t);
 }
 
-void printmapping(const char* gen1, int len1,const MultiRange &mr,const char* gen2,int len2)
+void printmapping(const char* gen1, int len1, const MultiRange &mr, const char* gen2, int len2)
 {
-printN(' ',GEN1MAX-len1);
-printN(gen1,len1);
-printf(" : ");
-int i;
-for(i=0;i<len2;i++)
-	if (mr.contains(i))
-		putchar(gen2[i]);
-	else
-		putchar('.');
-putchar('\n');
+	printN(' ', GEN1MAX - len1);
+	printN(gen1, len1);
+	printf(" : ");
+	int i;
+	for (i = 0; i < len2; i++)
+		if (mr.contains(i))
+			putchar(gen2[i]);
+		else
+			putchar('.');
+	putchar('\n');
 }
 
 void stripstring(SString &str)
 {
-char *t=str.directWrite();
-for(;*t;t++)
-	if (strchr("\n\r\t",*t)) *t=' ';
+	char *t = str.directWrite();
+	for (; *t; t++)
+		if (strchr("\n\r\t", *t)) *t = ' ';
 }
 
-void printConvMap(const SString& gen1,const SString& gen2,const MultiMap& map)
+void printConvMap(const SString& gen1, const SString& gen2, const MultiMap& map)
 {
-int y,y2,len1;
-int id=0;
-if (map.isEmpty())
+	int y, y2, len1;
+	int id = 0;
+	if (map.isEmpty())
 	{
-	printf("{ empty }\n");
-	return;
+		printf("{ empty }\n");
+		return;
 	}
-len1=gen1.len();
-SString g1=gen1;
-stripstring(g1);
-SString g2=gen2;
-stripstring(g2);
-const char* g=g1.c_str();
-y=0;
-MultiRange *mr;
-MultiRange emptyrange;
-printN(' ',GEN1MAX);
-printf("   %s\n",g2.c_str());
-int begin=map.getBegin();
-int end=map.getEnd();
-while(y<len1)
+	len1 = gen1.len();
+	SString g1 = gen1;
+	stripstring(g1);
+	SString g2 = gen2;
+	stripstring(g2);
+	const char* g = g1.c_str();
+	y = 0;
+	MultiRange *mr;
+	MultiRange emptyrange;
+	printN(' ', GEN1MAX);
+	printf("   %s\n", g2.c_str());
+	int begin = map.getBegin();
+	int end = map.getEnd();
+	while (y < len1)
 	{
-	if (y<begin)
+		if (y < begin)
 		{
-		mr=&emptyrange;
-		y2=begin;
+			mr = &emptyrange;
+			y2 = begin;
 		}
-	else if (y>end)
+		else if (y > end)
 		{
-		mr=&emptyrange;
-		y2=len1;
+			mr = &emptyrange;
+			y2 = len1;
 		}
-	else	{
-		id=map.findMappingId(y);
-		mr=&map.getMapping(id)->to;
-		y2=map.getMapping(id+1)->begin;
+		else	{
+			id = map.findMappingId(y);
+			mr = &map.getMapping(id)->to;
+			y2 = map.getMapping(id + 1)->begin;
 		}
-	if ((y2-y) > GEN1MAX) y2=y+GEN1MAX;
-	if (y2>(y+len1)) y2=y+len1;
-	printmapping(g+y,y2-y,*mr,g2.c_str(),g2.len());
-	y=y2;
+		if ((y2 - y) > GEN1MAX) y2 = y + GEN1MAX;
+		if (y2 > (y + len1)) y2 = y + len1;
+		printmapping(g + y, y2 - y, *mr, g2.c_str(), g2.len());
+		y = y2;
 	}
 }
 
-void printModelMap(const SString& gen1,const MultiMap& map)
+const MultiMap & getModelDisplayMap()
 {
-SString g2("012345678901234567890123456789");
-printN(' ',GEN1MAX);
-printf("   Parts     Joints    Neurons\n");
-printConvMap(gen1,g2,map);
+	static MultiMap display_map;
+	if (display_map.isEmpty())
+	{
+		for (int i = 0; i < 10; i++)
+		{
+			display_map.add(Model::partToMap(i), Model::partToMap(i), i, i);
+			display_map.add(Model::jointToMap(i), Model::jointToMap(i), 10 + i, 10 + i);
+			display_map.add(Model::neuroToMap(i), Model::neuroToMap(i), 20 + i, 20 + i);
+		}
+	}
+	return display_map;
 }
+
+void printModelMap(const SString& gen1, const MultiMap& map)
+{
+	MultiMap combined_map;
+	combined_map.addCombined(map, getModelDisplayMap());
+	SString g2("012345678901234567890123456789");
+	printN(' ', GEN1MAX);
+	printf("   Parts     Joints    Neurons\n");
+	printConvMap(gen1, g2, combined_map);
+}
Index: cpp/frams/_demos/printconvmap.h
===================================================================
--- cpp/frams/_demos/printconvmap.h	(revision 730)
+++ cpp/frams/_demos/printconvmap.h	(revision 732)
@@ -1,4 +1,4 @@
 // This file is a part of Framsticks SDK.  http://www.framsticks.com/
-// Copyright (C) 1999-2015  Maciej Komosinski and Szymon Ulatowski.
+// Copyright (C) 1999-2018  Maciej Komosinski and Szymon Ulatowski.
 // See LICENSE.txt for details.
 
@@ -10,6 +10,7 @@
 class MultiMap;
 
-void printConvMap(const SString& gen1,const SString& gen2,const MultiMap& map);
-void printModelMap(const SString& gen1,const MultiMap& map);
+void printConvMap(const SString& gen1, const SString& gen2, const MultiMap& map);
+void printModelMap(const SString& gen1, const MultiMap& map); //automaticaly combines the map with the ModelDisplayMap
+const MultiMap & getModelDisplayMap(); // mapping: true model -> display (so the regular map printing/debugging tools can be used for model maps, avoiding invonveniently huge numbers)
 
 #endif
Index: cpp/frams/_demos/saver_test_geno.cpp
===================================================================
--- cpp/frams/_demos/saver_test_geno.cpp	(revision 730)
+++ cpp/frams/_demos/saver_test_geno.cpp	(revision 732)
@@ -28,6 +28,6 @@
 	{
 		int N = atoi(argv[2]);
-		MiniGenotype g;
-		Param p(minigenotype_paramtab, &g);
+		GenotypeMini g;
+		Param p(genotypemini_paramtab, &g);
 		g.clear();
 		printf("Saving %d genotypes to %s\n", N, argv[1]);
Index: cpp/frams/_demos/simil_test.cpp
===================================================================
--- cpp/frams/_demos/simil_test.cpp	(revision 730)
+++ cpp/frams/_demos/simil_test.cpp	(revision 732)
@@ -125,6 +125,6 @@
 
 	long count = 0, totalsize = 0;
-	MiniGenotypeLoader loader(szFileName);
-	MiniGenotype *loaded;
+	GenotypeMiniLoader loader(szFileName);
+	GenotypeMini *loaded;
 	while (loaded = loader.loadNextGenotype())
 	{
@@ -147,5 +147,5 @@
 		}
 	}
-	if (loader.getStatus() == MiniGenotypeLoader::OnError)
+	if (loader.getStatus() == GenotypeMiniLoader::OnError)
 	{
 		printf("Error: %s", loader.getError().c_str());
