Index: cpp/frams/genetics/fS/fS_general.cpp
===================================================================
--- cpp/frams/genetics/fS/fS_general.cpp	(revision 958)
+++ cpp/frams/genetics/fS/fS_general.cpp	(revision 969)
@@ -10,14 +10,9 @@
 #include "frams/util/rndutil.h"
 #include "frams/neuro/neurolibrary.h"
-
+#include "../genooperators.h"
 
 int fS_Genotype::precision = 4;
-
-
-double round2(double var)
-{
-	double value = (int) (var * 100 + .5);
-	return (double) value / 100;
-}
+bool fS_Genotype::TURN_WITH_ROTATION = false;
+
 
 double fS_stod(const string&  str, int start, size_t* size)
@@ -30,4 +25,8 @@
 	{
 		throw fS_Exception("Invalid numeric value", start);
+	}
+	catch(const std::out_of_range& ex)
+	{
+		throw fS_Exception("Invalid numeric value; out of range", start);
 	}
 }
@@ -39,4 +38,5 @@
 	fr = _state->fr;
 	s = _state->s;
+	stif = _state->stif;
 }
 
@@ -55,9 +55,5 @@
 {
 	Orient rotmatrix = Orient_1;
-	rotmatrix.rotate(Pt3D(
-			Convert::toRadians(rotation.x),
-			Convert::toRadians(rotation.y),
-			Convert::toRadians(rotation.z)
-	));
+	rotmatrix.rotate(rotation);
 	vector = rotmatrix.transform(vector);
 }
@@ -115,10 +111,7 @@
 }
 
-Node::Node(Substring &restOfGeno, bool _modifierMode, bool _paramMode, bool _cycleMode, Node *_parent)
+Node::Node(Substring &restOfGeno, Node *_parent)
 {
 	parent = _parent;
-	modifierMode = _modifierMode;
-	paramMode = _paramMode;
-	cycleMode = _cycleMode;
 	partDescription = new Substring(restOfGeno);
 
@@ -293,5 +286,5 @@
 		return item->second;
 	else
-		return defaultParamValues.at(key);
+		return defaultValues.at(key);
 }
 
@@ -415,20 +408,25 @@
 }
 
-double getDistance(Pt3D radiiParent, Pt3D radii, Pt3D vector, Pt3D rotationParent, Pt3D rotation)
-{
+double Node::getDistance()
+{
+	Pt3D size = calculateSize();
+	Pt3D parentSize = parent->calculateSize();	// Here we are sure that parent is not nullptr
 	int parentSphereCount, sphereCount;
 	double parentSphereRadius, sphereRadius;
-	Pt3D *centersParent = findSphereCenters(parentSphereCount, parentSphereRadius, radiiParent, rotationParent);
-	Pt3D *centers = findSphereCenters(sphereCount, sphereRadius, radii, rotation);
+	Pt3D *centersParent = findSphereCenters(parentSphereCount, parentSphereRadius, parentSize, parent->getRotation());
+	Pt3D *centers = findSphereCenters(sphereCount, sphereRadius, size, getRotation());
 
 	double distanceThreshold = sphereRadius + parentSphereRadius;
 	double minDistance = 0.0;
-	double maxDistance = 2 * (max3(radiiParent) + max3(radii));
+	double maxDistance = 2 * (max3(parentSize) + max3(size));
 	double currentDistance = avg(maxDistance, minDistance);
 	int result = -1;
+	int iterationNo = 0;
 	while (result != ADJACENT)
 	{
-		Pt3D currentVector = vector * currentDistance;
+		iterationNo++;
+		Pt3D currentVector = state->v * currentDistance;
 		result = isCollision(centersParent, centers, parentSphereCount, sphereCount, currentVector, distanceThreshold);
+
 		if (result == DISJOINT)
 		{
@@ -440,6 +438,11 @@
 			currentDistance = avg(maxDistance, currentDistance);
 		}
+
+		if(maxDistance <= 0 || iterationNo > 1000)
+			throw fS_Exception("Computing of distances between parts failed", 0);
 		if (currentDistance > maxDistance)
+		{
 			throw fS_Exception("Internal error; then maximal distance between parts exceeded.", 0);
+		}
 		if (currentDistance < minDistance)
 			throw fS_Exception("Internal error; the minimal distance between parts exceeded.", 0);
@@ -449,8 +452,8 @@
 	delete[] centersParent;
 	delete[] centers;
-	return round2(currentDistance);
-}
-
-void Node::getState(State *_state, const Pt3D &parentSize)
+	return currentDistance;
+}
+
+void Node::getState(State *_state)
 {
 	if (state != nullptr)
@@ -473,7 +476,8 @@
 		else if (mod == MODIFIERS[2])
 			state->s *= multiplier;
-	}
-
-	Pt3D size = calculateSize();
+		else if (mod == MODIFIERS[3])
+			state->stif *= multiplier;
+	}
+
 	if (parent != nullptr)
 	{
@@ -481,9 +485,9 @@
 		state->rotate(getVectorRotation());
 
-		double distance = getDistance(parentSize, size, state->v, getRotation(), getRotation());
+		double distance = getDistance();
 		state->addVector(distance);
 	}
 	for (int i = 0; i < int(children.size()); i++)
