Index: cpp/frams/model/model.cpp
===================================================================
--- cpp/frams/model/model.cpp	(revision 955)
+++ cpp/frams/model/model.cpp	(revision 972)
@@ -1,4 +1,4 @@
 // This file is a part of Framsticks SDK.  http://www.framsticks.com/
-// Copyright (C) 1999-2019  Maciej Komosinski and Szymon Ulatowski.
+// Copyright (C) 1999-2020  Maciej Komosinski and Szymon Ulatowski.
 // See LICENSE.txt for details.
 
@@ -11,11 +11,11 @@
 #define F0_CHECKPOINT_LINE "checkpoint:"
 
-Model::Model()
+Model::Model(ShapeType sh)
 {
 	autobuildmaps = false;
-	init();
-}
-
-void Model::init()
+	init(sh);
+}
+
+void Model::init(ShapeType sh)
 {
 	partmappingchanged = 0;
@@ -30,4 +30,10 @@
 	f0genoknown = 1;
 	shape = SHAPE_UNKNOWN;
+	declared_shape = sh;
+}
+
+void Model::declareShapeType(ShapeType sh)
+{
+	declared_shape = sh;
 }
 
@@ -51,4 +57,5 @@
 	f0genoknown = 0;
 	shape = mod.shape;
+	declared_shape = mod.declared_shape;
 	startenergy = mod.startenergy;
 	modelfromgenotype = mod.modelfromgenotype;
@@ -93,8 +100,8 @@
 
 
-Model::Model(const Geno &src, bool buildmaps, bool _using_checkpoints, bool _is_checkpoint)
+Model::Model(const Geno &src, ShapeType st, bool buildmaps, bool _using_checkpoints, bool _is_checkpoint)
 	:autobuildmaps(buildmaps)
 {
-	init(src, _using_checkpoints, _is_checkpoint);
+	init(src, st, _using_checkpoints, _is_checkpoint);
 }
 
@@ -110,5 +117,5 @@
 	:autobuildmaps(buildmaps)
 {
-	init();
+	init(mod.declared_shape);
 	open(_using_checkpoints, _is_checkpoint);
 	internalCopy(mod);
@@ -123,7 +130,7 @@
 }
 
-void Model::init(const Geno &src, bool _using_checkpoints, bool _is_checkpoint)
-{
-	init();
+void Model::init(const Geno &src, ShapeType sh, bool _using_checkpoints, bool _is_checkpoint)
+{
+	init(sh);
 	using_checkpoints = _using_checkpoints;
 	is_checkpoint = _is_checkpoint;
@@ -162,5 +169,5 @@
 	delMap();
 	delF0Map();
-	init();
+	init(declared_shape);
 	geno = Geno();
 	f0geno = Geno();
@@ -333,5 +340,8 @@
 	f0warnposition = -1;
 	MultiMap *convmap = autobuildmaps ? new MultiMap() : NULL;
-	f0geno = (geno.getFormat() == "0") ? geno : geno.getConverted("0", convmap, using_checkpoints);
+	if (declared_shape == SHAPE_UNKNOWN)
+		f0geno = geno.getConverted(Geno::F0_FORMAT_LIST, convmap, using_checkpoints);
+	else
+		f0geno = geno.getConverted(genoFormatForShapeType(declared_shape), convmap, using_checkpoints);
 	f0genoknown = 1;
 	if (f0geno.isInvalid())
@@ -467,5 +477,5 @@
 	modelparam.select(this);
 	modelparam.saveSingleLine(mod_props, handle_defaults ? &defaultmodel : NULL, true, !handle_defaults);
-	if (mod_props.len() > 1) //are there any non-default values? ("\n" is empty)
+	if (mod_props.length() > 1) //are there any non-default values? ("\n" is empty)
 	{
 		gen += "m:";
@@ -476,28 +486,28 @@
 	{
 		partparam.select(p);
-		len = gen.len();
+		len = gen.length();
 		gen += "p:";
 		partparam.saveSingleLine(gen, handle_defaults ? &defaultpart : NULL, true, !handle_defaults);
 		if (map)
-			map->add(len, gen.len() - 1, partToMap(i));
+			map->add(len, gen.length() - 1, partToMap(i));
 	}
 	for (i = 0; j = (Joint *)joints(i); i++)
 	{
 		jointparam.select(j);
-		len = gen.len();
+		len = gen.length();
 		jointparam.setParamTab(j->usedelta ? f0_joint_paramtab : f0_nodeltajoint_paramtab);
 		gen += "j:";
 		jointparam.saveSingleLine(gen, handle_defaults ? &defaultjoint : NULL, true, !handle_defaults);
 		if (map)
-			map->add(len, gen.len() - 1, jointToMap(i));
+			map->add(len, gen.length() - 1, jointToMap(i));
 	}
 	for (i = 0; n = (Neuro *)neurons(i); i++)
 	{
 		neuroparam.select(n);
-		len = gen.len();
+		len = gen.length();
 		gen += "n:";
 		neuroparam.saveSingleLine(gen, handle_defaults ? &defaultneuro : NULL, true, !handle_defaults);
 		if (map)
-			map->add(len, gen.len() - 1, neuroToMap(i));
+			map->add(len, gen.length() - 1, neuroToMap(i));
 	}
 	for (a = 0; a < neurons.size(); a++)
@@ -526,9 +536,9 @@
 				nc.info = **s;
 			connparam.select(&nc);
-			len = gen.len();
+			len = gen.length();
 			gen += "c:";
 			connparam.saveSingleLine(gen, handle_defaults ? &defaultconn : NULL, true, !handle_defaults);
 			if (map)
-				map->add(len, gen.len() - 1, neuroToMap(n->refno));
+				map->add(len, gen.length() - 1, neuroToMap(n->refno));
 		}
 	}
@@ -541,5 +551,43 @@
 	}
 
