Index: cpp/frams/Makefile-GDK-files
===================================================================
--- cpp/frams/Makefile-GDK-files	(revision 139)
+++ cpp/frams/Makefile-GDK-files	(revision 140)
@@ -2,8 +2,8 @@
 
 # ALL_DIRS is later expanded by the shell, no spaces/newlines allowed, or it breaks
-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/model,frams/neuro,frams/neuro/impl,frams/param,frams/test,frams/util,frams/vm/classes,frams/virtfile,frams/_demos}
+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
-GENMAN_GDK_OBJS=frams/genetics/f9/oper_f9.o
+GENOCONV_GDK_OBJS=frams/genetics/f1/conv_f1.o frams/genetics/f9/conv_f9.o frams/genetics/fF/conv_fF.o
+GENMAN_GDK_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
Index: cpp/frams/genetics/fF/conv_fF.cpp
===================================================================
--- cpp/frams/genetics/fF/conv_fF.cpp	(revision 140)
+++ cpp/frams/genetics/fF/conv_fF.cpp	(revision 140)
@@ -0,0 +1,50 @@
+// 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 "conv_fF.h"
+#include "fF_genotype.h"
+#include <frams/model/model.h>
+#include <common/nonstd_stl.h>
+
+GenoConv_fF0::GenoConv_fF0()
+{
+	name = "7-value Foraminifera encoding";
+	in_format = 'F';
+	out_format = '0';
+	mapsupport = 0;
+}
+
+SString GenoConv_fF0::convert(SString &in, MultiMap *map)
+{
+	fF_growth_params gp;
+	gp.load(in);
+	Model m;
+	m.open();
+	// subsequent parts (chambers) are placed relative to the previous part's orientation and location
+	Part *p1, *p2;
+	p1 = m.addNewPart(Part::SHAPE_ELLIPSOID); //initial part
+	Pt3D scaling(gp.scalex, gp.scaley, gp.scalez);
+	p1->scale = scaling;
+
+	Orient rotation = Orient_1; //must be initialized explicitly because the default Orient constructor does not initialize anything
+	rotation.rotate(Pt3D(0, gp.angle1, gp.angle2)); //assumed rotation around x is 0, which is limiting if we use assymetrical shapes (i.e., not spheres). But the original model had only two angles...
+
+	for (int i = 0; i < gp.number_of_chambers; i++, p1 = p2)
+	{
+		p2 = m.addNewPart(Part::SHAPE_ELLIPSOID);
+		p2->scale = p1->scale.entrywiseProduct(scaling); //each part's scale is its predecessor's scale * scaling
+
+		p2->setOrient(p1->o.transform(rotation)); //rotation transformed by p1 orientation
+
+		// Part's tip (offset from the center) is the point at (scale.x,0,0) in part's local coordinates.
+		// Get the offset in global coordinates by transforming it by the part's orientation.
+		p2->p = p1->p
+			+ p1->o.transform(Pt3D(p1->scale.x*gp.translation,0,0))  // p1's tip transformed
+			+ p2->o.transform(Pt3D(p2->scale.x*gp.translation,0,0)); // p2's tip transformed
+
+		m.addNewJoint(p1, p2, Joint::SHAPE_SOLID); //all parts must be connected
+	}
+	m.close();
+	return m.getF0Geno().getGene();
+}
Index: cpp/frams/genetics/fF/conv_fF.h
===================================================================
--- cpp/frams/genetics/fF/conv_fF.h	(revision 140)
+++ cpp/frams/genetics/fF/conv_fF.h	(revision 140)
@@ -0,0 +1,28 @@
+// 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.
+
+#ifndef _CONV_FF_H_
+#define _CONV_FF_H_
+
+#include <frams/util/multimap.h>
+#include <frams/util/sstring.h>
+#include <frams/genetics/genoconv.h>
+
+
+
+// The f9->f0 converter
+class GenoConv_fF0: public GenoConverter
+{
+public:
+	GenoConv_fF0();
+
+	//implementation of the GenoConverter method
+	SString convert(SString &in, MultiMap *map);
+
+protected:
+	//auxiliary methods
+	//...
+};
+
+#endif
Index: cpp/frams/genetics/fF/fF_genotype.h
===================================================================
--- cpp/frams/genetics/fF/fF_genotype.h	(revision 140)
+++ cpp/frams/genetics/fF/fF_genotype.h	(revision 140)
@@ -0,0 +1,44 @@
+// 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.
+
+#ifndef _FF_GENOTYPE_H_
+#define _FF_GENOTYPE_H_
+
+#include <stdio.h>
+#include "common/stl-util.h"
+
+
+struct fF_growth_params
+{
+	int number_of_chambers;
+	double scalex, scaley, scalez; //scaling factors
+	double translation; //translation factor, TF range [−1; 1]
+	double angle1, angle2;
+
+	fF_growth_params()
+	{
+		reset();
+	}
+
+	void reset()
+	{
+		number_of_chambers = 1;
+		scalex = scaley = scalez = 1;
+		translation = 1;
+		angle1 = angle2 = 0;
+	}
+
+	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;
+	}
+
+	string save()
+	{
+		return ssprintf("%d %f %f %f %f %f %f", number_of_chambers, scalex, scaley, scalez, translation, angle1, angle2);
+	}
+};
+
+
+#endif
Index: cpp/frams/genetics/fF/oper_fF.cpp
===================================================================
--- cpp/frams/genetics/fF/oper_fF.cpp	(revision 140)
+++ cpp/frams/genetics/fF/oper_fF.cpp	(revision 140)
@@ -0,0 +1,125 @@
+// 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 "oper_fF.h"
+#include <frams/genetics/f9/conv_f9.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[]=
+{
+	{"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,},
+};
+#undef FIELDSTRUCT
+
+
+GenoOper_fF::GenoOper_fF()
+{
+	par.setParamTab(GENOf9param_tab);
+	par.select(this);
+	par.setDefault();
+	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;
+}
+
+///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
+	free(gene);
+	gene=strdup(validated); //reallocate
+	return GENOPER_OK;
+}
+
+///Very simple mutation
+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++)
+	{
+		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++;
+		}
+	}
+
+	if (rnd01<mut_prob) //add or delete a random char
+	{
+		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=(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)
+{
+	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);
+	return GENOPER_OK;
+}
+
+///Applying some colors and font styles...
+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);
+	}
+	return style;
+}
Index: cpp/frams/genetics/fF/oper_fF.h
===================================================================
--- cpp/frams/genetics/fF/oper_fF.h	(revision 140)
+++ cpp/frams/genetics/fF/oper_fF.h	(revision 140)
@@ -0,0 +1,25 @@
+// 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.
+
+#ifndef _GENOOPER_FF_H_
+#define _GENOOPER_FF_H_
+
+#include "../oper_fx.h"
+
+
+class GenoOper_fF : public GenoOperators
+{
+public:
+	GenoOper_fF();
+	int checkValidity(const char *);
+	int validate(char *&);
+	int mutate(char *&g, float& chg, int &method);
+	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"; }
+
+	double mut_prob; //mutation probability
+};
+
+#endif
Index: cpp/frams/genetics/gen-config-GDK.h
===================================================================
--- cpp/frams/genetics/gen-config-GDK.h	(revision 139)
+++ cpp/frams/genetics/gen-config-GDK.h	(revision 140)
@@ -19,4 +19,5 @@
 //#define USE_GENCONV_f50
 #define USE_GENCONV_f90
+#define USE_GENCONV_fF0
 
 //#define USE_GENMAN_f0
@@ -27,2 +28,3 @@
 //#define USE_GENMAN_f5
 #define USE_GENMAN_f9
+#define USE_GENMAN_fF