-		children[i]->getState(state, size);
+		children[i]->getState(state);
 }
 
@@ -493,5 +497,5 @@
 	for (int i = 0; i < int(branches.size()); i++)
 	{
-		children.push_back(new Node(branches[i], modifierMode, paramMode, cycleMode, this));
+		children.push_back(new Node(branches[i], this));
 	}
 }
@@ -593,16 +597,13 @@
 Pt3D Node::getVectorRotation()
 {
-	double rx = getParam(ROT_X);
-	double ry = getParam(ROT_Y);
-	double rz = getParam(ROT_Z);
-	return Pt3D(rx, ry, rz);
+	return Pt3D(getParam(ROT_X), getParam(ROT_Y), getParam(ROT_Z));
 }
 
 Pt3D Node::getRotation()
 {
-	double rx = getParam(RX);
-	double ry = getParam(RY);
-	double rz = getParam(RZ);
-	return Pt3D(rx, ry, rz);
+	Pt3D rotation = Pt3D(getParam(RX), getParam(RY), getParam(RZ));
+	if(fS_Genotype::TURN_WITH_ROTATION)
+		rotation += getVectorRotation();
+	return rotation;
 }
 
@@ -614,5 +615,4 @@
 		addJointsToModel(model, parent);
 
-
 	for (int i = 0; i < int(neurons.size()); i++)
 	{
@@ -639,14 +639,14 @@
 {
 	part = new Part(partType);
-	part->p = Pt3D(round2(state->location.x),
-				   round2(state->location.y),
-				   round2(state->location.z));
-
-	part->friction = round2(getParam(FRICTION) * state->fr);
-	part->ingest = round2(getParam(INGESTION) * state->ing);
+	part->p = Pt3D(state->location.x,
+				   state->location.y,
+				   state->location.z);
+
+	part->friction = getParam(FRICTION) * state->fr;
+	part->ingest = getParam(INGESTION) * state->ing;
 	Pt3D size = calculateSize();
-	part->scale.x = round2(size.x);
-	part->scale.y = round2(size.y);
-	part->scale.z = round2(size.z);
+	part->scale.x = size.x;
+	part->scale.y = size.y;
+	part->scale.z = size.z;
 	part->setRot(getRotation());
 }
@@ -655,4 +655,7 @@
 {
 	Joint *j = new Joint();
+	j->stif = getParam(STIFFNESS) * state->stif;
+	j->rotstif = j->stif;
+
 	j->attachToParts(parent->part, part);
 	switch (joint)
@@ -698,10 +701,9 @@
 			if (i != 0)
 				result += NEURON_SEPARATOR;
-			if (n->getClassName() != "N")
-			{
-				result += n->getDetails();
-				if (!n->inputs.empty())
-					result += NEURON_INTERNAL_SEPARATOR;
-			}
+
+			result += n->getDetails();
+			if (!n->inputs.empty())
+				result += NEURON_INTERNAL_SEPARATOR;
+
 			for (auto it = n->inputs.begin(); it != n->inputs.end(); ++it)
 			{
@@ -714,5 +716,4 @@
 					result += SString::valueOf(it->second);
 				}
-
 			}
 		}