-	g = Geno(gen.c_str(), '0');
+	g = Geno(gen.c_str(), genoFormatForShapeType(getShapeType()), "", "");
+}
+
+SString Model::genoFormatForShapeType(ShapeType st)
+{
+	switch (st)
+	{
+	case SHAPE_BALL_AND_STICK:
+		return "0";
+	case SHAPE_SOLIDS:
+		return "0s";
+	default:
+		return Geno::INVALID_FORMAT;
+	}
+}
+
+Model::ShapeType Model::shapeTypeForGenoFormat(const SString& format)
+{
+	if (format == "0")
+		return SHAPE_BALL_AND_STICK;
+	else if (format == "0s")
+		return SHAPE_SOLIDS;
+	else
+		return SHAPE_UNKNOWN;
+
+}
+
+const char* Model::getShapeTypeName(ShapeType sh)
+{
+	switch (sh)
+	{
+	case SHAPE_BALL_AND_STICK: return "ball-and-stick";
+	case SHAPE_SOLIDS: return "solid shapes";
+	case SHAPE_UNKNOWN: return "unknown";
+
+	case SHAPE_ILLEGAL:
+	default:
+		return "illegal";
+	}
 }
 
@@ -653,5 +701,5 @@
 	if (result < 0)
 	{
-		if (error_message.len() == 0) // generic error when no detailed message is available
+		if (error_message.length() == 0) // generic error when no detailed message is available
 			error_message = "Invalid f0 code";
 		if (line_num > 0)
@@ -731,5 +779,5 @@
 		{
 			// default class for unparented units: standard neuron
-			if (nu->getClassName().len() == 0) nu->setClassName("N");
+			if (nu->getClassName().length() == 0) nu->setClassName("N");
 		}
 		/*
@@ -832,5 +880,5 @@
 SString Model::nameForErrors() const
 {
-	if (geno.getName().len() > 0)
+	if (geno.getName().length() > 0)
 		return SString::sprintf(" in '%s'", geno.getName().c_str());
 	return SString::empty();
@@ -1061,4 +1109,10 @@
 	if (shape == SHAPE_ILLEGAL)
 		ret = 0;
+	else if ((declared_shape != SHAPE_UNKNOWN) && (declared_shape != shape))
+	{
+		logPrintf("Model", "internalCheck", LOG_ERROR, "Model shape type '%s' does not match the declared type '%s'", getShapeTypeName(shape), getShapeTypeName(declared_shape));
+		ret = 0;
+	}
+
 	return ret;
 }
