Index: cpp/frams/genetics/f4/f4_general.cpp
===================================================================
--- cpp/frams/genetics/f4/f4_general.cpp	(revision 1249)
+++ cpp/frams/genetics/f4/f4_general.cpp	(revision 1259)
@@ -37,5 +37,5 @@
 {
 	nr = nnr;
-	type = CELL_UNDIFF;
+	type = f4_Cell_type::CELL_UNDIFF;
 	dadlink = ndad;
 	org = NULL;
@@ -62,5 +62,5 @@
 	{
 		// make sure it is a stick (and not a stick f4_Cell!)
-		if (ndad->type == CELL_STICK)
+		if (ndad->type == f4_Cell_type::CELL_STICK)
 		{
 			//firstend = ndad->lastend;
@@ -68,5 +68,5 @@
 			ndad->stickchildcount++;
 		}
-		if (ndad->type == CELL_NEURON)
+		if (ndad->type == f4_Cell_type::CELL_NEURON)
 		{
 			inertia = ndad->inertia;
@@ -84,5 +84,5 @@
 {
 	nr = nnr;
-	type = CELL_UNDIFF;
+	type = f4_Cell_type::CELL_UNDIFF;
 	dadlink = ndad;
 	org = nO;
@@ -112,5 +112,5 @@
 	{
 		// make sure it is a stick (and not a stick f4_Cell!)
-		if (ndad->type == CELL_STICK)
+		if (ndad->type == f4_Cell_type::CELL_STICK)
 		{
 			//firstend = ndad->lastend;
@@ -118,5 +118,5 @@
 			ndad->stickchildcount++;
 		}
-		if (ndad->type == CELL_NEURON)
+		if (ndad->type == f4_Cell_type::CELL_NEURON)
 		{
 			inertia = ndad->inertia;
@@ -173,5 +173,5 @@
 
 				// error: sticks cannot divide
-				if (type == CELL_STICK)
+				if (type == f4_Cell_type::CELL_STICK)
 				{
 					// cannot fix
@@ -181,5 +181,5 @@
 
 				// undiff divides
-				if (type == CELL_UNDIFF)
+				if (type == f4_Cell_type::CELL_UNDIFF)
 				{
 					// commacount is set only when daughter turns into X
@@ -194,5 +194,5 @@
 				}
 				// a neuron divides: create a new, duplicate connections
-				if (type == CELL_NEURON)
+				if (type == f4_Cell_type::CELL_NEURON)
 				{
 					// daughter cell
@@ -203,5 +203,5 @@
 					repeat.clear();
 					// it is a neuron from start
-					tmp->type = CELL_NEURON;
+					tmp->type = f4_Cell_type::CELL_NEURON;
 					// it has the same type as the parent neuron
 					tmp->neuclass = neuclass;
@@ -257,5 +257,5 @@
 				{
 					// error: still undiff
-					if (type == CELL_UNDIFF)
+					if (type == f4_Cell_type::CELL_UNDIFF)
 					{
 						// fix it: insert an 'X'
@@ -301,5 +301,5 @@
 			{
 				// error: if neuron
-				if (type == CELL_NEURON)
+				if (type == f4_Cell_type::CELL_NEURON)
 				{
 					// fix: delete it
@@ -331,5 +331,5 @@
 			{
 				// error: if neuron
-				if (type == CELL_NEURON) //some neurons have the same single-letter names as modifiers (for example G,S,D), but they are supposed to have is_neuroclass==true so they should indeed not be handled here
+				if (type == f4_Cell_type::CELL_NEURON) //some neurons have the same single-letter names as modifiers (for example G,S,D), but they are supposed to have is_neuroclass==true so they should indeed not be handled here
 				{//however, what we see here is actually modifiers such as IdqEbWL (so not valid neuroclasses) that occurred within an already differentiated cell of type==CELL_NEURON.
 					//printf("Handled as a modifier, but type==CELL_NEURON: '%c'\n", name);
@@ -346,5 +346,5 @@
 				// turn undiff. cell into a stick
 				// error: already differentiated
-				if (type != CELL_UNDIFF)
+				if (type != f4_Cell_type::CELL_UNDIFF)
 				{
 					// fix: delete this node
@@ -352,5 +352,5 @@
 					return;  // error code set -> stop further cells development
 				}
-				type = CELL_STICK;
+				type = f4_Cell_type::CELL_STICK;
 				// fix dad commacount and own anglepos
 				if (dadlink != NULL)
@@ -367,5 +367,5 @@
 				// connection to neuron
 				// error: not a neuron
-				if (type != CELL_NEURON)
+				if (type != f4_Cell_type::CELL_NEURON)
 				{
 					// fix: delete it
@@ -384,5 +384,5 @@
 				for (int i = 0; i < org->cell_count; i++)
 				{
-					if (org->C[i]->type == CELL_NEURON) neu_counter++;
+					if (org->C[i]->type == f4_Cell_type::CELL_NEURON) neu_counter++;
 					if (org->C[i] == this) { this_index = neu_counter - 1; break; }
 				}
@@ -398,5 +398,5 @@
 				for (from = 0; from < org->cell_count; from++)
 				{
-					if (org->C[from]->type == CELL_NEURON) neu_counter++;
+					if (org->C[from]->type == f4_Cell_type::CELL_NEURON) neu_counter++;
 					if (from_index == (neu_counter - 1)) break;
 				}
@@ -457,5 +457,5 @@
 				// neuron parameter
 				// error: not a neuron
-				if (type != CELL_NEURON)
+				if (type != f4_Cell_type::CELL_NEURON)
 				{
 					// fix: delete it
@@ -513,5 +513,5 @@
 		{
 			genoRange.add(gcur->pos, gcur->pos + int(gcur->name.length()) + 2 - 1); // +2 for N:
-			if (type != CELL_UNDIFF)
+			if (type != f4_Cell_type::CELL_UNDIFF)
 			{
 				// fix: delete this node
@@ -527,5 +527,5 @@
 			}
 			neuclass = gcur->neuclass;
-			type = CELL_NEURON;
+			type = f4_Cell_type::CELL_NEURON;
 			// change of type also halts development, to give other
 			// cells a chance for adjustment.  Namely, it is important
@@ -567,5 +567,5 @@
 	{
 		if (org->C[i]->dadlink == this)
-			if (org->C[i]->type == CELL_STICK)
+			if (org->C[i]->type == f4_Cell_type::CELL_STICK)
 				stickchildcount++;
 	}
@@ -575,7 +575,7 @@
 	else
 		P.muscle_bend_range = 1.0 / std::max(1, dadlink->stickchildcount); //bend range in f1: 0, 1 (line XX[|]) -> 100%, 2 (Y-shape X(X[|],X)) -> 50%, 3 (cross X(X[|],X,X)) -> 33%
-	//MacKo 2023-05: but shouldn't this formula ^^ also take commacount into consideration, like in f1?
-
-	if (type == CELL_STICK)
+	//MacKo 2023-05: but shouldn't this formula ^^ also take commacount into consideration, like in f1? Note: in f0, the range of a newly added muscle has the default value (1.0) until modified by mutation, and the range can be set to any value completely unrelated to the junction where the muscle is located. In f1, the range of a newly added muscle depends on the number of branches (commas) in the junction including empty branches (see also conv_f1_f0_branch_muscle_range), but can be overridden by the genotype due to mutation and any value can be directly set just as in f0 - e.g. X[|,r:0.8] - so the value based on the number of commas only serves as a default. Compared to f0 and f1, f4 enforces a specific range here and this cannot be changed in any way, because as of now (2023-05) there is no support to mutate neural properties except for the N neuron.
+
+	if (type == f4_Cell_type::CELL_STICK)
 	{
 		if (dadlink == NULL)
@@ -716,7 +716,7 @@
 	for (int i = 0; i < cell_count; i++)
 	{
-		if (C[i]->type == CELL_NEURON)
-		{
-			while (C[i]->dadlink->type == CELL_NEURON)
+		if (C[i]->type == f4_Cell_type::CELL_NEURON)
+		{
+			while (C[i]->dadlink->type == f4_Cell_type::CELL_NEURON)
 			{
 				C[i]->dadlink = C[i]->dadlink->dadlink;
@@ -729,7 +729,7 @@
 	for (int i = 0; i < cell_count; i++)
 	{
-		if (C[i]->type == CELL_UNDIFF)
-		{
-			C[i]->type = CELL_STICK;
+		if (C[i]->type == f4_Cell_type::CELL_UNDIFF)
+		{
+			C[i]->type = f4_Cell_type::CELL_STICK;
 			//setError();
 		}
@@ -764,8 +764,8 @@
 		switch (c->type)
 		{
-		case CELL_UNDIFF: type = "undiff"; break;
-		case CELL_STICK:  type = "STICK"; break;
-		case CELL_NEURON: type = string("NEURON:") + c->neuclass->name.c_str(); break;
-		default: type = std::to_string(c->type);
+		case f4_Cell_type::CELL_UNDIFF: type = "undiff"; break;
+		case f4_Cell_type::CELL_STICK:  type = "STICK"; break;
+		case f4_Cell_type::CELL_NEURON: type = string("NEURON:") + c->neuclass->name.c_str(); break;
+		default: type = std::to_string(static_cast<int>(c->type));
 		}
 		const char *status = c->gcur == c->old_gcur ? (c->gcur != NULL ? "no progress" : "") : (c->gcur != NULL ? "progress" : "finished"); //progress or no progress means the cell is yielding = not finished but decided to halt development and wait for other cells. New cells may be created in case of "no progress" status.
@@ -893,5 +893,5 @@
 	if (curc >= cell_count) return;
 
-	if (C[curc]->type != CELL_STICK) return;
+	if (C[curc]->type != f4_Cell_type::CELL_STICK) return;
 
 	f4_Cell *thisti = C[curc];
@@ -899,6 +899,12 @@
 		*tmpcel = *(thisti->dadlink);
 
-	// adjust length, curvedness, etc.
+	// Adjust length, curvedness, etc.
 	tmpcel->P.propagateAlong(false);
+
+	// The sequence of "while" loops below is a fast and simple heuristic (decrease as long as the value is too big, then increase as long as the value is too small).
+	// However, since every different sequence of upper- and lower-case modifiers produces a different value of a given property,
+	// all 2^N sequences should be tested to discover the best approximation of the target value of a given property using N modifiers.
+	// This issue is TODO if anybody needed this function (and modifier sequences it produces) for any serious use. Also, add support for Qq.
+	// See also GenoOperators::simplifiedModifiers() and geneprops_test.cpp.
 	while (tmpcel->P.length > thisti->P.length)
 	{
@@ -938,5 +944,5 @@
 	for (int i = 0; i < cell_count; i++)
 	{
-		if (C[i]->type == CELL_NEURON)
+		if (C[i]->type == f4_Cell_type::CELL_NEURON)
 		{
 			if (C[i]->dadlink == thisti)
@@ -971,5 +977,5 @@
 	for (int i = 0; i < cell_count; i++)
 	{
-		if (C[i]->type == CELL_STICK)
+		if (C[i]->type == f4_Cell_type::CELL_STICK)
 		{
 			if (C[i]->dadlink == thisti)