@@ -754,13 +755,13 @@
 
 
-bool Node::changeSizeParam(string paramKey, double multiplier, bool ensureCircleSection)
-{
-	double oldValue = getParam(paramKey);
-	params[paramKey] = oldValue * multiplier;
+bool Node::changeSizeParam(string key, bool ensureCircleSection)
+{
+	double oldValue = getParam(key);
+	params[key] = GenoOperators::mutateCreep('f', params[key], minValues.at(key), maxValues.at(key), true);
 	if (!ensureCircleSection || isPartSizeValid())
 		return true;
 	else
 	{
-		params[paramKey] = oldValue;
+		params[key] = oldValue;
 		return false;
 	}
@@ -786,17 +787,6 @@
 	{
 		string geno = genotype.c_str();
-		// M - modifier mode, S - standard mode
-		size_t modeSeparatorIndex = geno.find(':');
-		if (modeSeparatorIndex == string::npos)
-			throw fS_Exception("No mode separator", 0);
-
-		string modeStr = geno.substr(0, modeSeparatorIndex).c_str();
-		bool modifierMode = modeStr.find(MODIFIER_MODE) != string::npos;
-		bool paramMode = modeStr.find(PARAM_MODE) != string::npos;
-		bool cycleMode = modeStr.find(CYCLE_MODE) != string::npos;
-
-		int actualGenoStart = modeSeparatorIndex + 1;
-		Substring substring(geno.c_str(), actualGenoStart, geno.length() - actualGenoStart);
-		startNode = new Node(substring, modifierMode, paramMode, cycleMode, nullptr);
+		Substring substring(geno.c_str(), 0, geno.length());
+		startNode = new Node(substring, nullptr);
 		validateNeuroInputs();
 	}
@@ -816,15 +806,5 @@
 {
 	State *initialState = new State(Pt3D(0), Pt3D(1, 0, 0));
-	startNode->getState(initialState, Pt3D(1.0));
-}
-
-double fS_Genotype::randomParamMultiplier()
-{
-	double multiplier = 1 + fabs(RndGen.GaussStd());
-	if (multiplier > PARAM_MAX_MULTIPLIER)
-		multiplier = PARAM_MAX_MULTIPLIER;
-	if (rndUint(2) == 0)
-		multiplier = 1.0 / multiplier;
-	return multiplier;
+	startNode->getState(initialState);
 }
 
@@ -833,30 +813,5 @@
 	getState();
 	startNode->buildModel(model, nullptr);
-
 	buildNeuroConnections(model);
-
-	// Additional joints
-	vector<Node*> allNodes = getAllNodes();
-	for (int i = 0; i < int(allNodes.size()); i++)
-	{
-		Node *node = allNodes[i];
-		if (node->params.find(JOINT_DISTANCE) != node->params.end())
-		{
-			Node *otherNode = getNearestNode(allNodes, node);
-			if (otherNode != nullptr)
-			{
-				// If other node is close enough, add a joint
-				double distance = node->state->location.distanceTo(otherNode->state->location);
-				if (distance < node->params[JOINT_DISTANCE])
-				{
-					Joint *joint = new Joint();
-					joint->attachToParts(node->part, otherNode->part);
-
-					joint->shape = Joint::Shape::SHAPE_FIXED;
-					model.addJoint(joint);
-				}
-			}
-		}
-	}
 }
 
@@ -905,13 +860,4 @@
 	SString geno;
 	geno.memoryHint(100);     // Provide a small buffer from the start to improve performance
-
-	if (startNode->modifierMode)
-		geno += MODIFIER_MODE;
-	if (startNode->paramMode)
-		geno += PARAM_MODE;
-	if (startNode->cycleMode)
-		geno += CYCLE_MODE;
-
-	geno += ':';
 	startNode->getGeno(geno);
 	return geno;
@@ -1010,5 +956,5 @@
 		if (!nodes[i]->isPartSizeValid())
 		{
-			return nodes[i]->partDescription->start;
+			return 1 + nodes[i]->partDescription->start;
 		}
 	}
