Index: cpp/frams/genetics/fS/fS_general.cpp
===================================================================
--- cpp/frams/genetics/fS/fS_general.cpp	(revision 1006)
+++ cpp/frams/genetics/fS/fS_general.cpp	(revision 1017)
@@ -16,22 +16,62 @@
 int fS_Genotype::precision = 4;
 bool fS_Genotype::TURN_WITH_ROTATION = false;
+std::map<string, double> Node::minValues;
+std::map<string, double> Node::defaultValues;
+std::map<string, double> Node::maxValues;
 
 void Node::prepareParams()
 {
-	defaultValues = {
-			{INGESTION, Model::getDefPart().ingest},
-			{FRICTION,  Model::getDefPart().friction},
-			{STIFFNESS, Model::getDefJoint().stif},
-			{ROT_X,     0.0},
-			{ROT_Y,     0.0},
-			{ROT_Z,     0.0},
-			{RX,        0.0},
-			{RY,        0.0},
-			{RZ,        0.0},
-			{SIZE,      1.0},
-			{SIZE_X,    Model::getDefPart().scale.x},
-			{SIZE_Y,    Model::getDefPart().scale.y},
-			{SIZE_Z,    Model::getDefPart().scale.z}
-	};
+	if(minValues.empty())
+	{
+		minValues = {
+				{INGESTION, Model::getMinPart().ingest},
+				{FRICTION,  Model::getMinPart().friction},
+				{ROT_X,     -M_PI},
+				{ROT_Y,     -M_PI},
+				{ROT_Z,     -M_PI},
+				{RX,        -M_PI},
+				{RY,        -M_PI},
+				{RZ,        -M_PI},
+				{SIZE,      0.01},
+				{SIZE_X,    Model::getMinPart().scale.x},
+				{SIZE_Y,    Model::getMinPart().scale.y},
+				{SIZE_Z,    Model::getMinPart().scale.z}
+		};
+	}
+
+	if(maxValues.empty())
+	{
+		maxValues = {
+				{INGESTION, Model::getMaxPart().ingest},
+				{FRICTION,  Model::getMaxPart().friction},
+				{ROT_X,     M_PI},
+				{ROT_Y,     M_PI},
+				{ROT_Z,     M_PI},
+				{RX,        M_PI},
+				{RY,        M_PI},
+				{RZ,        M_PI},
+				{SIZE,      100.0},
+				{SIZE_X,    Model::getMaxPart().scale.x},
+				{SIZE_Y,    Model::getMaxPart().scale.y},
+				{SIZE_Z,    Model::getMaxPart().scale.z}
+		};
+	}
+	if(defaultValues.empty())
+	{
+		defaultValues = {
+				{INGESTION, Model::getDefPart().ingest},
+				{FRICTION,  Model::getDefPart().friction},
+				{ROT_X,     0.0},
+				{ROT_Y,     0.0},
+				{ROT_Z,     0.0},
+				{RX,        0.0},
+				{RY,        0.0},
+				{RZ,        0.0},
+				{SIZE,      1.0},
+				{SIZE_X,    Model::getDefPart().scale.x},
+				{SIZE_Y,    Model::getDefPart().scale.y},
+				{SIZE_Z,    Model::getDefPart().scale.z}
+		};
+	}
 }
 
@@ -58,5 +98,4 @@
 	fr = _state->fr;
 	s = _state->s;
-	stif = _state->stif;
 }
 
@@ -259,4 +298,5 @@
 	if(paramsEndIndex == -1)
 		throw fS_Exception("Lacking param end sign", restOfGenotype.start);
+
 	for (int i = 0; i < int(separators.size()) - 1; i++)
 	{
@@ -297,15 +337,22 @@
 }
 
-double Node::getParam(string key)
+double Node::getParam(const string &key)
 {
 	auto item = params.find(key);
 	if (item != params.end())
 		return item->second;
-	else
-		return defaultValues.at(key);
-}
-
-
-void Node::getState(State *_state)
+	return defaultValues.at(key);
+}
+
+double Node::getParam(const string &key, double defaultValue)
+{
+	auto item = params.find(key);
+	if (item != params.end())
+		return item->second;
+	return defaultValue;
+}
+
+
+void Node::getState(State *_state, bool calculateLocation)
 {
 	if (state != nullptr)
@@ -328,9 +375,7 @@
 		else if (mod == MODIFIERS[2])
 			state->s *= multiplier;
-		else if (mod == MODIFIERS[3])
-			state->stif *= multiplier;
-	}
-
-	if (parent != nullptr)
+	}
+
+	if (parent != nullptr && calculateLocation)
 	{
 		// Rotate
@@ -341,5 +386,5 @@
 	}
 	for (int i = 0; i < int(children.size()); i++)
