Index: /cpp/frams/genetics/f9/f9_conv.cpp
===================================================================
--- /cpp/frams/genetics/f9/f9_conv.cpp	(revision 1156)
+++ /cpp/frams/genetics/f9/f9_conv.cpp	(revision 1157)
@@ -19,4 +19,5 @@
 
 const char* turtle_commands_f9 = "LRBFDU";
+int turtle_commands_f9_count = 6; //keep in sync, must equal strlen(turtle_commands_f9)
 
 //const char* turtle_commandsX_f9="-+0000";
Index: /cpp/frams/genetics/f9/f9_conv.h
===================================================================
--- /cpp/frams/genetics/f9/f9_conv.h	(revision 1156)
+++ /cpp/frams/genetics/f9/f9_conv.h	(revision 1157)
@@ -1,4 +1,4 @@
 // This file is a part of Framsticks SDK.  http://www.framsticks.com/
-// Copyright (C) 1999-2018  Maciej Komosinski and Szymon Ulatowski.
+// Copyright (C) 1999-2021  Maciej Komosinski and Szymon Ulatowski.
 // See LICENSE.txt for details.
 
@@ -17,4 +17,5 @@
 
 extern const char* turtle_commands_f9;
+extern int turtle_commands_f9_count;
 
 
Index: /cpp/frams/genetics/f9/f9_oper.cpp
===================================================================
--- /cpp/frams/genetics/f9/f9_oper.cpp	(revision 1156)
+++ /cpp/frams/genetics/f9/f9_oper.cpp	(revision 1157)
@@ -1,4 +1,4 @@
 // This file is a part of Framsticks SDK.  http://www.framsticks.com/
-// Copyright (C) 1999-2020  Maciej Komosinski and Szymon Ulatowski.
+// Copyright (C) 1999-2021  Maciej Komosinski and Szymon Ulatowski.
 // See LICENSE.txt for details.
 
@@ -7,4 +7,5 @@
 #include <common/nonstd.h> //rndUint, rndDouble
 #include <string.h>
+#include <assert.h>
 
 
@@ -13,5 +14,5 @@
 {
 	{ "Genetics: f9", 1, 1, },
-	{ "f9_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)", },
+	{ "f9_mut", 0, 0, "Mutation probability", "f 0 1 0", FIELD(mut_prob), "How many genes should be mutated during single mutation (1=all genes, 0.1=ten percent, 0=one gene)", },
 	{ 0, },
 };
@@ -47,47 +48,74 @@
 }
 
-///Very simple mutation
+void GenoOper_f9::mutate_replace(char *gene, int i)
+{
+	char oldgene = gene[i];
+	const char *pos = strchr(turtle_commands_f9, oldgene);
+	if (pos == NULL) //gene not in the set of allowed commands
+		gene[i] = turtle_commands_f9[rndUint(turtle_commands_f9_count)];
+	else
+		gene[i] = turtle_commands_f9[((pos - turtle_commands_f9) + 1 + rndUint(turtle_commands_f9_count - 1)) % turtle_commands_f9_count]; //always change to a different command
+	//printf("%c %c\n", oldgene, gene[i]);
+	assert(gene[i] != oldgene);
+}
+
+void GenoOper_f9::mutate_add_or_del(char *& gene, int len, int add_0_del_1)
+{
+	string newgeno(gene);
+	if (add_0_del_1 == 0) //add
+	{
+		int p = rndUint(len + 1);  //random location
+		//printf("before add: %s\n",(const char*)newgeno);
+		newgeno = newgeno.substr(0, p) + string(turtle_commands_f9 + rndUint(turtle_commands_f9_count), 1) + newgeno.substr(p);
+		//printf("after add: %s\n",(const char*)newgeno);
+	}
+	else //delete
+	{
+		int p = rndUint(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);
+	}
+	free(gene);
+	gene = strdup(newgeno.c_str()); //reallocate
+}
+
+///Simple mutation
 int GenoOper_f9::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 (rndDouble(1) < mut_prob) //normalize prob with the length of the genotype
+	if (mut_prob > 0)
+		for (int i = 0; i < len; i++)
 		{
-			char oldgene = gene[i];
-			gene[i] = turtle_commands_f9[rndUint(symbols)];
-			if (gene[i] != oldgene) changes++;
+			if (rndDouble(1) < mut_prob) //normalize prob with the length of the genotype
+			{
+				mutate_replace(gene, i);
+				changes++;
+			}
 		}
-	}
 
 	if (rndDouble(1) < mut_prob) //add or delete a random char
 	{
-		SString newgeno(gene);
-		if (rndUint(2) == 0) //add
-		{
-			int symbols = strlen(turtle_commands_f9);
-			int p = rndUint(len + 1);  //random location
-			//printf("before add: %s\n",(const char*)newgeno);
-			newgeno = newgeno.substr(0, p) + SString(turtle_commands_f9 + rndUint(symbols), 1) + newgeno.substr(p);
-			//printf("after add: %s\n",(const char*)newgeno);
-			changes++;
-		}
-		else if (len > 1) //delete
-		{
-			int p = rndUint(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.c_str()); //reallocate
+		int change_add_or_del = 1 + (len > 1); //either add a new symbol (1), or delete a random symbol (+(len>1))
+		int add_0_del_1 = rndUint(change_add_or_del);
+		mutate_add_or_del(gene, len, add_0_del_1);
+		changes++;
+	}
+
+	if (changes == 0) //if nothing changed so far, then fallback to minimal change: always changes one symbol
+	{
+		int change_what = len + 1 + (len > 1); //either replace an existing gene, or add a new symbol (+1), or delete a random symbol (+(len>1))
+		int change_selected = rndUint(change_what);
+		if (change_selected < len)
+			mutate_replace(gene, change_selected);
+		else
+			mutate_add_or_del(gene, len, change_selected - len);
+		changes++;
 	}
 
 	chg = (float)changes / len;
-	return changes > 0 ? GENOPER_OK : GENOPER_OPFAIL; //no changes => OPFAIL so that GenMan will call mutate again
+	return changes > 0 ? GENOPER_OK : GENOPER_OPFAIL; //no changes? (should never happen) => OPFAIL so that GenMan will call mutate again
 }
 
Index: /cpp/frams/genetics/f9/f9_oper.h
===================================================================
--- /cpp/frams/genetics/f9/f9_oper.h	(revision 1156)
+++ /cpp/frams/genetics/f9/f9_oper.h	(revision 1157)
@@ -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-2021  Maciej Komosinski and Szymon Ulatowski.
 // See LICENSE.txt for details.
 
@@ -20,4 +20,7 @@
 	const char* getSimplest() { return "R"; }
 
+	void mutate_replace(char *gene, int i); //helper for mutate()
+	void mutate_add_or_del(char *& gene, int len, int add_0_del_1); //helper for mutate()
+
 	double mut_prob; //mutation probability
 };