-		children[i]->getState(state);
+		children[i]->getState(state, calculateLocation);
 }
 
@@ -388,11 +433,10 @@
 }
 
-Pt3D Node::calculateSize()
+void Node::calculateSize(Pt3D &scale)
 {
 	double sizeMultiplier = getParam(SIZE) * state->s;
-	double sx = getParam(SIZE_X) * sizeMultiplier;
-	double sy = getParam(SIZE_Y) * sizeMultiplier;
-	double sz = getParam(SIZE_Z) * sizeMultiplier;
-	return Pt3D(sx, sy, sz);
+	scale.x = getParam(SIZE_X) * sizeMultiplier;
+	scale.y = getParam(SIZE_Y) * sizeMultiplier;
+	scale.z = getParam(SIZE_Z) * sizeMultiplier;
 }
 
@@ -400,5 +444,6 @@
 {
 	double result;
-	Pt3D size = calculateSize();
+	Pt3D size;
+	calculateSize(size);
 	double radiiProduct = size.x * size.y * size.z;
 	switch (partType)
@@ -421,5 +466,6 @@
 bool Node::isPartSizeValid()
 {
-	Pt3D size = calculateSize();
+	Pt3D size;
+	calculateSize(size);
 	double volume = calculateVolume();
 	Part_MinMaxDef minP = Model::getMinPart();
@@ -449,10 +495,10 @@
 Pt3D Node::getVectorRotation()
 {
-	return Pt3D(getParam(ROT_X), getParam(ROT_Y), getParam(ROT_Z));
+	return Pt3D(getParam(ROT_X, 0.0), getParam(ROT_Y, 0.0), getParam(ROT_Z, 0.0));
 }
 
 Pt3D Node::getRotation()
 {
-	Pt3D rotation = Pt3D(getParam(RX), getParam(RY), getParam(RZ));
+	Pt3D rotation = Pt3D(getParam(RX, 0.0), getParam(RY, 0.0), getParam(RZ, 0.0));
 	if(fS_Genotype::TURN_WITH_ROTATION)
 		rotation += getVectorRotation();
@@ -492,14 +538,9 @@
 {
 	part = new Part(partType);
-	part->p = Pt3D(state->location.x,
-				   state->location.y,
-				   state->location.z);
+	part->p = Pt3D(state->location);
 
 	part->friction = getParam(FRICTION) * state->fr;
 	part->ingest = getParam(INGESTION) * state->ing;
-	Pt3D size = calculateSize();
-	part->scale.x = size.x;
-	part->scale.y = size.y;
-	part->scale.z = size.z;
+	calculateSize(part->scale);
 	part->setRot(getRotation());
 }
@@ -508,7 +549,4 @@
 {
 	Joint *j = new Joint();
-	j->stif = getParam(STIFFNESS) * state->stif;
-	j->rotstif = j->stif;
-
 	j->attachToParts(parent->part, part);
 	switch (joint)
@@ -650,8 +688,8 @@
 }
 
-void fS_Genotype::getState()
+void fS_Genotype::getState(bool calculateLocation)
 {
 	State *initialState = new State(Pt3D(0), Pt3D(1, 0, 0));
-	startNode->getState(initialState);
+	startNode->getState(initialState, calculateLocation);
 }
 
@@ -662,5 +700,5 @@
 	model.open(using_checkpoints);
 
-	getState();
+	getState(true);
 	startNode->buildModel(model, nullptr);
 	buildNeuroConnections(model);
@@ -808,5 +846,5 @@
 int fS_Genotype::checkValidityOfPartSizes()
 {
-	getState();
+	getState(false);
 	vector<Node*> nodes = getAllNodes();
 	for (int i = 0; i < int(nodes.size()); i++)
