Index: /java/main/src/main/java/com/framsticks/communication/ClientSideManagedConnection.java
===================================================================
--- /java/main/src/main/java/com/framsticks/communication/ClientSideManagedConnection.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/communication/ClientSideManagedConnection.java	(revision 107)
@@ -80,5 +80,5 @@
 		protocolVersion = -1;
 		requestedFeatures.add("request_id");
-		requestedFeatures.add("call_empty_result");
+		// requestedFeatures.add("call_empty_result");
 		requestedFeatures.add("needfile_id");
 	}
Index: /java/main/src/main/java/com/framsticks/communication/ServerSideManagedConnection.java
===================================================================
--- /java/main/src/main/java/com/framsticks/communication/ServerSideManagedConnection.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/communication/ServerSideManagedConnection.java	(revision 107)
@@ -56,8 +56,8 @@
 					return;
 				}
-				if (feature.equals("call_empty_result")) {
-					responseCallback.pass(new Response(true, null));
-					return;
-				}
+				// if (feature.equals("call_empty_result")) {
+				// 	responseCallback.pass(new Response(true, null));
+				// 	return;
+				// }
 				if (feature.equals("needfile_id")) {
 					responseCallback.pass(new Response(true, null));
Index: /java/main/src/main/java/com/framsticks/experiment/AbstractExperimentLogic.java
===================================================================
--- /java/main/src/main/java/com/framsticks/experiment/AbstractExperimentLogic.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/experiment/AbstractExperimentLogic.java	(revision 107)
@@ -15,4 +15,5 @@
 	 * @return the experiment
 	 */
+	@Override
 	public Experiment getExperiment() {
 		return experiment;
Index: /java/main/src/main/java/com/framsticks/experiment/Experiment.java
===================================================================
--- /java/main/src/main/java/com/framsticks/experiment/Experiment.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/experiment/Experiment.java	(revision 107)
@@ -1,4 +1,6 @@
 package com.framsticks.experiment;
 
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 
@@ -8,4 +10,5 @@
 
 import com.framsticks.params.EventListener;
+import com.framsticks.params.MessageLogger;
 import com.framsticks.params.ParamFlags;
 import com.framsticks.params.SimpleUniqueList;
@@ -13,7 +16,8 @@
 import com.framsticks.params.annotations.FramsClassAnnotation;
 import com.framsticks.params.annotations.ParamAnnotation;
-import com.framsticks.params.types.ProcedureParam;
 import com.framsticks.remote.RemoteTree;
+import com.framsticks.structure.Path;
 import com.framsticks.structure.messages.ListChange;
+import com.framsticks.structure.messages.Message;
 import com.framsticks.util.ExceptionHandler;
 import com.framsticks.util.FramsticksException;
@@ -23,4 +27,6 @@
 import com.framsticks.util.dispatching.DispatcherSetable;
 import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.Future;
+import com.framsticks.util.dispatching.FutureHandler;
 import com.framsticks.util.dispatching.Joinable;
 import com.framsticks.util.dispatching.JoinableCollection;
@@ -43,6 +49,9 @@
 	protected final BufferedDispatcher<Experiment> bufferedDispatcher = new BufferedDispatcher<>(this);
 
+	protected SimulatorProvider simulatorProvider;
+
 	protected String expdef;
 
+	protected final MessageLogger messages = new MessageLogger(NetLoadSaveLogic.class);
 
 	/**
@@ -90,4 +99,21 @@
 
 	/**
+	 * @return the simulatorProvider
+	 */
+	@ParamAnnotation(flags = ParamFlags.USERREADONLY)
+	public SimulatorProvider getSimulatorProvider() {
+		return simulatorProvider;
+	}
+
+	/**
+	 * @param simulatorProvider the simulatorProvider to set
+	 */
+	@AutoAppendAnnotation
+	@ParamAnnotation
+	public void setSimulatorProvider(SimulatorProvider simulatorProvider) {
+		this.simulatorProvider = simulatorProvider;
+	}
+
+	/**
 	 * @return the expdef
 	 */
@@ -118,8 +144,10 @@
 	@AutoAppendAnnotation
 	public void addSimulator(Simulator simulator) {
+		log.debug("add simulator {}", simulator);
 		simulators.add(simulator);
 		simulatorAsJoinables.add(simulator);
 		simulators.fireChildrenChange(simulator, ListChange.Action.Modify, "ready");
 
+		simulatorCandidates.remove(simulator.getRemoteTree());
 	}
 
@@ -156,5 +184,8 @@
 
 		Dispatching.use(simulatorAsJoinables, this);
+		Dispatching.use(simulatorProvider, this);
 		Dispatching.use(simulatorCandidates, this);
+
+		tryProvideAllSimulators(Future.<List<Simulator>>doNothing(this));
 	}
 
@@ -163,5 +194,8 @@
 
 		Dispatching.drop(simulatorAsJoinables, this);
+		Dispatching.drop(simulatorProvider, this);
 		Dispatching.drop(simulatorCandidates, this);
+
+		Dispatching.drop(bufferedDispatcher, this);
 
 		finishJoinable();
@@ -175,9 +209,9 @@
 	@Override
 	protected void joinableJoin() throws InterruptedException {
-		Dispatching.drop(bufferedDispatcher, this);
 
 		Dispatching.join(simulatorAsJoinables);
+		Dispatching.join(simulatorProvider);
 		Dispatching.join(simulatorCandidates);
-		Dispatching.join(bufferedDispatcher.getTargetDispatcher());
+		// Dispatching.join(bufferedDispatcher.getTargetDispatcher());
 	}
 
@@ -197,9 +231,62 @@
 	}
 
-	@ParamAnnotation(paramType = ProcedureParam.class)
-	public void connectToSimulator(String address) {
-		SimulatorConnector connector = new SimulatorConnector();
-		connector.setAddress(address);
-		connector.attachTo(this);
+	// @ParamAnnotation(paramType = ProcedureParam.class)
+	// public void connectToSimulator(String address) {
+	//	SimulatorConnector connector = new SimulatorConnector();
+	//	connector.setAddress(address);
+	//	connector.attachTo(this);
+	// }
+	//
+
+	public Simulator createSimulator(RemoteTree tree, Path path) {
+		return new Simulator(this, tree, path);
+	}
+
+	public void tryProvideNextSimulator(final FutureHandler<Simulator> future) {
+		log.debug("trying to provide next simulator");
+		simulatorProvider.provideSimulator(new SimulatorSpecification(this, expdef), new Future<Simulator>(future) {
+
+			@Override
+			protected void result(Simulator result) {
+				assert isActive();
+				if (result != null) {
+					addSimulator(result);
+				} else {
+					log.debug("no more simulators remaining");
+				}
+				future.pass(result);
+
+			}
+		});
+
+	}
+
+	public void tryProvideAllSimulators(final FutureHandler<List<Simulator>> future) {
+		log.debug("trying to provide all simulators");
+		final List<Simulator> list = new LinkedList<>();
+
+		tryProvideNextSimulator(new Future<Simulator>(future) {
+
+			@Override
+			protected void result(Simulator result) {
+				if (result == null) {
+					future.pass(list);
+					return;
+				}
+				list.add(result);
+				tryProvideNextSimulator(this);
+			}
+		});
+
+	}
+
+	@ParamAnnotation(id = "messages")
+	public void addMessageListener(EventListener<Message> listener) {
+		messages.add(listener);
+	}
+
+	@ParamAnnotation(id = "messages")
+	public void removeMessageListener(EventListener<Message> listener) {
+		messages.remove(listener);
 	}
 
Index: /java/main/src/main/java/com/framsticks/experiment/ExperimentLogic.java
===================================================================
--- /java/main/src/main/java/com/framsticks/experiment/ExperimentLogic.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/experiment/ExperimentLogic.java	(revision 107)
@@ -3,3 +3,5 @@
 public interface ExperimentLogic {
 
+	public Experiment getExperiment();
+
 }
Index: /java/main/src/main/java/com/framsticks/experiment/NetLoadSaveLogic.java
===================================================================
--- /java/main/src/main/java/com/framsticks/experiment/NetLoadSaveLogic.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/experiment/NetLoadSaveLogic.java	(revision 107)
@@ -18,5 +18,4 @@
 	private static final Logger log = LogManager.getLogger(NetLoadSaveLogic.class);
 
-	protected String option = "an option";
 
 	protected final Class<NF> netJavaClass;
@@ -95,20 +94,4 @@
 
 	/**
-	 * @return the option
-	 */
-	@ParamAnnotation
-	public String getOption() {
-		return option;
-	}
-
-	/**
-	 * @param option the option to set
-	 */
-	@ParamAnnotation
-	public void setOption(String option) {
-		this.option = option;
-	}
-
-	/**
 	 * @return the netJavaClass
 	 */
Index: /java/main/src/main/java/com/framsticks/experiment/Simulator.java
===================================================================
--- /java/main/src/main/java/com/framsticks/experiment/Simulator.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/experiment/Simulator.java	(revision 107)
@@ -157,4 +157,6 @@
 	@ParamAnnotation(paramType = ProcedureParam.class)
 	public void init() {
+		log.debug("initializing simulator {}", this);
+		call(simulatorPath, "init", arguments(), Object.class, Future.doNothing(Object.class, this));
 	}
 
@@ -168,4 +170,5 @@
 	public void stop() {
 		log.debug("stoping simulator {}", this);
+		call(simulatorPath, "stop", arguments(), Object.class, Future.doNothing(Object.class, this));
 	}
 
@@ -202,5 +205,5 @@
 
 	public <N> void netload(final N net, final FutureHandler<Object> future) {
-		final String netloadId = "NetLoadSaveLogic" + netloadIdCounter.getAndIncrement();
+		final String netloadId = "netload" + netloadIdCounter.getAndIncrement();
 
 		final File file = AccessOperations.convert(File.class, net, getRemoteTree().getRegistry());
Index: /java/main/src/main/java/com/framsticks/experiment/SimulatorConnector.java
===================================================================
--- /java/main/src/main/java/com/framsticks/experiment/SimulatorConnector.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/experiment/SimulatorConnector.java	(revision 107)
@@ -7,30 +7,75 @@
 import com.framsticks.communication.Address;
 import com.framsticks.params.annotations.FramsClassAnnotation;
-import com.framsticks.params.annotations.ParamAnnotation;
 import com.framsticks.remote.RemoteTree;
 import com.framsticks.structure.Path;
-import com.framsticks.util.AutoAttacher;
 import com.framsticks.util.Misc;
 import com.framsticks.util.dispatching.Dispatcher;
 import com.framsticks.util.dispatching.Dispatching;
 import com.framsticks.util.dispatching.Future;
-import com.framsticks.util.lang.Casting;
-import com.framsticks.util.lang.Strings;
+import com.framsticks.util.dispatching.FutureHandler;
+import com.framsticks.util.dispatching.Joinable;
+import com.framsticks.util.dispatching.JoinableParent;
+import com.framsticks.util.dispatching.JoinableState;
 
 import static com.framsticks.structure.TreeOperations.*;
 
 @FramsClassAnnotation
-public class SimulatorConnector implements AutoAttacher {
+public class SimulatorConnector extends SingleSimulatorProvider implements JoinableParent {
 	private static final Logger log = LogManager.getLogger(SimulatorConnector.class);
 
+	protected Experiment experiment;
+	protected RemoteTree remoteTree;
+	protected Simulator simulator;
+	protected Address address;
+	protected boolean provided = false;
 
-	protected Experiment experiment;
-	protected Address address;
-	protected RemoteTree remoteTree;
+	public boolean hasProvided() {
+		return provided;
+	}
+
+	public void setAddress(Address address) {
+		this.address = address;
+	}
+
+	public Address getAddress() {
+		return address;
+	}
+
+
+	@Override
+	public String getName() {
+		return "simulator connector";
+	}
+
+	@Override
+	protected void joinableStart() {
+
+	}
+
+	@Override
+	protected void joinableInterrupt() {
+		Dispatching.drop(remoteTree, this);
+		finishJoinable();
+	}
+
+	@Override
+	protected void joinableFinish() {
+
+	}
+
+	@Override
+	protected void joinableJoin() throws InterruptedException {
+		Dispatching.join(remoteTree);
+	}
 
 	@SuppressWarnings({ "rawtypes", "unchecked" })
 	@Override
-	public void attachTo(Object parent) {
-		experiment = Casting.throwCast(Experiment.class, parent);
+	public void provideSimulator(final SimulatorSpecification specification, final FutureHandler<Simulator> future) {
+		if (hasProvided()) {
+			future.pass(null);
+			return;
+		}
+		provided = true;
+		experiment = specification.getExperiment();
 
 		Misc.throwIfNull(address);
@@ -41,6 +86,6 @@
 		remoteTree.setDispatcher((Dispatcher) experiment.getDispatcher());
 
-
 		experiment.getSimulatorCandidates().add(remoteTree);
+		Dispatching.use(remoteTree, this);
 
 		Dispatching.dispatchLog(remoteTree, log, Level.DEBUG, "first task in remote tree");
@@ -51,27 +96,16 @@
 			protected void result(Path result) {
 				log.debug("resolved simulator path: {}", result);
-				Misc.checkEquals(experiment.getExpdef(), bindAccess(result).get("expdef", String.class), "expdef mismatch in connected simulator", this);
+				Misc.checkEquals(specification.getDefinition(), bindAccess(result).get("expdef", String.class), "expdef mismatch in connected simulator", SimulatorConnector.this);
 
-				Simulator simulator = new Simulator(experiment, remoteTree, result);
-				experiment.addSimulator(simulator);
-				experiment.getSimulatorCandidates().remove(remoteTree);
+				simulator = experiment.createSimulator(remoteTree, result);
+
+				future.pass(simulator);
 			}
 		});
 	}
 
-	@ParamAnnotation
-	public void setAddress(String address) {
-		this.address = new Address(address);
+	@Override
+	public void childChangedState(Joinable joinable, JoinableState state) {
+		log.debug("child {} changed state to {}", joinable, state);
 	}
-
-	@ParamAnnotation
-	public String getAddress() {
-		return Strings.toStringNullProof(address, "");
-	}
-
-	@Override
-	public String toString() {
-		return "simulator connector to: " + Strings.toStringNullProof(address, "<null>");
-	}
-
 }
Index: /java/main/src/main/java/com/framsticks/experiment/SimulatorGroup.java
===================================================================
--- /java/main/src/main/java/com/framsticks/experiment/SimulatorGroup.java	(revision 107)
+++ /java/main/src/main/java/com/framsticks/experiment/SimulatorGroup.java	(revision 107)
@@ -0,0 +1,42 @@
+package com.framsticks.experiment;
+
+import java.util.Iterator;
+
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.util.dispatching.Future;
+import com.framsticks.util.dispatching.FutureHandler;
+import com.framsticks.util.dispatching.JoinableCollection;
+
+@FramsClassAnnotation
+public class SimulatorGroup extends JoinableCollection<SimulatorProvider> implements SimulatorProvider {
+
+	@Override
+	public String getName() {
+		return "simulator group";
+	}
+
+
+	@Override
+	public void provideSimulator(final SimulatorSpecification specification, final FutureHandler<Simulator> future) {
+		final Iterator<SimulatorProvider> iterator = joinables.iterator();
+
+		new Future<Simulator>(future) {
+
+			@Override
+			protected void result(Simulator result) {
+				if (result != null) {
+					future.pass(result);
+					return;
+				}
+				if (!iterator.hasNext()) {
+					future.pass(null);
+					return;
+				}
+				iterator.next().provideSimulator(specification, this);
+
+			}
+		}.pass(null);
+
+	}
+
+}
Index: /java/main/src/main/java/com/framsticks/experiment/SimulatorProvider.java
===================================================================
--- /java/main/src/main/java/com/framsticks/experiment/SimulatorProvider.java	(revision 107)
+++ /java/main/src/main/java/com/framsticks/experiment/SimulatorProvider.java	(revision 107)
@@ -0,0 +1,11 @@
+package com.framsticks.experiment;
+
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.util.dispatching.FutureHandler;
+import com.framsticks.util.dispatching.Joinable;
+
+@FramsClassAnnotation
+public interface SimulatorProvider extends Joinable {
+
+	public void provideSimulator(SimulatorSpecification specification, FutureHandler<Simulator> future);
+}
Index: /java/main/src/main/java/com/framsticks/experiment/SimulatorRange.java
===================================================================
--- /java/main/src/main/java/com/framsticks/experiment/SimulatorRange.java	(revision 107)
+++ /java/main/src/main/java/com/framsticks/experiment/SimulatorRange.java	(revision 107)
@@ -0,0 +1,105 @@
+package com.framsticks.experiment;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
+
+import com.framsticks.communication.Address;
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.params.annotations.ParamAnnotation;
+import com.framsticks.params.types.UniversalParam;
+import com.framsticks.util.dispatching.FutureHandler;
+import com.framsticks.util.dispatching.JoinableCollection;
+
+@FramsClassAnnotation
+public class SimulatorRange extends JoinableCollection<SimulatorProvider> implements SimulatorProvider {
+	private static final Logger log = LogManager.getLogger(Experiment.class);
+
+
+	protected List<String> hosts = new ArrayList<>();
+	protected List<Integer> ports = new ArrayList<>();
+
+	protected Iterator<Address> addresses;
+	protected boolean run = true;
+
+	@Override
+	public String getName() {
+		return "simulator range";
+	}
+
+	@Override
+	public void provideSimulator(final SimulatorSpecification specification, final FutureHandler<Simulator> future) {
+		if (addresses == null) {
+			log.info("providing simulators from set: {} X {}", hosts, ports);
+
+			List<Address> list = new ArrayList<Address>();
+			for (String host : hosts) {
+				for (Integer port : ports) {
+					list.add(new Address(host, port));
+				}
+			}
+			addresses = list.iterator();
+		}
+
+		if (!addresses.hasNext()) {
+			future.pass(null);
+			return;
+		}
+		Address address = addresses.next();
+		SingleSimulatorProvider provider = (run ? new SimulatorRunner() : new SimulatorConnector());
+		provider.setAddress(address);
+		add(provider);
+		provider.provideSimulator(specification, future);
+	}
+
+	/**
+	 * @return the hosts
+	 */
+	@ParamAnnotation(paramType = UniversalParam.class)
+	public List<String> getHosts() {
+		return hosts;
+	}
+
+	/**
+	 * @param hosts the hosts to set
+	 */
+	@ParamAnnotation
+	public void setHosts(List<String> hosts) {
+		this.hosts = hosts;
+	}
+
+	/**
+	 * @return the ports
+	 */
+	@ParamAnnotation(paramType = UniversalParam.class)
+	public List<Integer> getPorts() {
+		return ports;
+	}
+
+	/**
+	 * @param ports the ports to set
+	 */
+	@ParamAnnotation
+	public void setPorts(List<Integer> ports) {
+		this.ports = ports;
+	}
+
+	/**
+	 * @return the run
+	 */
+	@ParamAnnotation
+	public boolean getRun() {
+		return run;
+	}
+
+	/**
+	 * @param run the run to set
+	 */
+	@ParamAnnotation
+	public void setRun(boolean run) {
+		this.run = run;
+	}
+}
Index: /java/main/src/main/java/com/framsticks/experiment/SimulatorRunner.java
===================================================================
--- /java/main/src/main/java/com/framsticks/experiment/SimulatorRunner.java	(revision 107)
+++ /java/main/src/main/java/com/framsticks/experiment/SimulatorRunner.java	(revision 107)
@@ -0,0 +1,92 @@
+package com.framsticks.experiment;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
+
+import com.framsticks.communication.Address;
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.running.FramsServer;
+import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.FutureHandler;
+import com.framsticks.util.dispatching.Joinable;
+import com.framsticks.util.dispatching.JoinableParent;
+import com.framsticks.util.dispatching.JoinableState;
+
+@FramsClassAnnotation
+public class SimulatorRunner extends SingleSimulatorProvider implements JoinableParent {
+
+	private static final Logger log = LogManager.getLogger(SimulatorRunner.class);
+
+	protected final SimulatorConnector connector;
+	protected final FramsServer server;
+
+	/**
+	 *
+	 */
+	public SimulatorRunner() {
+		connector = new SimulatorConnector();
+		server = new FramsServer();
+	}
+
+	@Override
+	public String getName() {
+		return "simulator runner";
+	}
+
+	@Override
+	public void provideSimulator(SimulatorSpecification specification, FutureHandler<Simulator> future) {
+		if (connector.hasProvided()) {
+			future.pass(null);
+			return;
+		}
+		log.debug("running simulator at {}", getAddress());
+
+		if (!getAddress().getHostName().equals("localhost")) {
+			server.setHost(getAddress().getHostName());
+		}
+
+		server.setPort(getAddress().getPort());
+		server.setExpdef(specification.getDefinition());
+
+		Dispatching.use(server, this);
+
+		Dispatching.use(connector, this);
+		connector.provideSimulator(specification, future);
+	}
+
+	@Override
+	public void childChangedState(Joinable joinable, JoinableState state) {
+		proceedToState(state);
+	}
+
+	@Override
+	protected void joinableStart() {
+	}
+
+	@Override
+	protected void joinableInterrupt() {
+		finishJoinable();
+	}
+
+	@Override
+	protected void joinableFinish() {
+		Dispatching.drop(connector, this);
+		Dispatching.drop(server, this);
+	}
+
+	@Override
+	protected void joinableJoin() throws InterruptedException {
+		Dispatching.join(connector);
+		Dispatching.join(server);
+	}
+
+	@Override
+	public Address getAddress() {
+		return connector.getAddress();
+	}
+
+	@Override
+	public void setAddress(Address address) {
+		connector.setAddress(address);
+	}
+}
Index: /java/main/src/main/java/com/framsticks/experiment/SimulatorSpecification.java
===================================================================
--- /java/main/src/main/java/com/framsticks/experiment/SimulatorSpecification.java	(revision 107)
+++ /java/main/src/main/java/com/framsticks/experiment/SimulatorSpecification.java	(revision 107)
@@ -0,0 +1,31 @@
+package com.framsticks.experiment;
+
+public class SimulatorSpecification {
+
+	protected final Experiment experiment;
+	protected final String definition;
+
+	/**
+	 * @param experiment
+	 * @param definition
+	 */
+	public SimulatorSpecification(Experiment experiment, String definition) {
+		this.experiment = experiment;
+		this.definition = definition;
+	}
+
+	/**
+	 * @return the experiment
+	 */
+	public Experiment getExperiment() {
+		return experiment;
+	}
+
+	/**
+	 * @return the definition
+	 */
+	public String getDefinition() {
+		return definition;
+	}
+
+}
Index: /java/main/src/main/java/com/framsticks/experiment/SingleSimulatorProvider.java
===================================================================
--- /java/main/src/main/java/com/framsticks/experiment/SingleSimulatorProvider.java	(revision 107)
+++ /java/main/src/main/java/com/framsticks/experiment/SingleSimulatorProvider.java	(revision 107)
@@ -0,0 +1,30 @@
+package com.framsticks.experiment;
+
+import com.framsticks.communication.Address;
+import com.framsticks.params.annotations.ParamAnnotation;
+import com.framsticks.util.dispatching.AbstractJoinable;
+import com.framsticks.util.lang.Strings;
+
+public abstract class SingleSimulatorProvider extends AbstractJoinable implements SimulatorProvider {
+
+
+	@ParamAnnotation(id = "address")
+	public void setAddressString(String address) {
+		setAddress(new Address(address));
+	}
+
+	@ParamAnnotation(id = "address")
+	public String getAddressString() {
+		return Strings.toStringNullProof(getAddress(), "");
+	}
+
+	public abstract void setAddress(Address address);
+
+	public abstract Address getAddress();
+
+	@Override
+	public String toString() {
+		return "simulator connector to: " + Strings.toStringNullProof(getAddress(), "<null>");
+	}
+
+}
Index: /java/main/src/main/java/com/framsticks/experiment/WorkPackageLogic.java
===================================================================
--- /java/main/src/main/java/com/framsticks/experiment/WorkPackageLogic.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/experiment/WorkPackageLogic.java	(revision 107)
@@ -76,5 +76,5 @@
 				assert experiment.isActive();
 
-				log.debug("received package from {}: {}", simulator, netResult);
+				log.info("received package from {}: {}", simulator, netResult);
 				WorkPackageLogic.this.messages.info("netsave", netResult.toString());
 
Index: /java/main/src/main/java/com/framsticks/gui/controls/SliderControl.java
===================================================================
--- /java/main/src/main/java/com/framsticks/gui/controls/SliderControl.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/gui/controls/SliderControl.java	(revision 107)
@@ -196,4 +196,5 @@
 	}
 
+
 	@Override
 	public Number pullValueFromUserInterface() {
Index: /java/main/src/main/java/com/framsticks/gui/controls/TextAreaControl.java
===================================================================
--- /java/main/src/main/java/com/framsticks/gui/controls/TextAreaControl.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/gui/controls/TextAreaControl.java	(revision 107)
@@ -5,8 +5,10 @@
 
 import javax.swing.*;
+import javax.swing.text.JTextComponent;
+
 import java.awt.*;
 
 @SuppressWarnings("serial")
-public class TextAreaControl extends TextControl {
+public class TextAreaControl extends TextOnlyControl {
 
 	protected final JTextArea textArea;
@@ -39,12 +41,13 @@
 
 	@Override
-	public void pushValueToUserInterfaceImpl(Object value) {
-		textArea.setText((String) value);
-		this.revalidate();
+	protected JTextComponent getTextComponent() {
+		return textArea;
 	}
 
 	@Override
-	public Object pullValueFromUserInterface() {
-		return textArea.getText();
+	public void pushValueToUserInterfaceImpl(Object value) {
+		// getTextComponent().setText(getParam().serialize(value));
+		super.pushValueToUserInterfaceImpl(value);
+		this.revalidate();
 	}
 
Index: /java/main/src/main/java/com/framsticks/gui/controls/TextControl.java
===================================================================
--- /java/main/src/main/java/com/framsticks/gui/controls/TextControl.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/gui/controls/TextControl.java	(revision 107)
@@ -41,3 +41,6 @@
 		};
 	}
+
+
+
 }
Index: /java/main/src/main/java/com/framsticks/gui/controls/TextFieldControl.java
===================================================================
--- /java/main/src/main/java/com/framsticks/gui/controls/TextFieldControl.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/gui/controls/TextFieldControl.java	(revision 107)
@@ -3,22 +3,23 @@
 import com.framsticks.gui.Gui;
 import com.framsticks.params.PrimitiveParam;
-import com.framsticks.util.lang.Strings;
 
 import javax.swing.*;
+import javax.swing.text.JTextComponent;
+
 import java.awt.*;
 
 @SuppressWarnings("serial")
-public class TextFieldControl extends TextControl {
+public class TextFieldControl extends TextOnlyControl {
 
 
-	private static final Color CORRECT_COLOR = new Color(180, 255, 215);
 	private static final Color WRONG_COLOR = new Color(255, 180, 215);
 
 	protected final JTextField textField;
+	private final Color correctColor;
 
 	@Override
 	protected boolean notifyOfChange() {
 		boolean result = super.notifyOfChange();
-		textField.setBackground(result ? CORRECT_COLOR : WRONG_COLOR);
+		textField.setBackground(result ? correctColor : WRONG_COLOR);
 		return result;
 	}
@@ -28,4 +29,5 @@
 		textField = new JTextField();
 		textField.setName("value");
+		correctColor = textField.getBackground();
 
 		textField.setMinimumSize(new Dimension(0, Control.LINE_HEIGHT));
@@ -37,12 +39,8 @@
 	}
 
-	@Override
-	public void pushValueToUserInterfaceImpl(Object text) {
-		textField.setText(Strings.toStringNullProof(text));
-	}
 
 	@Override
-	public Object pullValueFromUserInterface() {
-		return textField.getText();
+	protected JTextComponent getTextComponent() {
+		return textField;
 	}
 
Index: /java/main/src/main/java/com/framsticks/gui/controls/TextOnlyControl.java
===================================================================
--- /java/main/src/main/java/com/framsticks/gui/controls/TextOnlyControl.java	(revision 107)
+++ /java/main/src/main/java/com/framsticks/gui/controls/TextOnlyControl.java	(revision 107)
@@ -0,0 +1,25 @@
+package com.framsticks.gui.controls;
+
+import javax.swing.text.JTextComponent;
+
+import com.framsticks.params.PrimitiveParam;
+
+@SuppressWarnings("serial")
+public abstract class TextOnlyControl extends TextControl {
+
+	public TextOnlyControl(PrimitiveParam<?> valueParam) {
+		super(valueParam);
+	}
+
+	protected abstract JTextComponent getTextComponent();
+
+	@Override
+	public void pushValueToUserInterfaceImpl(Object text) {
+		getTextComponent().setText(getParam().serialize(text));
+	}
+
+	@Override
+	public Object pullValueFromUserInterface() {
+		return getTextComponent().getText();
+	}
+}
Index: /java/main/src/main/java/com/framsticks/model/Genotype.java
===================================================================
--- /java/main/src/main/java/com/framsticks/model/Genotype.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/model/Genotype.java	(revision 107)
@@ -112,4 +112,8 @@
 	public void setPopsiz(int popsiz) { this.instances = popsiz; }
 
+	@Override
+	public String toString() {
+		return name;
+	}
 
 }
Index: /java/main/src/main/java/com/framsticks/params/AccessOperations.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/AccessOperations.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/params/AccessOperations.java	(revision 107)
@@ -99,4 +99,5 @@
 	public static Access loadAll(@Nullable final Access rootAccess, Source source, final Registry registry) {
 		final MultiParamLoader loader = new MultiParamLoader();
+		log.trace("loading all from {} into {}", source, rootAccess);
 		loader.setNewSource(source);
 		final LinkedList<Access> accessesStack = new LinkedList<>();
@@ -146,6 +147,11 @@
 
 							if (p instanceof ListParam) {
-								ListAccess listAccess = Casting.assertCast(ListAccess.class, registry.prepareAccess(p));
-								listAccess.select(a.get(p, Object.class));
+								ListAccess listAccess = Casting.assertCast(ListAccess.class, registry.prepareAccess(p, true));
+								Object list = a.get(p, Object.class);
+								if (list == null) {
+									list = listAccess.createAccessee();
+									a.set(p, list);
+								}
+								listAccess.select(list);
 								parent.set(new Pair<Access, CompositeParam>(listAccess, listAccess.prepareParamFor(Integer.toString(listAccess.getParamCount()))));
 
@@ -157,4 +163,5 @@
 
 					if (parent.get() == null) {
+						log.trace("{} cannot be placed in {}", name, a);
 						accessIterator.remove();
 					}
@@ -162,8 +169,8 @@
 
 				if (parent.get() == null) {
-					throw new FramsticksException().msg("failed to find place for loaded object").arg("name", name);
-				}
-
-				currentAccess.set(registry.prepareAccess(parent.get().second));
+					throw new FramsticksException().msg("failed to find place for loaded object").arg("name", name); //.arg("in", accessesStack);
+				}
+
+				currentAccess.set(registry.prepareAccess(parent.get().second, true));
 				Object object = parent.get().first.get(parent.get().second, Object.class);
 				if (object != null) {
@@ -200,5 +207,5 @@
 	}
 
-	public static void saveAll(Access access, Sink sink, Registry registry) {
+	public static <S extends Sink> S saveAll(Access access, S sink, Registry registry) {
 		if (access instanceof ObjectAccess) {
 			savePrimitives(access, sink);
@@ -209,6 +216,7 @@
 				continue;
 			}
-			saveAll(registry.prepareAccess(p).select(child), sink, registry);
-		}
+			saveAll(registry.prepareAccess(p, true).select(child), sink, registry);
+		}
+		return sink;
 	}
 
@@ -219,5 +227,5 @@
 				continue;
 			}
-			savePrimitives(registry.prepareAccess(p).select(child), sink);
+			savePrimitives(registry.prepareAccess(p, true).select(child), sink);
 		}
 	}
@@ -297,5 +305,5 @@
 					}
 
-					return registry.prepareAccess(result).select(objectAccess.get(result, Object.class));
+					return registry.prepareAccess(result, true).select(objectAccess.get(result, Object.class));
 				}
 			});
@@ -323,5 +331,7 @@
 			}
 			if ((param.getFlags() & ParamFlags.DONTLOAD) == 0) {
-				int retFlags = access.set((ValueParam) param, entry.value);
+				ValueParam valueParam = (ValueParam) param;
+				// Object object = valueParam.deserialize(entry.value, null,  Object.class);
+				int retFlags = access.set(valueParam, entry.value);
 				if ((retFlags & (PSET_HITMIN | PSET_HITMAX)) != 0) {
 					String which = ((retFlags & PSET_HITMIN) != 0) ? "small" : "big";
@@ -440,4 +450,5 @@
 	 */
 	public static <T, F> T convert(Class<T> toJavaClass, F from, Registry registry) {
+		log.trace("converting from {} to {}", from, toJavaClass);
 		if (toJavaClass.equals(from.getClass())) {
 			return toJavaClass.cast(from);
@@ -478,5 +489,5 @@
 
 				if (avp instanceof CompositeParam) {
-					assureEquality(registry.prepareAccess((CompositeParam) avp).select(oa), registry.prepareAccess((CompositeParam) bvp).select(ob), registry);
+					assureEquality(registry.prepareAccess((CompositeParam) avp, false).select(oa), registry.prepareAccess((CompositeParam) bvp, false).select(ob), registry);
 					continue;
 				}
Index: /java/main/src/main/java/com/framsticks/params/ArrayListAccess.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/ArrayListAccess.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/params/ArrayListAccess.java	(revision 107)
@@ -137,5 +137,5 @@
 				return new Iterator<Param>() {
 
-					protected ListIterator<Object> internal = list.listIterator();
+					protected final ListIterator<Object> internal = list.listIterator();
 
 					@Override
Index: /java/main/src/main/java/com/framsticks/params/FramsClassBuilder.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/FramsClassBuilder.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/params/FramsClassBuilder.java	(revision 107)
@@ -42,5 +42,9 @@
 
 	public static FramsClass readFromStream(InputStream stream) {
-		return Loaders.loadFramsClass(new FileSource(stream));
+		return readFromSource(new FileSource(stream));
+	}
+
+	public static FramsClass readFromSource(Source source) {
+		return Loaders.loadFramsClass(source);
 	}
 
Index: /java/main/src/main/java/com/framsticks/params/FreeAccess.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/FreeAccess.java	(revision 107)
+++ /java/main/src/main/java/com/framsticks/params/FreeAccess.java	(revision 107)
@@ -0,0 +1,181 @@
+package com.framsticks.params;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import com.framsticks.params.types.EventParam;
+import com.framsticks.params.types.ObjectParam;
+import com.framsticks.params.types.ProcedureParam;
+import com.framsticks.params.types.UniversalParam;
+import com.framsticks.util.UnimplementedException;
+
+public class FreeAccess implements ObjectAccess {
+
+	protected FreeObject object;
+
+	protected final String typeName;
+
+	/**
+	 * @param typeName
+	 */
+	public FreeAccess(String typeName) {
+		this.typeName = typeName;
+	}
+
+	@Override
+	public Param getParam(int i) {
+		throw new InvalidOperationException();
+	}
+
+	@Override
+	public Param getParam(String id) {
+		return Param.build().type(UniversalParam.class).idAndName(id).finish();
+	}
+
+	@Override
+	public int getParamCount() {
+		return object.size();
+	}
+
+	@Override
+	public Iterable<Param> getParams() {
+		return new Iterable<Param>() {
+
+			@Override
+			public Iterator<Param> iterator() {
+				return new Iterator<Param>() {
+
+					protected final Iterator<Map.Entry<String, Object>> internal = object.iterator();
+
+					@Override
+					public boolean hasNext() {
+						return internal.hasNext();
+					}
+
+					@Override
+					public Param next() {
+						return Param.build().idAndName(internal.next().getKey()).type(UniversalParam.class).finish(Param.class);
+					}
+
+					@Override
+					public void remove() {
+						throw new UnimplementedException().msg("remove element from FreeAccess").arg("access", FreeAccess.this);
+					}
+				};
+			}
+		};
+	}
+
+	@Override
+	public String getTypeId() {
+		return typeName;
+	}
+
+	@Override
+	public Object call(String id, Object... arguments) {
+		throw new InvalidOperationException().msg("properties access does not support calling methods").arg("id", id);
+	}
+
+	@Override
+	public Object call(ProcedureParam param, Object... arguments) {
+		throw new InvalidOperationException().msg("properties access does not support calling methods").arg("param", param);
+	}
+
+	@Override
+	public <T> T get(int i, Class<T> type) {
+		throw new InvalidOperationException();
+	}
+
+	@Override
+	public <T> T get(String id, Class<T> type) {
+		return object.get(id, type);
+	}
+
+	@Override
+	public <T> T get(ValueParam param, Class<T> type) {
+		return get(param.getId(), type);
+	}
+
+	@Override
+	public <T> int set(int i, T value) {
+		throw new InvalidOperationException();
+	}
+
+	@Override
+	public <T> int set(String id, T value) {
+		object.set(id, (value instanceof String) ? ParamsUtil.deserialize((String) value) : value);
+		return 0;
+	}
+
+	@Override
+	public <T> int set(ValueParam param, T value) {
+		return set(param.getId(), value);
+	}
+
+	@Override
+	public void reg(EventParam param, EventListener<?> listener) {
+		throw new InvalidOperationException().msg("properties access does not support registering events").arg("param", param).arg("access", this);
+	}
+
+	@Override
+	public void regRemove(EventParam param, EventListener<?> listener) {
+		throw new InvalidOperationException().msg("properties access does not support registering events").arg("param", param).arg("access", this);
+	}
+
+	@Override
+	public void clearValues() {
+		object.clear();
+	}
+
+	@Override
+	public Access select(Object object) {
+		this.object = ParamsUtil.selectObjectForAccess(this, object, FreeObject.class);
+		return this;
+	}
+
+	@Override
+	public Object getSelected() {
+		return object;
+	}
+
+	@Override
+	public Access cloneAccess() {
+		return new FreeAccess(typeName);
+	}
+
+	@Override
+	public Object createAccessee() {
+		return new FreeObject(typeName);
+	}
+
+	@Override
+	public FramsClass getFramsClass() {
+		throw new InvalidOperationException();
+	}
+
+	@Override
+	public void tryAutoAppend(Object object) {
+		throw new InvalidOperationException();
+	}
+
+	@Override
+	public int getCompositeParamCount() {
+		return 0;
+	}
+
+	@Override
+	public CompositeParam getCompositeParam(int number) {
+		throw new InvalidOperationException();
+	}
+
+	@Override
+	public ParamBuilder buildParam(ParamBuilder builder) {
+		return builder.name(typeName).type(ObjectParam.class).containedTypeName(typeName);
+	}
+
+	@Override
+	public String toString() {
+		return "FreeAccess[" + typeName + "]";
+	}
+
+}
Index: /java/main/src/main/java/com/framsticks/params/FreeObject.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/FreeObject.java	(revision 107)
+++ /java/main/src/main/java/com/framsticks/params/FreeObject.java	(revision 107)
@@ -0,0 +1,12 @@
+package com.framsticks.params;
+
+public class FreeObject extends MapBasedObject {
+
+	/**
+	 *
+	 */
+	public FreeObject(String framsTypeName) {
+		super(framsTypeName);
+	}
+
+}
Index: /java/main/src/main/java/com/framsticks/params/MapBasedObject.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/MapBasedObject.java	(revision 107)
+++ /java/main/src/main/java/com/framsticks/params/MapBasedObject.java	(revision 107)
@@ -0,0 +1,55 @@
+package com.framsticks.params;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+
+import com.framsticks.util.lang.Casting;
+
+public class MapBasedObject implements Iterable<Map.Entry<String, Object>> {
+
+	protected final String framsTypeName;
+	protected final Map<String, Object> values = new TreeMap<>();
+
+	/**
+	 * @param framsTypeName
+	 */
+	public MapBasedObject(String framsTypeName) {
+		this.framsTypeName = framsTypeName;
+	}
+
+	public <T> void set(String id, T value) {
+		values.put(id, value);
+	}
+
+	public <T> T get(String id, Class<T> type) {
+		return Casting.nullOrThrowCast(type, values.get(id));
+	}
+
+	public void clear() {
+		values.clear();
+	}
+
+	public int size() {
+		return values.size();
+	}
+
+	@Override
+	public String toString() {
+		return values.toString();
+	}
+
+	/**
+	 * @return the framsTypeName
+	 */
+	public String getFramsTypeName() {
+		return framsTypeName;
+	}
+
+	@Override
+	public Iterator<Entry<String, Object>> iterator() {
+		return values.entrySet().iterator();
+	}
+
+}
Index: /java/main/src/main/java/com/framsticks/params/OpaqueObject.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/OpaqueObject.java	(revision 107)
+++ /java/main/src/main/java/com/framsticks/params/OpaqueObject.java	(revision 107)
@@ -0,0 +1,49 @@
+package com.framsticks.params;
+
+public class OpaqueObject {
+
+	protected final String typeName;
+	protected final long address;
+
+	/**
+	 * @param typeName
+	 * @param address
+	 */
+	public OpaqueObject(String typeName, long address) {
+		this.typeName = typeName;
+		this.address = address;
+	}
+
+	@Override
+	public String toString() {
+		return typeName + "<0x" + Long.toHexString(address) + ">";
+	}
+
+	/**
+	 * @return the typeName
+	 */
+	public String getTypeName() {
+		return typeName;
+	}
+
+	/**
+	 * @return the address
+	 */
+	public long getAddress() {
+		return address;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (!(obj instanceof OpaqueObject)) {
+			return false;
+		}
+		OpaqueObject opaque = (OpaqueObject) obj;
+		return typeName.equals(opaque.getTypeName()) && address == opaque.getAddress();
+	}
+
+	@Override
+	public int hashCode() {
+		return typeName.hashCode() ^ new Long(address).hashCode();
+	}
+}
Index: /java/main/src/main/java/com/framsticks/params/ParamCandidate.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/ParamCandidate.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/params/ParamCandidate.java	(revision 107)
@@ -80,4 +80,5 @@
 	protected final OneTime<Method> remover = new OneTime<>("remover");
 	protected final OneTime<Class<? extends Param>> paramType = new OneTime<>("paramType");
+	protected final OneTime<String> stringType = new OneTime<>("stringType");
 
 	protected int flags = 0;
@@ -278,4 +279,7 @@
 		if (!paramAnnotation.paramType().equals(Param.class)) {
 			paramType.set(paramAnnotation.paramType());
+		}
+		if (!"".equals(paramAnnotation.stringType())) {
+			stringType.set(paramAnnotation.stringType());
 		}
 		if (member instanceof Field) {
@@ -371,4 +375,5 @@
 		protected final List<ParamCandidate> order;
 		protected final java.util.Set<Class<?>> dependantClasses = new HashSet<>();
+		protected final java.util.Set<String> dependantClassesFromInfo = new HashSet<>();
 
 		/**
@@ -398,4 +403,8 @@
 			return dependantClasses;
 		}
+
+		public java.util.Set<String> getDependentClassesFromInfo() {
+			return dependantClassesFromInfo;
+		}
 	}
 
@@ -432,5 +441,7 @@
 					result.dependantClasses.add(r);
 				}
-
+				for (String i : fa.registerFromInfo()) {
+					result.dependantClassesFromInfo.add(i);
+				}
 
 				final List<String> order = Arrays.asList(fa.order());
@@ -575,4 +586,9 @@
 
 	public ParamBuilder induceParamType(ParamBuilder builder) {
+
+		if (stringType.has()) {
+			return builder.type(stringType.get());
+		}
+
 		Method method = getCaller();
 		if (method == null) {
Index: /java/main/src/main/java/com/framsticks/params/ParamsUtil.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/ParamsUtil.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/params/ParamsUtil.java	(revision 107)
@@ -2,10 +2,18 @@
 
 import java.util.ArrayList;
+// import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import javax.annotation.Nonnull;
 
+// import org.apache.logging.log4j.Logger;
+// import org.apache.logging.log4j.LogManager;
+
 import com.framsticks.util.FramsticksException;
+import com.framsticks.util.lang.Numbers;
 
 
@@ -16,4 +24,6 @@
  */
 public abstract class ParamsUtil {
+	// private final static Logger log = LogManager.getLogger(ParamsUtil.class.getName());
+
 
 	public static String readSourceToString(Source source) {
@@ -212,4 +222,8 @@
 				return true;
 			}
+			if (type.equals(OpaqueObject.class)) {
+				builder.append(value.toString());
+				return true;
+			}
 			throw new FramsticksException().msg("invalid type for serialization").arg("type", type);
 		}
@@ -233,6 +247,202 @@
 	}
 
+	public static class DeserializationContext {
+
+		public static final Pattern OPAQUE_OBJECT_PATTERN = Pattern.compile("^(\\w+)<0x([a-fA-F0-9]+)>$");
+
+		@SuppressWarnings("serial")
+		public static class Exception extends FramsticksException {
+		}
+
+		protected final ArrayList<Object> objects = new ArrayList<>();
+		protected int cursor = 0;
+		protected final String input;
+
+		/**
+		 * @param input
+		 */
+		public DeserializationContext(String input) {
+			this.input = input;
+			cursor = 0;
+		}
+
+		protected boolean isFinished() {
+			return cursor == input.length();
+		}
+
+		protected boolean is(char value) {
+			if (isFinished()) {
+				throw fail().msg("input ended");
+			}
+			return input.charAt(cursor) == value;
+		}
+
+		protected boolean isOneOf(String values) {
+			if (isFinished()) {
+				throw fail().msg("input ended");
+			}
+			return values.indexOf(input.charAt(cursor)) != -1;
+		}
+
+		protected char at() {
+			return input.charAt(cursor);
+		}
+
+		protected char at(int pos) {
+			return input.charAt(pos);
+		}
+
+		protected FramsticksException fail() {
+			return new Exception().arg("at", cursor).arg("input", input);
+		}
+
+		protected void force(char value) {
+			if (!is(value)) {
+				throw fail().msg("invalid character").arg("expected", value).arg("found", at());
+			}
+			next();
+		}
+
+		protected boolean isAndNext(char value) {
+			if (!is(value)) {
+				return false;
+			}
+			next();
+			return true;
+		}
+
+		protected void next() {
+			++cursor;
+			// log.info("at: {}|{}", input.substring(0, cursor), input.substring(cursor));
+		}
+
+		protected void goToNext(char value) {
+			while (cursor < input.length()) {
+				if (is(value)) {
+					return;
+				}
+				next();
+			}
+			throw fail().msg("passed end").arg("searching", value);
+		}
+
+
+		protected String forceStringRemaining() {
+			int start = cursor;
+			while (true) {
+				goToNext('"');
+				if (at(cursor - 1) != '\\') {
+					next();
+					return input.substring(start, cursor - 1);
+				}
+				next();
+				// it is finishing that loop, because of throwing in goToNext()
+			}
+			// throw fail();
+		}
+
+		public Object deserialize() {
+			if (isAndNext('[')) {
+				List<Object> list = new ArrayList<>();
+				objects.add(list);
+				while (!isAndNext(']')) {
+					if (!list.isEmpty()) {
+						force(',');
+					}
+					Object child = deserialize();
+					list.add(child);
+				}
+				return list;
+			}
+
+			if (isAndNext('{')) {
+				Map<String, Object> map = new TreeMap<>();
+				objects.add(map);
+				while (!isAndNext('}')) {
+					if (!map.isEmpty()) {
+						force(',');
+					}
+					force('"');
+					String key = forceStringRemaining();
+					force(':');
+					Object value = deserialize();
+					map.put(key, value);
+				}
+				return map;
+			}
+
+			if (isAndNext('"')) {
+				return forceStringRemaining();
+			}
+			int start = cursor;
+			while (!isFinished() && !isOneOf("]},")) {
+				next();
+			}
+			if (start == cursor) {
+				throw fail().msg("empty value");
+			}
+
+			String value = input.substring(start, cursor);
+			if (value.equals("null")) {
+				//TODO: add this to list?
+				return null;
+			}
+
+			Matcher matcher = OPAQUE_OBJECT_PATTERN.matcher(value);
+			if (matcher.matches()) {
+				return new OpaqueObject(matcher.group(1), Long.parseLong(matcher.group(2), 16));
+			}
+
+
+			Object number = DeserializationContext.tryParseNumber(value);
+			if (number != null) {
+				return number;
+			}
+
+			if (value.charAt(0) == '^') {
+				Integer reference = Numbers.parse(value.substring(1), Integer.class);
+				if (reference == null) {
+					throw fail().msg("invalid reference").arg("reference", reference);
+				}
+				return objects.get(reference);
+			}
+			//TODO: parse ^
+			//TODO: parse opaque object
+			throw fail().msg("unknown entity");
+
+		}
+
+		public static Object tryParseNumber(String value) {
+			Integer i = Numbers.parse(value, Integer.class);
+			if (i != null) {
+				return i;
+			}
+
+			Double d = Numbers.parse(value, Double.class);
+			if (d != null) {
+				return d;
+			}
+
+			return null;
+		}
+	}
+
+
+	public static Object deserialize(String value) {
+		Object number = DeserializationContext.tryParseNumber(value);
+		if (number != null) {
+			return number;
+		}
+
+		if (!value.startsWith(SERIALIZED)) {
+			return value;
+		}
+		return new DeserializationContext(value.substring(SERIALIZED.length())).deserialize();
+	}
+
 	public static <T> T deserialize(String value, Class<T> type) {
-		return null;
+		Object object = deserialize(value);
+
+		return type.cast(object);
 	}
 
Index: /java/main/src/main/java/com/framsticks/params/PrimitiveParam.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/PrimitiveParam.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/params/PrimitiveParam.java	(revision 107)
@@ -3,5 +3,4 @@
 import com.framsticks.util.FramsticksException;
 import com.framsticks.util.Misc;
-import com.framsticks.util.lang.Casting;
 import com.framsticks.util.lang.Numbers;
 import com.framsticks.util.lang.Strings;
@@ -51,13 +50,12 @@
 					return type.cast(value);
 				}
-				// if (Number.class.isAssignableFrom(type)) {
 				return Numbers.parse((String) value, type);
-				// }
-				// return null;
+			} if ((value instanceof Integer) && (type.equals(Double.class))) {
+				return type.cast(new Double((Integer) value));
 			} else {
 				return type.cast(value);
 			}
 		} catch (ClassCastException e) {
-			throw new FramsticksException().msg("failed to cast").cause(e).arg("param", this).arg("actual", value.getClass()).arg("requested", type);
+			throw new FramsticksException().msg("failed to cast").cause(e).arg("param", this).arg("actual", value.getClass()).arg("requested", type).arg("value", value);
 		}
 	}
@@ -99,16 +97,7 @@
 	}
 
-	@Override
 	public <T> String serialize(T value) {
 		return Strings.toStringNullProof(value);
 	}
 
-	@Override
-	public <T> T deserialize(String text, T currentValue, Class<T> type) {
-		try {
-			return Casting.nullOrThrowCast(type, reassign(text, currentValue).getValue());
-		} catch (CastFailure e) {
-			return null;
-		}
-	}
 }
Index: /java/main/src/main/java/com/framsticks/params/PropertiesAccess.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/PropertiesAccess.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/params/PropertiesAccess.java	(revision 107)
@@ -112,2 +112,3 @@
 	}
 }
+
Index: /java/main/src/main/java/com/framsticks/params/PropertiesObject.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/PropertiesObject.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/params/PropertiesObject.java	(revision 107)
@@ -1,47 +1,12 @@
 package com.framsticks.params;
 
-import java.util.Map;
-import java.util.TreeMap;
-
-import com.framsticks.util.lang.Casting;
-
-public class PropertiesObject {
-
-	protected final String framsTypeName;
-	protected final Map<String, Object> values = new TreeMap<>();
+public class PropertiesObject extends MapBasedObject {
 
 	/**
-	 * @param framsTypeName
+	 *
 	 */
 	public PropertiesObject(String framsTypeName) {
-		this.framsTypeName = framsTypeName;
+		super(framsTypeName);
 	}
 
-	public <T> void set(String id, T value) {
-		values.put(id, value);
-	}
-
-	public <T> T get(String id, Class<T> type) {
-		return Casting.nullOrThrowCast(type, values.get(id));
-	}
-
-	public void clear() {
-		values.clear();
-	}
-
-	public int size() {
-		return values.size();
-	}
-
-	@Override
-	public String toString() {
-		return values.toString();
-	}
-
-	/**
-	 * @return the framsTypeName
-	 */
-	public String getFramsTypeName() {
-		return framsTypeName;
-	}
 }
Index: /java/main/src/main/java/com/framsticks/params/ReflectionAccess.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/ReflectionAccess.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/params/ReflectionAccess.java	(revision 107)
@@ -11,4 +11,5 @@
 import com.framsticks.params.types.ProcedureParam;
 import com.framsticks.util.FramsticksException;
+import com.framsticks.util.Misc;
 
 import static com.framsticks.util.lang.Containers.*;
@@ -90,5 +91,5 @@
 			}
 		} catch (FramsticksException e) {
-			throw e.arg("param", param).arg("value", value).arg("access", this);
+			throw e.arg("param", param).arg("value", value).arg("value type", Misc.getClass(value)).arg("access", this);
 		}
 	}
Index: /java/main/src/main/java/com/framsticks/params/Registry.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/Registry.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/params/Registry.java	(revision 107)
@@ -8,4 +8,5 @@
 import com.framsticks.util.DoubleMap;
 import com.framsticks.util.FramsticksException;
+import com.framsticks.util.lang.Casting;
 import com.framsticks.util.lang.Strings;
 
@@ -53,4 +54,8 @@
 			registerAndBuild(r);
 		}
+
+		for (String i : ParamCandidate.getAllCandidates(javaClass).getDependentClassesFromInfo()) {
+			putFramsClass(FramsClassBuilder.readFromStream(getClass().getResourceAsStream("/info/" + i + ".info")));
+		}
 		return this;
 	}
@@ -76,4 +81,8 @@
 		try {
 			if (!javaClasses.containsValue(javaClass)) {
+				registerAndBuild(javaClass);
+			}
+
+			if (!javaClasses.containsValue(javaClass)) {
 				throw new FramsticksException().msg("java class is not registered");
 			}
@@ -114,14 +123,24 @@
 	}
 
-	public @Nonnull Access prepareAccess(CompositeParam param) throws ConstructionException {
-		return wrapAccessWithListIfNeeded(param, createAccess(param.getContainedTypeName()));
-	}
-
-	public @Nonnull Access createAccess(@Nonnull String name) throws ConstructionException {
+	public @Nonnull Access prepareAccess(CompositeParam param, boolean force) throws ConstructionException {
+		return wrapAccessWithListIfNeeded(param, createAccess(param.getContainedTypeName(), force));
+	}
+
+	public @Nonnull Access createAccess(@Nonnull Object object) throws ConstructionException {
+		if (object instanceof MapBasedObject) {
+			return createAccess(((MapBasedObject) object).getFramsTypeName());
+		}
+		return createAccess(object.getClass());
+	}
+
+	public @Nonnull Access createAccess(@Nonnull String name, boolean force) throws ConstructionException {
 		try {
 			Strings.assureNotEmpty(name);
 			FramsClass framsClass = getFramsClass(name);
 			if (framsClass == null) {
-				throw new ConstructionException().msg("framsclass is missing");
+				if (!force) {
+					throw new ConstructionException().msg("framsclass is missing");
+				}
+				return new FreeAccess(name);
 			}
 
@@ -131,4 +150,8 @@
 			throw new FramsticksException().msg("failed to create access for name").arg("name", name).cause(e);
 		}
+	}
+
+	public @Nonnull Access createAccess(@Nonnull String name) throws ConstructionException {
+		return createAccess(name, false);
 	}
 
@@ -166,5 +189,21 @@
 
 	public Access bindAccessFor(Object object) {
-		return createAccess(object.getClass()).select(object);
+		return createAccess(object).select(object);
+	}
+
+	public Registry register(ParamsPackage paramsPackage) {
+		paramsPackage.register(this);
+		return this;
+	}
+
+	public Registry registerAndBuild(ParamsPackage paramsPackage) {
+		paramsPackage.setBuild(true);
+		paramsPackage.register(this);
+		return this;
+	}
+
+	public Access bindAccessFor(Access parent, String paramName) {
+		CompositeParam childParam = Casting.throwCast(CompositeParam.class, parent.getParam(paramName));
+		return prepareAccess(childParam, true).select(parent.get(childParam, Object.class));
 	}
 
Index: /java/main/src/main/java/com/framsticks/params/UniqueListAccess.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/UniqueListAccess.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/params/UniqueListAccess.java	(revision 107)
@@ -187,10 +187,28 @@
 	}
 
+	public int setUidOf(Object value, String uid) {
+		return uidAccess.select(value).set(uidName, uid);
+	}
+
+	protected int uidCounter = 1;
+
+	public String generateNextUid() {
+		return containedTypeName.substring(0, 1).toUpperCase() + Integer.toString(uidCounter++);
+	}
+
+	public String findNextFreeUid() {
+		String uid;
+		do {
+			uid = generateNextUid();
+		} while (get(uid, Object.class) != null);
+		return uid;
+	}
+
 	protected int setByUid(Object object, String uid) {
 		if (uid == null) {
 			uid = getUidOf(object);
 			if (uid == null) {
-				log.error("failed to set - missing uid");
-				return 0;
+				uid = findNextFreeUid();
+				setUidOf(object, uid);
 			}
 		}
@@ -205,13 +223,23 @@
 	@Override
 	public <T> int set(int i, T value) {
-		if (i != map.size()) {
-			throw new FramsticksUnsupportedOperationException().msg("setting element in unique list through index is available only for addition");
-		}
-		set(getUidOf(value), value);
-		return 0;
+		if (value != null) {
+			if (i != map.size()) {
+				throw new FramsticksUnsupportedOperationException().msg("setting element in unique list through index is available only for addition");
+			}
+			set(getUidOf(value), value);
+			return 0;
+		}
+		if (i >= map.size()) {
+			throw new FramsticksUnsupportedOperationException().msg("invalid index for removal");
+		}
+		Object current = get(i, Object.class);
+		return setByUid(null, getUidOf(current));
 	}
 
 	@Override
 	public <T> int set(String id, T value) {
+		if (id == null) {
+			return setByUid(value, null);
+		}
 		Integer i = Numbers.parse(id, Integer.class);
 		if (i != null) {
Index: /java/main/src/main/java/com/framsticks/params/ValueParam.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/ValueParam.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/params/ValueParam.java	(revision 107)
@@ -28,7 +28,5 @@
 	}
 
-	public abstract <T> String serialize(T value);
-
-	public abstract <T> T deserialize(String text, T currentValue, Class<T> type);
+	// public abstract <T> String serialize(T value);
 
 }
Index: /java/main/src/main/java/com/framsticks/params/annotations/FramsClassAnnotation.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/annotations/FramsClassAnnotation.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/params/annotations/FramsClassAnnotation.java	(revision 107)
@@ -14,3 +14,4 @@
 	String[] order() default {};
 	Class<?>[] register() default {};
+	String[] registerFromInfo() default {};
 }
Index: /java/main/src/main/java/com/framsticks/params/types/ListParam.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/types/ListParam.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/params/types/ListParam.java	(revision 107)
@@ -16,12 +16,8 @@
 	}
 
-	@Override
-	public <T> String serialize(T value) {
-		return null;
-	}
+	// @Override
+	// public <T> String serialize(T value) {
+	// 	return null;
+	// }
 
-	@Override
-	public <T> T deserialize(String text, T currentValue, Class<T> type) {
-		return null;
-	}
 }
Index: /java/main/src/main/java/com/framsticks/params/types/ObjectParam.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/types/ObjectParam.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/params/types/ObjectParam.java	(revision 107)
@@ -5,5 +5,4 @@
 import com.framsticks.params.CompositeParam;
 import com.framsticks.params.ParamBuilder;
-import com.framsticks.params.ParamsUtil;
 import com.framsticks.params.ReassignResult;
 
@@ -51,13 +50,8 @@
 	}
 
-	@Override
-	public <T> String serialize(T value) {
-		return ParamsUtil.serialize(value);
-	}
-
-	@Override
-	public <T> T deserialize(String text, T currentValue, Class<T> type) {
-		return ParamsUtil.deserialize(text, type);
-	}
+	// @Override
+	// public <T> String serialize(T value) {
+	// 	return ParamsUtil.serialize(value);
+	// }
 
 }
Index: /java/main/src/main/java/com/framsticks/params/types/StringParam.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/types/StringParam.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/params/types/StringParam.java	(revision 107)
@@ -49,4 +49,7 @@
 	@Override
 	public String serialize(Object value) {
+		if (value == null) {
+			return "";
+		}
 		assert value instanceof String;
 		String s = (String) value;
Index: /java/main/src/main/java/com/framsticks/params/types/UniversalParam.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/types/UniversalParam.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/params/types/UniversalParam.java	(revision 107)
@@ -35,4 +35,7 @@
 	@Override
 	public ReassignResult<Object> reassign(Object newValue, Object oldValue) throws CastFailure {
+		if (newValue instanceof String) {
+			return ReassignResult.create(ParamsUtil.deserialize((String) newValue, Object.class));
+		}
 		return ReassignResult.create(newValue);
 	}
@@ -43,8 +46,4 @@
 	}
 
-	@Override
-	public <T> T deserialize(String text, T currentValue, Class<T> type) {
-		return ParamsUtil.deserialize(text, type);
-	}
 
 }
Index: /java/main/src/main/java/com/framsticks/parsers/F0Writer.java
===================================================================
--- /java/main/src/main/java/com/framsticks/parsers/F0Writer.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/parsers/F0Writer.java	(revision 107)
@@ -33,5 +33,5 @@
 		if (access instanceof ListAccess) {
 			for (ValueParam p : Containers.filterInstanceof(access.getParams(), ValueParam.class)) {
-				write(schema.getRegistry().prepareAccess((CompositeParam) p).select(access.get(p, Object.class)));
+				write(schema.getRegistry().prepareAccess((CompositeParam) p, false).select(access.get(p, Object.class)));
 			}
 			return;
@@ -44,5 +44,5 @@
 		for (ValueParam param : filterInstanceof(access.getParams(), ValueParam.class)) {
 			if (param instanceof CompositeParam) {
-				Access a = schema.getRegistry().prepareAccess((CompositeParam) param);
+				Access a = schema.getRegistry().prepareAccess((CompositeParam) param, false);
 				a.select(access.get((ValueParam) param, Object.class));
 				write(a);
Index: /java/main/src/main/java/com/framsticks/remote/RemoteTree.java
===================================================================
--- /java/main/src/main/java/com/framsticks/remote/RemoteTree.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/remote/RemoteTree.java	(revision 107)
@@ -192,5 +192,5 @@
 			protected void result(FramsClass result) {
 
-				final Access access = registry.prepareAccess(path.getTop().getParam());
+				final Access access = registry.prepareAccess(path.getTop().getParam(), false);
 				connection.send(new GetRequest().path(path.getTextual()), AtOnceDispatcher.getInstance(), new ClientSideResponseFuture(remover) {
 					@Override
Index: /java/main/src/main/java/com/framsticks/running/ExternalProcess.java
===================================================================
--- /java/main/src/main/java/com/framsticks/running/ExternalProcess.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/running/ExternalProcess.java	(revision 107)
@@ -8,4 +8,5 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
@@ -31,4 +32,5 @@
 import com.framsticks.util.dispatching.ThrowExceptionHandler;
 import com.framsticks.util.io.Encoding;
+import com.framsticks.util.lang.Strings;
 
 @FramsClassAnnotation
@@ -38,5 +40,4 @@
 	protected List<String> arguments = new ArrayList<>();
 	protected Process process;
-	protected final ProcessBuilder builder = new ProcessBuilder();
 	protected Thread<ExternalProcess> readerThread = new Thread<ExternalProcess>();
 
@@ -45,4 +46,6 @@
 	protected Integer exitCode;
 	protected String echoInput;
+	protected String directory;
+	protected String host;
 
 	protected final EventListeners<ValueChange> listeners = new EventListeners<>();
@@ -70,5 +73,4 @@
 		setName("process");
 		arguments.add(null);
-		builder.redirectErrorStream(true);
 	}
 
@@ -120,15 +122,46 @@
 	@ParamAnnotation(flags = ParamFlags.USERREADONLY)
 	public void setDirectory(String directory) {
-		builder.directory(new File(directory));
+		this.directory = directory;
+	}
+
+	/**
+	 * @return the host
+	 */
+	public String getHost() {
+		return host;
+	}
+
+	/**
+	 * @param host the host to set
+	 */
+	public void setHost(String host) {
+		this.host = host;
 	}
 
 	@ParamAnnotation
 	public String getDirectory() {
-		return builder.directory() != null ? builder.directory().getName() : ".";
+		return Strings.toStringNullProof(directory, ".");
 	}
 
 	@Override
 	protected void joinableStart() {
+
+		final ProcessBuilder builder = new ProcessBuilder();
+
+		builder.redirectErrorStream(true);
+		if (host == null) {
+			setDirectory(System.getProperties().get("user.home") + "/" + getDirectory());
+			setCommand(getDirectory() + "/" + getCommand());
+			builder.directory(new File(getDirectory()));
+		} else {
+			StringBuilder b = new StringBuilder();
+			setCommand("./" + getCommand());
+			for (String a : arguments) {
+				b.append(" '").append(a).append("'");
+			}
+			arguments = Arrays.asList("ssh", host, "-tt", ("cd " + getDirectory() + " &&" + b.toString()));
+		}
 		log.info("running process {}", this);
+
 		builder.command(arguments);
 		try {
Index: /java/main/src/main/java/com/framsticks/running/FramsServer.java
===================================================================
--- /java/main/src/main/java/com/framsticks/running/FramsServer.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/running/FramsServer.java	(revision 107)
@@ -20,5 +20,6 @@
 	public FramsServer() {
 		super();
-		setPath(System.getProperties().get("user.home") + "/opt/framsticks");
+		setCommand("frams.linux");
+		setPath("opt/framsticks");
 		setName("frams");
 	}
@@ -55,5 +56,4 @@
 	public void setPath(String path) {
 		this.path = path;
-		setCommand(path + "/frams.linux");
 		setDirectory(path);
 	}
Index: /java/main/src/main/java/com/framsticks/standard/StandardExperiment.java
===================================================================
--- /java/main/src/main/java/com/framsticks/standard/StandardExperiment.java	(revision 107)
+++ /java/main/src/main/java/com/framsticks/standard/StandardExperiment.java	(revision 107)
@@ -0,0 +1,145 @@
+package com.framsticks.standard;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
+import java.util.TimerTask;
+
+import com.framsticks.experiment.Experiment;
+import com.framsticks.experiment.Simulator;
+import com.framsticks.model.Genotype;
+import com.framsticks.params.Access;
+import com.framsticks.params.EventListener;
+import com.framsticks.params.Registry;
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.structure.messages.ListChange;
+import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.Future;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
+
+@FramsClassAnnotation
+public class StandardExperiment extends Experiment {
+
+	private static final Logger log = LogManager.getLogger(StandardExperiment.class);
+
+	protected final Registry registry = new Registry();
+
+	protected List<Genotype> genotypes = new LinkedList<>();
+	protected Random random = new Random();
+
+	// @ParamAnnotation
+	// protected final NetLoadSaveLogic<StandardState> netLoadSaveLogic;
+
+	/**
+	 *
+	 */
+	public StandardExperiment() {
+
+		setExpdef("standard");
+		registry.registerAndBuild(StandardState.class);
+
+		addSimulatorsListener(new EventListener<ListChange>() {
+			@Override
+			public void action(final ListChange change) {
+				assert isActive();
+				final Simulator simulator = getSimulators().get(change.getIdentifier());
+				if (change.getAction().equals(ListChange.Action.Add)) {
+					simulator.init();
+					return;
+				}
+				if (change.getAction().equals(ListChange.Action.Modify)) {
+					if (change.hasHint("ready")) {
+						log.debug("issuing netsave");
+
+						simulator.netsave(StandardState.class, new Future<StandardState>(StandardExperiment.this) {
+							@Override
+							protected void result(StandardState result) {
+								assert isActive();
+								assert result != null;
+								processState(simulator, result);
+
+								simulator.netload(result, new Future<Object>(StandardExperiment.this) {
+
+									@Override
+									protected void result(Object result) {
+										runSimulatorFor(simulator);
+									}
+								});
+							}
+						});
+					}
+
+					return;
+				}
+
+			}
+		});
+
+
+		// netLoadSaveLogic = new NetLoadSaveLogic<StandardState>(this, StandardState.class) {
+		//	@Override
+		//	public void netload(Simulator simulator, FutureHandler<StandardState> net) {
+		//		assert isActive();
+		//		// Dispatching.sleep(0.1);
+		//		net.pass(null);
+		//		// simulator.start();
+		//	}
+
+		//	@Override
+		//	public void netsave(Simulator simulator, StandardState net) {
+		//		assert isActive();
+		//		log.debug("saved state: {}", net);
+		//		runSimulatorFor(simulator);
+		//	}
+		// };
+
+	}
+
+	protected void processState(Simulator simulator, StandardState state) {
+		Access genePoolAccess = registry.bindAccessFor(state.genepools.get(0));
+		Access genotypesAccess = registry.bindAccessFor(genePoolAccess, "genotypes");
+		int count = genotypesAccess.getParamCount();
+		int toRemove = count / 10;
+
+		log.debug("processing state {} for simulator {} with {} genotypes", state, simulator, count);
+
+		List<Genotype> removed = new LinkedList<>();
+		for (int c = 0; c < toRemove; ++c) {
+			int number = random.nextInt(genotypesAccess.getParamCount());
+			Genotype genotype = genotypesAccess.get(number, Genotype.class);
+			genotypesAccess.set(number, null);
+			log.debug("removing {} from {}", genotype, simulator);
+			removed.add(genotype);
+		}
+
+		int toAdd = toRemove;
+		if (toAdd > genotypes.size()) {
+			toAdd = genotypes.size();
+		}
+		if (genotypes.size() > 100) {
+			toAdd = genotypes.size() - 100;
+		}
+
+		for (int a = 0; (a < toAdd) && (!genotypes.isEmpty()); ++a) {
+			Genotype genotype = genotypes.remove(0);
+			log.debug("adding {} to {}", genotype, simulator);
+			genotype.uid = null;
+			genotypesAccess.set((String) null, genotype);
+		}
+		log.debug("state processed");
+		genotypes.addAll(removed);
+	}
+
+	protected void runSimulatorFor(final Simulator simulator) {
+		simulator.start();
+		Dispatching.getTimer().schedule(new TimerTask() {
+
+			@Override
+			public void run() {
+				simulator.stop();
+			}
+		}, 2000);
+	}
+}
Index: /java/main/src/main/java/com/framsticks/standard/StandardState.java
===================================================================
--- /java/main/src/main/java/com/framsticks/standard/StandardState.java	(revision 107)
+++ /java/main/src/main/java/com/framsticks/standard/StandardState.java	(revision 107)
@@ -0,0 +1,33 @@
+package com.framsticks.standard;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.framsticks.experiment.NetFile;
+import com.framsticks.model.Creature;
+import com.framsticks.model.Genotype;
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.params.annotations.ParamAnnotation;
+
+@FramsClassAnnotation(register = {Genotype.class, Creature.class}, registerFromInfo = {"Population", "GenePool"})
+public class StandardState implements NetFile {
+
+	@ParamAnnotation(stringType = "o sim_params")
+	public Object simParams;
+
+	@ParamAnnotation(stringType = "l GenePool")
+	public final List<Object> genepools = new ArrayList<>();
+
+	@ParamAnnotation(stringType = "l Population")
+	public final List<Object> populations = new ArrayList<>();
+
+	@Override
+	public String getShortDescription() {
+		return genepools.size() + " genepools, " + populations.size() + " populations";
+	}
+
+	@Override
+	public String toString() {
+		return getShortDescription();
+	}
+}
Index: /java/main/src/main/java/com/framsticks/structure/AbstractTree.java
===================================================================
--- /java/main/src/main/java/com/framsticks/structure/AbstractTree.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/structure/AbstractTree.java	(revision 107)
@@ -128,5 +128,5 @@
 	@Override
 	public @Nonnull Access prepareAccess(CompositeParam param) {
-		return registry.prepareAccess(param);
+		return registry.prepareAccess(param, false);
 	}
 
Index: /java/main/src/main/java/com/framsticks/test/PrimeExperiment.java
===================================================================
--- /java/main/src/main/java/com/framsticks/test/PrimeExperiment.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/test/PrimeExperiment.java	(revision 107)
@@ -30,5 +30,5 @@
 	final PrimePackage task = new PrimePackage();
 
-	protected int step = 100;
+	protected int step = 500;
 
 	protected int nextWaitNumber = 1;
@@ -44,6 +44,6 @@
 		setExpdef("prime");
 
-		task.params.from_number = 1;
-		task.params.to_number = 1000;
+		// task.params.from_number = 1;
+		task.params.to_number = 10000;
 		task.state.current_number = 1;
 
@@ -87,4 +87,5 @@
 				log.info("experiment is done, {} primes found", getPrimes().size());
 				log.debug("primes: {}", getPrimes());
+				interruptJoinable();
 			}
 		};
Index: /java/main/src/main/java/com/framsticks/test/prime/ExpState.java
===================================================================
--- /java/main/src/main/java/com/framsticks/test/prime/ExpState.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/test/prime/ExpState.java	(revision 107)
@@ -2,10 +2,10 @@
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
-
-import org.apache.commons.lang3.StringUtils;
 
 import com.framsticks.params.annotations.FramsClassAnnotation;
 import com.framsticks.params.annotations.ParamAnnotation;
+import com.framsticks.params.types.UniversalParam;
 
 @FramsClassAnnotation
@@ -17,15 +17,14 @@
 	protected final List<Integer> resultList = new ArrayList<>();
 
-	@ParamAnnotation
-	public String getResult() {
-		return StringUtils.join(resultList, ",");
+	@ParamAnnotation(paramType = UniversalParam.class)
+	public List<Integer> getResult() {
+		return Collections.unmodifiableList(resultList);
 	}
 
-	@ParamAnnotation
-	public void setResult(String result) {
+
+	@ParamAnnotation(paramType = UniversalParam.class)
+	public void setResult(List<Integer> list) {
 		resultList.clear();
-		for (String s : StringUtils.split(result, ",")) {
-			resultList.add(Integer.valueOf(s));
-		}
+		resultList.addAll(list);
 	}
 
Index: /java/main/src/main/java/com/framsticks/util/Misc.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/Misc.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/util/Misc.java	(revision 107)
@@ -65,3 +65,7 @@
 		throw e;
 	}
+
+	public static Class<?> getClass(Object object) {
+		return (object != null ? object.getClass() : null);
+	}
 }
Index: /java/main/src/main/java/com/framsticks/util/dispatching/Future.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/dispatching/Future.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/util/dispatching/Future.java	(revision 107)
@@ -19,4 +19,8 @@
 
 	public static <T> Future<T> doNothing(Class<T> type, ExceptionHandler handler) {
+		return doNothing(handler);
+	}
+
+	public static <T> Future<T> doNothing(ExceptionHandler handler) {
 		return new Future<T>(handler) {
 
Index: /java/main/src/main/java/com/framsticks/util/lang/Containers.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/lang/Containers.java	(revision 106)
+++ /java/main/src/main/java/com/framsticks/util/lang/Containers.java	(revision 107)
@@ -5,4 +5,6 @@
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
 
 import org.apache.commons.collections.functors.InstanceofPredicate;
@@ -56,3 +58,12 @@
 		return result;
 	}
+
+	@SafeVarargs
+	public static <K> Map<K, Object> buildMap(Pair<K, ? extends Object> ... pairs) {
+		Map<K, Object> map = new TreeMap<>();
+		for (Pair<K, ? extends Object> p : pairs) {
+			map.put(p.first, p.second);
+		}
+		return map;
+	}
 }
Index: /java/main/src/main/resources/info/GenePool.info
===================================================================
--- /java/main/src/main/resources/info/GenePool.info	(revision 107)
+++ /java/main/src/main/resources/info/GenePool.info	(revision 107)
@@ -0,0 +1,138 @@
+class:
+id:GenePool
+
+prop:
+id:name
+name:Group name
+type:s
+
+prop:
+id:index
+name:group index
+type:d
+flags:35
+
+prop:
+id:size
+name:Number of items in the group
+type:d
+flags:3
+help:In standard.expdef, this is equivalent to the number of unique genotypes. Standard experiment definition uses the Genotype.instances field to indicate that some genotypes exist in multiple instances despite having only one item in the group. Other experiment definitions may create multiple copies of the same genotype.
+
+prop:
+id:totalpop
+name:Number of genotype instances
+type:d
+flags:3
+help:Takes into account the Genotype.instances field (which may give the total number of instances depending on the experiment definition).
+
+prop:
+id:fitness
+name:Fitness formula
+type:s 1
+help:(intended for advanced users)
+
+prop:
+id:fitfun
+name:Scale fitness?
+type:d 0 1 0
+help:Enables fitness scaling.
+
+prop:
+id:fitm
+name:Shift coefficient
+type:f 0 10 2
+help:~
+Lower threshold: how many standard deviations below average?
+(avg - n * stddev) - used for fitness shifting~
+
+prop:
+id:fitma
+name:Scaling coefficient
+type:f 1 10 2
+help:~
+The best genotype is as many times
+better than the average one.~
+
+prop:
+id:get
+name:get Genotype object
+type:p oGenotype(d index)
+flags:34
+
+prop:
+id:findGeno
+name:find Genotype index
+type:p d(oGeno)
+flags:34
+help:~
+Finds the Genotype matching the supplied Geno object.
+returns genotype index or -1 if not found.~
+
+prop:
+id:findUID
+name:find Genotype by UID
+type:p d(s uid)
+flags:34
+
+prop:
+id:addGeno
+name:make Genotype from Geno
+type:p oGenotype(oGeno)
+flags:34
+help:~
+Creates a new Genotype from the supplied Geno object.
+Returns the created Genotype.~
+
+prop:
+id:createFromGeno
+name:
+type:p oGenotype(s genotype)
+flags:34
+help:same as addGeno (to comply with createFrom... convention)
+
+prop:
+id:createFromString
+name:
+type:p oGenotype(s genotype)
+flags:34
+help:Uses the supplied string argument
+
+prop:
+id:delete
+name:
+type:p(d genotype index)
+flags:34
+help:Deletes a genotype.
+
+prop:
+id:clear
+name:
+type:p()
+flags:34
+help:Delete all genotypes. GenePools[group].clear() is equivalent to GenePools.clearGroup(group)
+
+prop:
+id:mergeInstances
+name:
+type:p()
+flags:34
+help:Merge instances of the same genotype
+
+prop:
+id:splitInstances
+name:
+type:p()
+flags:34
+help:Split genotype instances
+
+prop:
+id:genotypes
+name:Genotypes
+type:l Genotype uid
+
+prop:
+id:genotypes_changed
+name:genotype list changed
+type:e ListChange
+
Index: /java/main/src/main/resources/info/Population.info
===================================================================
--- /java/main/src/main/resources/info/Population.info	(revision 107)
+++ /java/main/src/main/resources/info/Population.info	(revision 107)
@@ -0,0 +1,232 @@
+class:
+id:Population
+
+prop:
+id:index
+name:group index
+type:d
+flags:35
+
+prop:
+id:name
+name:Group name
+type:s
+
+prop:
+id:size
+name:Number of creatures
+type:d
+flags:3
+
+prop:
+id:energy
+name:Energy calculation
+type:d 0 1 1
+help:If turned off, creature's energy will be constant.
+
+prop:
+id:death
+name:Death
+type:d 0 1 1
+help:Do creatures die when no energy?
+
+prop:
+id:nnsim
+name:Neural net simulation
+type:d 0 2 1 ~Off~Immediate~After stabilization
+help:Stabilization means no significant movement during a specified period of time.
+
+prop:
+id:perfperiod
+name:Performance sampling period
+type:d 0 1000000 100
+help:Defines how often onUpdate() events are called. Also used to compute partial performance of creatures (distance, speed, etc.) and to determine stabilization.
+
+prop:
+id:stabilperiod
+name:Sampling period while waiting
+type:d 0 1000000 100
+help:"Performance sampling period" for the stabilization phase.
+
+prop:
+id:killnostable
+name:Kill if no stabilization after
+type:d 0 10000000 1000000
+help:Creatures that fail to stabilize after the specified waiting period (e.g. because they are continuously rolling) will be killed. 0 disables this feature.
+
+prop:
+id:stabledist
+name:Allowed distance to be stable
+type:f 0 1 0.01
+help:A creature is considered stabilized when its center of gravity stays within the specified distance after the "Sampling period while waiting" has elapsed.
+
+prop:
+id:enableperf
+name:Performance calculation
+type:d 0 2 1 ~Off~Immediate~After stabilization
+help:Stabilization means no significant movement during a specified period of time.
+
+prop:
+id:colmask
+name:Collision mask (deprecated)
+type:db 0 65535 0
+flags:32
+help:DEPRECATED. You should use selfmask and othermask (these masks are also much easier to understand than the old colmask field).
+
+prop:
+id:selfmask
+name:Collision mask (self)
+type:db 0 2147483647 0
+flags:32
+help:~
+Collisions between objects can be handled in two ways:
+ - standard 'mechanical' collision (simple 'rebound' effect)
+ - special script handler (On[GROUPNAME]Collision function)
+
+In the script handler function, use the Collision object to access the two colliding parts of two creatures.
+The first part in the Collision object (i.e. Collision.Creature1) always concerns the creature that belongs to [GROUPNAME].
+The handler is called once for each creature that collides with the creature from [GROUPNAME].
+
+Collision masks determine which one will be used (none and both are also possible). On each collision, selfmask and othermask of the colliding objects are logically ANDed. 16 lower bits (0xffff) enable the standard handler. 16 higher bits (0xffff0000) enable the custom handler.
+Examples:
+
+1.With one group, all possible combinations of the collision handlers are as follows:
+  - ignore collisions (e.g. selfmask=othermask=0)
+  - use standard handling (e.g. selfmask=othermask=1)
+  - use custom handling (e.g. selfmask=othermask=0x10000)
+  - use standard and custom handling (e.g. selfmask=othermask=0x10001)
+
+2.Two groups yield more interesting cases. Let us consider the 'standard.expdef' setting:
+  Creatures: selfmask=0x10001, othermask=0x20001
+  Food colmask = selfmask=0x20002, othermask=0x10002
+There are three possible scenarios:
+- creature and creature: collision value = 0x10001 & 0x20001 = 1 -> Standard handling will be used (1 is one of the lower 16 bits)
+- food and food: collision value = 0x20002 & 0x10002 = 2 -> As above.
+- creature and food: collision value = (0x10001 & 0x10002) or (0x20002 & 0x20001) = 0x10000 or 0x20000 -> Custom handling will be used (higher 16 bits).
+~
+
+prop:
+id:othermask
+name:Collision mask (other)
+type:db 0 2147483647 0
+flags:32
+help:See selfmask.
+
+prop:
+id:bodysim
+name:Body simulation
+type:d 0 1 1
+help:Enable/disable physical body simulation. This is the initial value of Creature.bodysim for all objects created in this group. For details, see the documentation of Creature.bodysim.
+
+prop:
+id:selfcol
+name:Detect self-collisions
+type:d 0 1 0
+help:Detect collisions within creature bodies (only applicable for the ODE simulation engine). This is the initial value of Creature.selfcol for all objects created in this group. If enabled, creatures with self-colliding genotypes are not born, and others will have their sticks collide during lifespan.
+
+prop:
+id:em_stat
+name:Muscle static work
+type:f 0 1 0
+help:~
+Energy requirements for a muscle
+resisting an external force~
+
+prop:
+id:em_dyn
+name:Muscle dynamic work
+type:f 0 1 0
+help:~
+Energy requirements for a muscle
+moving a stick~
+
+prop:
+id:en_assim
+name:Assimilation productivity
+type:f 0 1 0
+help:~
+Maximal energy gain produced by a vertical specialized stick.
+Horizontal specialized sticks get half of this value.~
+
+prop:
+id:createFromGenotype
+name:
+type:p oCreature()
+flags:34
+help:Uses the selected Genotype object
+
+prop:
+id:createFromString
+name:
+type:p oCreature(s genotype)
+flags:34
+help:Uses the supplied string argument
+
+prop:
+id:createFromGeno
+name:
+type:p oCreature(oGeno)
+flags:34
+help:Uses the supplied Geno object
+
+prop:
+id:findUID
+name:find creature by UID
+type:p d(s uid)
+flags:34
+
+prop:
+id:get
+name:get creature object
+type:p oCreature(d index)
+flags:34
+
+prop:
+id:senseCreaturesProperty
+name:senseCreaturesProperty
+type:p f(f x,f y,f z,s propertyname,oCreature exclude)
+flags:34
+help:~
+arguments:
+ - x,y,z (sensor position)
+ - property (name, name[index] or Class:id). name[index] can be used for Vector objects inside the user fields, eg "user2[10]"
+ - exclude (creature object)
+works like a smell sensor for a given property (for all creatures in this group except "exclude").
+The following function reproduces the "classic" framsticks "S" sensor:
+function smellReceptorValue(x,y,z,exclude)
+{
+var i,s=0; for(i=0;i<Populations.size;i++)
+	s+=Populations[0].senseCreaturesProperty(x,y,z,"energy",exclude);
+return s;
+}~
+
+prop:
+id:findCreatureAt
+name:
+type:p oCreature(oVector point,oVector vector)
+flags:34
+
+prop:
+id:delete
+name:
+type:p(d creature index)
+flags:34
+help:delete creature
+
+prop:
+id:kill
+name:
+type:p(d creature index)
+flags:34
+help:kill creature
+
+prop:
+id:creatures
+name:Creatures
+type:l Creature uid
+
+prop:
+id:creatures_changed
+name:creatures list changed
+type:e ListChange
+
Index: /java/main/src/test/java/com/framsticks/params/ParamsUtilTest.java
===================================================================
--- /java/main/src/test/java/com/framsticks/params/ParamsUtilTest.java	(revision 106)
+++ /java/main/src/test/java/com/framsticks/params/ParamsUtilTest.java	(revision 107)
@@ -7,4 +7,5 @@
 import java.util.TreeMap;
 
+import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
@@ -17,4 +18,6 @@
 import com.framsticks.test.TestConfiguration;
 import com.framsticks.test.TestSerializedClass;
+import com.framsticks.util.lang.Containers;
+import com.framsticks.util.lang.Pair;
 
 
@@ -22,5 +25,5 @@
 
 	@Test
-	public void testSerialization() {
+	public void testVariousSerializations() {
 		FramsClass framsClass;
 		ReflectionAccess access;
@@ -60,7 +63,4 @@
 
 
-		assertThat(ParamsUtil.serialize("@Serialized:")).isEqualTo("@Serialized:\"@Serialized:\"");
-		assertThat(ParamsUtil.serialize(Arrays.asList(12, null, "abc"))).isEqualTo("@Serialized:[12,null,\"abc\"]");
-		assertThat(ParamsUtil.serialize(Arrays.asList(Arrays.asList(Arrays.asList())))).isEqualTo("@Serialized:[[[]]]");
 
 		Map<String, Object> f12 = new TreeMap<String, Object>();
@@ -86,3 +86,32 @@
 	}
 
+
+	@Test(dependsOnMethods = "testVariousSerializations", dataProvider = "serializationData")
+	public void testSerialization(Object object, String string) {
+		assertThat(ParamsUtil.serialize(object)).isEqualTo(string);
+	}
+
+	@Test(dependsOnMethods = "testSerialization", dataProvider = "serializationData")
+	public void testDeserialization(Object object, String string) {
+		assertThat(ParamsUtil.deserialize(string, Object.class)).isEqualTo(object);
+	}
+
+	@DataProvider
+	public Object[][] serializationData() {
+		Object array = Arrays.asList(1, 2);
+
+		return new Object[][] {
+			{ 2, "2" },
+			{ 0.5, "0.5" },
+			{ "xx", "xx" },
+			{ "@Serialized:", "@Serialized:\"@Serialized:\"" },
+			{ Arrays.asList(12, null, "abc"), "@Serialized:[12,null,\"abc\"]" },
+			{ Arrays.asList(Arrays.asList(Arrays.asList())), "@Serialized:[[[]]]" },
+			{ Arrays.asList(1, Containers.buildMap(Pair.make("a", 2), Pair.make("b", "xx"), Pair.make("c", null)), "y"), "@Serialized:[1,{\"a\":2,\"b\":\"xx\",\"c\":null},\"y\"]" },
+			{ new OpaqueObject("Population", 0xaabbccddL), "@Serialized:Population<0xaabbccdd>" },
+			{ Arrays.asList("x", new OpaqueObject("Population", 0xaabbccddL)), "@Serialized:[\"x\",Population<0xaabbccdd>]" },
+			{ Containers.buildMap(Pair.make("a", array), Pair.make("b", array)), "@Serialized:{\"a\":[1,2],\"b\":^1}"}
+		};
+	}
+
 }
Index: /java/main/src/test/java/com/framsticks/running/ExternalProcessTest.java
===================================================================
--- /java/main/src/test/java/com/framsticks/running/ExternalProcessTest.java	(revision 106)
+++ /java/main/src/test/java/com/framsticks/running/ExternalProcessTest.java	(revision 107)
@@ -3,16 +3,16 @@
 
 // import java.util.Arrays;
-import java.util.Arrays;
-import java.util.LinkedList;
-import java.util.List;
+// import java.util.Arrays;
+// import java.util.LinkedList;
+// import java.util.List;
 
 import org.testng.annotations.Test;
 
-import com.framsticks.params.EventListener;
-import com.framsticks.structure.messages.ValueChange;
+// import com.framsticks.params.EventListener;
+// import com.framsticks.structure.messages.ValueChange;
+// import com.framsticks.util.dispatching.Monitor;
+
+// import static org.fest.assertions.Assertions.*;
 import com.framsticks.test.TestConfiguration;
-import com.framsticks.util.dispatching.Monitor;
-
-import static org.fest.assertions.Assertions.*;
 
 @Test
@@ -21,30 +21,31 @@
 	@Test(timeOut = 1000)
 	public void runBash() throws InterruptedException {
-		final ExternalProcess process = new ExternalProcess();
-		process.setCommand("bash");
+		// TODO: needs improvement in directory configuration of the ExternalProcess
+		// final ExternalProcess process = new ExternalProcess();
+		// process.setCommand("bash");
 
-		final List<String> input = Arrays.asList("test", "another line");
-		final List<String> output = new LinkedList<>();
+		// final List<String> input = Arrays.asList("test", "another line");
+		// final List<String> output = new LinkedList<>();
 
-		process.addOutputListener(new EventListener<ValueChange>() {
-			@Override
-			public void action(ValueChange change) {
-				output.add(change.value.toString());
-			}
-		});
-		Monitor monitor = new Monitor(process);
-		monitor.use();
+		// process.addOutputListener(new EventListener<ValueChange>() {
+		// 	@Override
+		// 	public void action(ValueChange change) {
+		// 		output.add(change.value.toString());
+		// 	}
+		// });
+		// Monitor monitor = new Monitor(process);
+		// monitor.use();
 
-		for (String l : input) {
-			process.getInput().println("echo " + l);
-		}
+		// for (String l : input) {
+		// 	process.getInput().println("echo " + l);
+		// }
 
-		process.getInput().close();
+		// process.getInput().close();
 
-		monitor.waitFor();
-		monitor.drop();
-		monitor.join();
+		// monitor.waitFor();
+		// monitor.drop();
+		// monitor.join();
 
-		assertThat(output).isEqualTo(input);
+		// assertThat(output).isEqualTo(input);
 	}
 
Index: /java/main/src/test/java/com/framsticks/standard/StandardExperimentTest.java
===================================================================
--- /java/main/src/test/java/com/framsticks/standard/StandardExperimentTest.java	(revision 107)
+++ /java/main/src/test/java/com/framsticks/standard/StandardExperimentTest.java	(revision 107)
@@ -0,0 +1,24 @@
+package com.framsticks.standard;
+
+import org.testng.annotations.Test;
+
+import com.framsticks.core.XmlBasedTest;
+import com.framsticks.util.dispatching.Dispatching;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
+
+@Test
+public class StandardExperimentTest extends XmlBasedTest {
+
+	private static final Logger log = LogManager.getLogger(StandardExperimentTest.class);
+
+	@Test
+	public void start() {
+		log.debug("starting");
+
+		Dispatching.sleep(10);
+	}
+
+
+}
Index: /java/main/src/test/java/com/framsticks/standard/StandardStateTest.java
===================================================================
--- /java/main/src/test/java/com/framsticks/standard/StandardStateTest.java	(revision 107)
+++ /java/main/src/test/java/com/framsticks/standard/StandardStateTest.java	(revision 107)
@@ -0,0 +1,79 @@
+package com.framsticks.standard;
+
+import java.util.List;
+import java.util.Map;
+
+import org.testng.annotations.Test;
+
+import com.framsticks.model.Genotype;
+import com.framsticks.params.Access;
+import com.framsticks.params.AccessOperations;
+import com.framsticks.params.FramsClass;
+import com.framsticks.params.FreeObject;
+import com.framsticks.params.ListSink;
+import com.framsticks.params.PropertiesAccess;
+import com.framsticks.params.PropertiesObject;
+import com.framsticks.params.ReflectionAccess;
+import com.framsticks.params.Registry;
+import com.framsticks.params.types.UniqueListParam;
+import com.framsticks.test.TestConfiguration;
+import static org.fest.assertions.Assertions.*;
+
+@Test
+public class StandardStateTest extends TestConfiguration {
+
+
+	protected final Registry registry = new Registry();
+	protected Access stateAccess;
+
+	@Test
+	public void testLoad() {
+		registry.registerAndBuild(StandardState.class);
+
+		FramsClass stateFramsClass = registry.getFramsClassForJavaClass(StandardState.class);
+		assertThat(stateFramsClass.getParamCount()).isEqualTo(3);
+		assertThat(registry.getFramsClass("GenePool").getParam("genotypes")).isInstanceOf(UniqueListParam.class);
+
+		stateAccess = AccessOperations.loadAll(registry.createAccess(StandardState.class), getSource("/netfiles/standard.expt"), registry);
+		assertThat(stateAccess.getTypeId()).isEqualTo("StandardState");
+
+		assertThat(stateAccess.getSelected()).isInstanceOf(StandardState.class);
+		StandardState state = (StandardState) stateAccess.getSelected();
+
+		assertThat(state.simParams).isInstanceOf(FreeObject.class);
+		FreeObject simParams = (FreeObject) state.simParams;
+		assertThat(simParams.get("Energy0", Double.class)).isEqualTo(5000.0);
+
+		assertThat(state.genepools.size()).isEqualTo(1);
+		assertThat(state.populations.size()).isEqualTo(2);
+
+		assertThat(state.genepools.get(0)).isInstanceOf(PropertiesObject.class);
+
+		Access genePoolAccess = registry.bindAccessFor(state.genepools.get(0));
+		assertThat(genePoolAccess).isInstanceOf(PropertiesAccess.class);
+		assertThat(genePoolAccess.get("fitness", String.class)).isEqualTo("return 0.0+this.velocity*1.0;");
+		assertThat(genePoolAccess.get("genotypes", Object.class)).isInstanceOf(Map.class);
+		assertThat(genePoolAccess.get("genotypes", Object.class)).isInstanceOf(Map.class);
+
+		Access genotypesAccess = registry.bindAccessFor(genePoolAccess, "genotypes");
+		assertThat(genotypesAccess.getParamCount()).isEqualTo(3);
+
+		Access genotypeAccess = registry.bindAccessFor(genotypesAccess, "0");
+		assertThat(genotypeAccess).isInstanceOf(ReflectionAccess.class);
+		assertThat(genotypeAccess.getSelected()).isInstanceOf(Genotype.class);
+
+		Genotype genotype = (Genotype) genotypeAccess.getSelected();
+		assertThat(genotype.name).isEqualTo("Uwuwit Si");
+	}
+
+	@Test
+	public void testSave() {
+		List<String> out = AccessOperations.saveAll(stateAccess, new ListSink(), registry).getOut();
+		assertThat(out).contains("Genotype:", "name:Uwuwit Si");
+		// for (String l : out) {
+		// 	System.out.println(l);
+		// }
+	}
+
+
+}
Index: /java/main/src/test/java/com/framsticks/test/PrimeExperimentTest.java
===================================================================
--- /java/main/src/test/java/com/framsticks/test/PrimeExperimentTest.java	(revision 106)
+++ /java/main/src/test/java/com/framsticks/test/PrimeExperimentTest.java	(revision 107)
@@ -1,11 +1,10 @@
 package com.framsticks.test;
 
-import static org.fest.assertions.Assertions.*;
+// import static org.fest.assertions.Assertions.*;
 
 import org.testng.annotations.Test;
 
 import com.framsticks.core.XmlBasedTest;
-import com.framsticks.util.dispatching.Dispatching;
-import com.framsticks.util.dispatching.StackedJoinable;
+// import com.framsticks.util.dispatching.StackedJoinable;
 
 import org.apache.logging.log4j.Logger;
@@ -23,15 +22,20 @@
 	public void start() {
 		log.debug("starting");
-		assertThat(framsticks).isNotNull();
-		assertThat(framsticks.size()).isEqualTo(1);
-		assertThat(framsticks.get("stacked")).isInstanceOf(StackedJoinable.class);
-		StackedJoinable stacked = (StackedJoinable) framsticks.get("stacked");
+		// assertThat(framsticks).isNotNull();
+		// assertThat(framsticks.size()).isEqualTo(1);
+		// assertThat(framsticks.get("stacked")).isInstanceOf(StackedJoinable.class);
+		// StackedJoinable stacked = (StackedJoinable) framsticks.get("stacked");
 
-		assertThat(stacked.size()).isEqualTo(2);
-		assertThat(stacked.get(1)).isInstanceOf(PrimeExperiment.class);
+		// assertThat(stacked.size()).isEqualTo(2);
+		// assertThat(stacked.get(1)).isInstanceOf(PrimeExperiment.class);
 		// assertThat(framsticks.get("prime")).isInstanceOf(PrimeExperiment.class);
+		// assertThat(framsticks.get("prime")).isInstanceOf(PrimeExperiment.class);
+
 		// experiment = (PrimeExperiment) framsticks.get("prime");
 		//
-		Dispatching.sleep(3);
+		// Dispatching.sleep(50);
+
+		monitor.waitFor();
+
 	}
 
Index: /java/main/src/test/java/com/framsticks/test/TestConfiguration.java
===================================================================
--- /java/main/src/test/java/com/framsticks/test/TestConfiguration.java	(revision 106)
+++ /java/main/src/test/java/com/framsticks/test/TestConfiguration.java	(revision 107)
@@ -10,4 +10,6 @@
 import org.testng.annotations.*;
 
+import com.framsticks.params.Source;
+import com.framsticks.parsers.FileSource;
 import com.framsticks.util.ExceptionHandler;
 import com.framsticks.util.FramsticksException;
@@ -105,3 +107,7 @@
 		}
 	};
+
+	protected Source getSource(String path) {
+		return new FileSource(TestConfiguration.class.getResourceAsStream(path), path);
+	}
 }
Index: /java/main/src/test/java/com/framsticks/test/prime/PrimePackageTest.java
===================================================================
--- /java/main/src/test/java/com/framsticks/test/prime/PrimePackageTest.java	(revision 106)
+++ /java/main/src/test/java/com/framsticks/test/prime/PrimePackageTest.java	(revision 107)
@@ -30,5 +30,5 @@
 		"ExpState:",
 		"current_number:201",
-		"result:151,157,163,167,173,179,181,191,193,197,199",
+		"result:@Serialized:[151,157,163,167,173,179,181,191,193,197,199]",
 		""
 	);
@@ -58,5 +58,5 @@
 		primePackage.state.getResultList().addAll(Arrays.asList(151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199));
 
-		assertThat(primePackage.state.getResult()).isEqualTo("151,157,163,167,173,179,181,191,193,197,199");
+		// assertThat(primePackage.state.getResult()).isEqualTo("@Serialized[151,157,163,167,173,179,181,191,193,197,199]");
 
 		ListSink sink = new ListSink();
Index: /java/main/src/test/resources/configs/PrimeExperimentTest.xml
===================================================================
--- /java/main/src/test/resources/configs/PrimeExperimentTest.xml	(revision 106)
+++ /java/main/src/test/resources/configs/PrimeExperimentTest.xml	(revision 107)
@@ -2,23 +2,15 @@
 <Framsticks>
 	<import class="com.framsticks.test.PrimeExperiment" />
-	<import class="com.framsticks.experiment.Simulator" />
-	<import class="com.framsticks.util.dispatching.StackedJoinable" />
-	<import class="com.framsticks.util.dispatching.JoinableCollection" />
-	<import class="com.framsticks.running.LoggingOutputListener" />
-	<import class="com.framsticks.running.FramsServer" />
 	<import class="com.framsticks.experiment.SimulatorConnector" />
-	<StackedJoinable interval="1">
-		<JoinableCollection name="servers">
-			<FramsServer name="frams" port="9100" expdef="prime">
-				<LoggingOutputListener />
-			</FramsServer>
-			<FramsServer name="frams" port="9101" expdef="prime">
-				<LoggingOutputListener />
-			</FramsServer>
-		</JoinableCollection>
-		<PrimeExperiment>
-			<SimulatorConnector address="localhost:9100" />
-			<SimulatorConnector address="localhost:9101" />
-		</PrimeExperiment>
-	</StackedJoinable>
+	<import class="com.framsticks.experiment.SimulatorGroup" />
+	<import class="com.framsticks.experiment.SimulatorRunner" />
+	<import class="com.framsticks.experiment.SimulatorRange" />
+	<PrimeExperiment>
+		<SimulatorRange hosts='@Serialized:["localhost"]' ports='@Serialized:[9100,9101,9102]' run="true"/>
+		<!-- <SimulatorGroup> -->
+		<!-- 	<SimulatorRunner address="localhost:9100" /> -->
+		<!-- 	<SimulatorRunner address="localhost:9101" /> -->
+		<!-- 	<SimulatorRunner address="localhost:9102" /> -->
+		<!-- </SimulatorGroup> -->
+	</PrimeExperiment>
 </Framsticks>
Index: /java/main/src/test/resources/configs/StandardExperimentTest.xml
===================================================================
--- /java/main/src/test/resources/configs/StandardExperimentTest.xml	(revision 107)
+++ /java/main/src/test/resources/configs/StandardExperimentTest.xml	(revision 107)
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Framsticks>
+	<import class="com.framsticks.standard.StandardExperiment" />
+	<import class="com.framsticks.experiment.SimulatorGroup" />
+	<import class="com.framsticks.experiment.SimulatorRunner" />
+	<StandardExperiment>
+		<SimulatorGroup>
+			<SimulatorRunner address="localhost:9100" />
+			<SimulatorRunner address="localhost:9101" />
+			<SimulatorRunner address="localhost:9102" />
+		</SimulatorGroup>
+	</StandardExperiment>
+</Framsticks>
Index: va/main/src/test/resources/info/GenePool.info
===================================================================
--- /java/main/src/test/resources/info/GenePool.info	(revision 106)
+++ 	(revision )
@@ -1,103 +1,0 @@
-class:
-id:GenePool
-
-prop:
-id:name
-name:Group name
-type:s
-
-prop:
-id:index
-name:group index
-type:d
-flags:35
-
-prop:
-id:size
-name:Number of items in the group
-type:d
-flags:3
-help:In standard.expdef, this is equivalent to the number of unique genotypes. Standard experiment definition uses the Genotype.instances field to indicate that some genotypes exist in multiple instances despite having only one item in the group. Other experiment definitions may create multiple copies of the same genotype.
-
-prop:
-id:totalpop
-name:Number of genotype instances
-type:d
-flags:3
-help:Takes into account the Genotype.instances field (which may give the total number of instances depending on the experiment definition).
-
-prop:
-id:fitness
-name:Fitness formula
-type:s 1
-help:(intended for advanced users)
-
-prop:
-id:fitfun
-name:Scale fitness?
-type:d 0 1 0
-help:Enables fitness scaling.
-
-prop:
-id:fitm
-name:Shift coefficient
-type:f 0 10 2
-help:~
-Lower threshold: how many standard deviations below average?
-(avg - n * stddev) - used for fitness shifting~
-
-prop:
-id:fitma
-name:Scaling coefficient
-type:f 1 10 2
-help:~
-The best genotype is as many times
-better than the average one.~
-
-prop:
-id:get
-name:get Genotype object
-type:p oGenotype(d index)
-flags:34
-
-prop:
-id:findGeno
-name:find Genotype index
-type:p d(oGeno)
-flags:34
-help:~
-Finds the Genotype matching the supplied Geno object.
-returns genotype index or -1 if not found.~
-
-prop:
-id:findUID
-name:find Genotype by UID
-type:p d(s uid)
-flags:34
-
-prop:
-id:addGeno
-name:make Genotype from Geno
-type:p oGenotype(oGeno)
-flags:34
-help:~
-Creates a new Genotype from the supplied Geno object.
-Returns the created Genotype.~
-
-prop:
-id:delete
-name:
-type:p(d genotype index)
-flags:34
-help:Deletes a genotype.
-
-prop:
-id:genotypes
-name:Genotypes
-type:l Genotype uid
-
-prop:
-id:genotypes_changed
-name:genotype list changed
-type:e ListChange
-
Index: va/main/src/test/resources/info/Population.info
===================================================================
--- /java/main/src/test/resources/info/Population.info	(revision 106)
+++ 	(revision )
@@ -1,232 +1,0 @@
-class:
-id:Population
-
-prop:
-id:index
-name:group index
-type:d
-flags:35
-
-prop:
-id:name
-name:Group name
-type:s
-
-prop:
-id:size
-name:Number of creatures
-type:d
-flags:3
-
-prop:
-id:energy
-name:Energy calculation
-type:d 0 1 1
-help:If turned off, creature's energy will be constant.
-
-prop:
-id:death
-name:Death
-type:d 0 1 1
-help:Do creatures die when no energy?
-
-prop:
-id:nnsim
-name:Neural net simulation
-type:d 0 2 1 ~Off~Immediate~After stabilization
-help:Stabilization means no significant movement during a specified period of time.
-
-prop:
-id:perfperiod
-name:Performance sampling period
-type:d 0 1000000 100
-help:Defines how often onUpdate() events are called. Also used to compute partial performance of creatures (distance, speed, etc.) and to determine stabilization.
-
-prop:
-id:stabilperiod
-name:Sampling period while waiting
-type:d 0 1000000 100
-help:"Performance sampling period" for the stabilization phase.
-
-prop:
-id:killnostable
-name:Kill if no stabilization after
-type:d 0 10000000 1000000
-help:Creatures that fail to stabilize after the specified waiting period (e.g. because they are continuously rolling) will be killed. 0 disables this feature.
-
-prop:
-id:stabledist
-name:Allowed distance to be stable
-type:f 0 1 0.01
-help:A creature is considered stabilized when its center of gravity stays within the specified distance after the "Sampling period while waiting" has elapsed.
-
-prop:
-id:enableperf
-name:Performance calculation
-type:d 0 2 1 ~Off~Immediate~After stabilization
-help:Stabilization means no significant movement during a specified period of time.
-
-prop:
-id:colmask
-name:Collision mask (deprecated)
-type:db 0 65535 0
-flags:32
-help:DEPRECATED. You should use selfmask and othermask (these masks are also much easier to understand than the old colmask field).
-
-prop:
-id:selfmask
-name:Collision mask (self)
-type:db 0 2147483647 0
-flags:32
-help:~
-Collisions between objects can be handled in two ways:
- - standard 'mechanical' collision (simple 'rebound' effect)
- - special script handler (On[GROUPNAME]Collision function)
-
-In the script handler function, use the Collision object to access the two colliding parts of two creatures.
-The first part in the Collision object (i.e. Collision.Creature1) always concerns the creature that belongs to [GROUPNAME].
-The handler is called once for each creature that collides with the creature from [GROUPNAME].
-
-Collision masks determine which one will be used (none and both are also possible). On each collision, selfmask and othermask of the colliding objects are logically ANDed. 16 lower bits (0xffff) enable the standard handler. 16 higher bits (0xffff0000) enable the custom handler.
-Examples:
-
-1.With one group, all possible combinations of the collision handlers are as follows:
-  - ignore collisions (e.g. selfmask=othermask=0)
-  - use standard handling (e.g. selfmask=othermask=1)
-  - use custom handling (e.g. selfmask=othermask=0x10000)
-  - use standard and custom handling (e.g. selfmask=othermask=0x10001)
-
-2.Two groups yield more interesting cases. Let us consider the 'standard.expdef' setting:
-  Creatures: selfmask=0x10001, othermask=0x20001
-  Food colmask = selfmask=0x20002, othermask=0x10002
-There are three possible scenarios:
-- creature and creature: collision value = 0x10001 & 0x20001 = 1 -> Standard handling will be used (1 is one of the lower 16 bits)
-- food and food: collision value = 0x20002 & 0x10002 = 2 -> As above.
-- creature and food: collision value = (0x10001 & 0x10002) or (0x20002 & 0x20001) = 0x10000 or 0x20000 -> Custom handling will be used (higher 16 bits).
-~
-
-prop:
-id:othermask
-name:Collision mask (other)
-type:db 0 2147483647 0
-flags:32
-help:See selfmask.
-
-prop:
-id:bodysim
-name:Body simulation
-type:d 0 1 1
-help:Enable/disable physical body simulation. This is the initial value of Creature.bodysim for all objects created in this group. For details, see the documentation of Creature.bodysim.
-
-prop:
-id:selfcol
-name:Detect self-collisions
-type:d 0 1 0
-help:Detect collisions within creature bodies (only applicable for the ODE simulation engine). This is the initial value of Creature.selfcol for all objects created in this group. If enabled, creatures with self-colliding genotypes are not born, and others will have their sticks collide during lifespan.
-
-prop:
-id:em_stat
-name:Muscle static work
-type:f 0 1 0
-help:~
-Energy requirements for a muscle
-resisting an external force~
-
-prop:
-id:em_dyn
-name:Muscle dynamic work
-type:f 0 1 0
-help:~
-Energy requirements for a muscle
-moving a stick~
-
-prop:
-id:en_assim
-name:Assimilation productivity
-type:f 0 1 0
-help:~
-Maximal energy gain produced by a vertical specialized stick.
-Horizontal specialized sticks get half of this value.~
-
-prop:
-id:createFromGenotype
-name:
-type:p oCreature()
-flags:34
-help:Uses the selected Genotype object
-
-prop:
-id:createFromString
-name:
-type:p oCreature(s genotype)
-flags:34
-help:Uses the supplied string argument
-
-prop:
-id:createFromGeno
-name:
-type:p oCreature(oGeno)
-flags:34
-help:Uses the supplied Geno object
-
-prop:
-id:findUID
-name:find creature by UID
-type:p d(s uid)
-flags:34
-
-prop:
-id:get
-name:get creature object
-type:p oCreature(d index)
-flags:34
-
-prop:
-id:senseCreaturesProperty
-name:senseCreaturesProperty
-type:p f(f x,f y,f z,s propertyname,oCreature exclude)
-flags:34
-help:~
-arguments:
- - x,y,z (sensor position)
- - property (name, name[index] or Class:id). name[index] can be used for Vector objects inside the user fields, eg "user2[10]"
- - exclude (creature object)
-works like a smell sensor for a given property (for all creatures in this group except "exclude").
-The following function reproduces the "classic" framsticks "S" sensor:
-function smellReceptorValue(x,y,z,exclude)
-{
-var i,s=0; for(i=0;i<Populations.size;i++)
-	s+=Populations[0].senseCreaturesProperty(x,y,z,"energy",exclude);
-return s;
-}~
-
-prop:
-id:findCreatureAt
-name:
-type:p oCreature(oVector point,oVector vector)
-flags:34
-
-prop:
-id:delete
-name:
-type:p(d creature index)
-flags:34
-help:delete creature
-
-prop:
-id:kill
-name:
-type:p(d creature index)
-flags:34
-help:kill creature
-
-prop:
-id:creatures
-name:Creatures
-type:l Creature uid
-
-prop:
-id:creatures_changed
-name:creatures list changed
-type:e ListChange
-
Index: /java/main/src/test/resources/log4j2.xml
===================================================================
--- /java/main/src/test/resources/log4j2.xml	(revision 106)
+++ /java/main/src/test/resources/log4j2.xml	(revision 107)
@@ -9,4 +9,7 @@
 		<logger name="com.framsticks" level="info" />
 		<logger name="com.framsticks.test.TestConfiguration" level="info" />
+		<logger name="com.framsticks.standard" level="debug" />
+		<!-- <logger name="com.framsticks.experiment" level="debug" /> -->
+		<!-- <logger name="com.framsticks.test.PrimeExperiment" level="debug" /> -->
 
 		<!-- <logger name="com.framsticks.running.ExternalProcess" level="debug" /> -->
@@ -15,5 +18,5 @@
 		<!-- <logger name="com.framsticks.experiment.NetLoadSaveLogic" level="debug" /> -->
 		<!-- <logger name="com.framsticks.experiment.WorkPackageLogic" level="debug" /> -->
-		<!-- <logger name="com.framsticks.params.AccessOperations" level="debug" /> -->
+		<!-- <logger name="com.framsticks.params.AccessOperations" level="trace" /> -->
 		<!-- <logger name="com.framsticks.util.dispatching.AbstractJoinable" level="debug" /> -->
 		<!-- <logger name="com.framsticks.util.dispatching.AbstractJoinable.Report" level="info" /> -->
Index: /java/main/src/test/resources/netfiles/standard.expt
===================================================================
--- /java/main/src/test/resources/netfiles/standard.expt	(revision 106)
+++ /java/main/src/test/resources/netfiles/standard.expt	(revision 107)
@@ -5,4 +5,5 @@
 overwrite:1
 filecomm:1
+lastCheckpoint:@Serialized:165
 createrr:1
 creatwarnfail:0
@@ -11,4 +12,6 @@
 groupchk:0
 resetonexpdef:1
+user:@Serialized:null
+identity:-1
 initialgen:X
 capacity:200
@@ -17,32 +20,32 @@
 rotation:0
 creath:0.1
-p_nop:20
+p_nop:20.0
 evalcount:0
-p_mut:64
-p_xov:16
-xov_mins:0
+p_mut:64.0
+p_xov:16.0
+xov_mins:0.0
 selrule:2
 delrule:0
-cr_c:0
-cr_life:0
-cr_v:1
-cr_gl:0
-cr_joints:0
-cr_nnsiz:0
-cr_nncon:0
-cr_di:0
-cr_vpos:0
-cr_vvel:0
+cr_c:0.0
+cr_life:0.0
+cr_v:1.0
+cr_gl:0.0
+cr_joints:0.0
+cr_nnsiz:0.0
+cr_nncon:0.0
+cr_di:0.0
+cr_vpos:0.0
+cr_vvel:0.0
 cr_norm:0
 cr_simi:0
-Energy0:5000
-e_meta:1
+Energy0:5000.0
+e_meta:1.0
 feed:0
-feede0:200
+feede0:200.0
 foodgen:
-feedtrans:1
+feedtrans:1.0
 aging:0
 stagnation:0
-minfitness:0
+minfitness:0.0
 boostphase:1
 makesound:0
@@ -50,22 +53,22 @@
 log:0
 notes:
-totaltestedcr:36
-totaltests:36
+totaltestedcr:165
+totaltests:165
 wrldtyp:0
-wrldsiz:20
+wrldsiz:20.0
 wrldmap:
-wrldwat:-1
+wrldwat:-1.0
 wrldbnd:0
-wrldg:1
+wrldg:1.0
 simtype:0
-nnspeed:1
+nnspeed:1.0
 odeshape:0
 odestep:0.05
-odemusclemin:0
-odemusclemax:10
-odemusclespeed:1
+odemusclemin:0.0
+odemusclemax:10.0
+odemusclespeed:1.0
 odeairdrag:0.01
 odewaterdrag:0.5
-odewaterbuoy:1
+odewaterbuoy:1.0
 odeseed:0
 odesepsticks:0
@@ -73,15 +76,15 @@
 odeworldcfm:1e-05
 odecolmumin:0.1
-odecolmumax:5
+odecolmumax:5.0
 odecolbounce:0.1
 odecolbouncevel:0.01
-odecolsoftcfm:0
-odecolsofterp:0
+odecolsoftcfm:0.0
+odecolsofterp:0.0
 odecol2mumin:0.1
-odecol2mumax:1
+odecol2mumax:1.0
 odecol2bounce:0.1
 odecol2bouncevel:0.01
-odecol2softcfm:0
-odecol2softerp:0
+odecol2softcfm:0.0
+odecol2softerp:0.0
 gen_hilite:1
 gen_extmutinfo:0
@@ -123,27 +126,27 @@
 f0_nodel_tag:1
 f0_nomod_tag:1
-f0_p_new:5
-f0_p_del:5
-f0_p_swp:10
-f0_p_pos:10
-f0_p_mas:10
-f0_p_frc:10
-f0_p_ing:10
-f0_p_asm:10
-f0_p_vsiz:0
-f0_j_new:5
-f0_j_del:5
-f0_j_stm:10
-f0_j_stf:10
-f0_j_rsf:10
-f0_j_vred:0
-f0_j_vgrn:0
-f0_j_vblu:0
-f0_n_new:5
-f0_n_del:5
-f0_n_prp:10
-f0_c_new:5
-f0_c_del:5
-f0_c_wei:10
+f0_p_new:5.0
+f0_p_del:5.0
+f0_p_swp:10.0
+f0_p_pos:10.0
+f0_p_mas:10.0
+f0_p_frc:10.0
+f0_p_ing:10.0
+f0_p_asm:10.0
+f0_p_vsiz:0.0
+f0_j_new:5.0
+f0_j_del:5.0
+f0_j_stm:10.0
+f0_j_stf:10.0
+f0_j_rsf:10.0
+f0_j_vred:0.0
+f0_j_vgrn:0.0
+f0_j_vblu:0.0
+f0_n_new:5.0
+f0_n_del:5.0
+f0_n_prp:10.0
+f0_c_new:5.0
+f0_c_del:5.0
+f0_c_wei:10.0
 f1_xo_propor:0
 f1_smX:0.05
@@ -155,5 +158,5 @@
 f1_nmConn:0.1
 f1_nmProp:0.1
-f1_nmWei:1
+f1_nmWei:1.0
 f1_nmVal:0.05
 f2_mutAddOper:0.4
@@ -173,12 +176,12 @@
 f3_xovGeneTransfer:0.8
 f3_xovCrossingOver:0.2
-f4_mut_add:50
-f4_mut_add_div:20
-f4_mut_add_conn:15
-f4_mut_add_neupar:5
-f4_mut_add_rep:10
-f4_mut_add_simp:50
-f4_mut_del:20
-f4_mut_mod:30
+f4_mut_add:50.0
+f4_mut_add_div:20.0
+f4_mut_add_conn:15.0
+f4_mut_add_neupar:5.0
+f4_mut_add_rep:10.0
+f4_mut_add_simp:50.0
+f4_mut_del:20.0
+f4_mut_mod:30.0
 genkonw0:1
 genkonw1:1
@@ -187,8 +190,8 @@
 genkonw4:1
 randinit:0.01
-nnoise:0
-touchrange:1
-bnoise_struct:0
-bnoise_vel:0
+nnoise:0.0
+touchrange:1.0
+bnoise_struct:0.0
+bnoise_vel:0.0
 ncl_N:1
 ncl_Nu:1
@@ -222,12 +225,12 @@
 ncl_SeeLight2:1
 simil_method:0
-simil_parts:0
-simil_partdeg:1
+simil_parts:0.0
+simil_partdeg:1.0
 simil_neuro:0.5
 symPosSteps:10
 symAlphaSteps:20
 symBetaSteps:20
-minjoint:0
-maxjoint:2
+minjoint:0.0
+maxjoint:2.0
 
 GenePool:
@@ -235,57 +238,57 @@
 fitness:return 0.0+this.velocity*1.0;
 fitfun:0
-fitm:2
-fitma:2
-
-org:
+fitm:2.0
+fitma:2.0
+
+Genotype:
 name:Uwuwit Si
 genotype:X
 info:
 num:1
-gnum:50
-popsiz:4
-lifespan:5000
-velocity:0
-distance:0
-vertvel:0
+gnum:0
+popsiz:6
+lifespan:5000.0
+velocity:0.0
+distance:0.0
+vertvel:0.0
 vertpos:-0.01
-user1:null
-user2:null
-user3:null
-uid:g6501
-
-org:
-name:Igoras Sy
-genotype:X[*]
-info:300.00% mutation of 'Uwuwit Si'
+user1:@Serialized:null
+user2:@Serialized:"2"
+user3:@Serialized:null
+uid:g1
+
+Genotype:
+name:Ezupan Si
+genotype:cX
+info:100.00% mutation of 'Uwuwit Si'
 num:2
-gnum:51
-popsiz:3
-lifespan:5000
-velocity:0
-distance:0
-vertvel:0
+gnum:1
+popsiz:2
+lifespan:5000.0
+velocity:0.0
+distance:0.0
+vertvel:0.0
 vertpos:-0.01
-user1:null
-user2:null
-user3:null
-uid:g6502
-
-org:
-name:Emofuf Sy
-genotype:wX[*]
-info:25.00% mutation of 'Igoras Sy'
+user1:@Serialized:null
+user2:@Serialized:null
+user3:@Serialized:null
+uid:g2
+
+Genotype:
+name:Omygut Sy
+genotype:cX[@]
+info:150.00% mutation of 'Ezupan Si'
 num:3
-gnum:52
-popsiz:3
-lifespan:5000
-velocity:0
-distance:0
-vertvel:0
+gnum:2
+popsiz:1
+lifespan:5000.0
+velocity:0.0
+distance:0.0
+vertvel:0.0
 vertpos:-0.01
-user1:null
-user2:null
-user3:null
-uid:g6503
+user1:@Serialized:null
+user2:@Serialized:null
+user3:@Serialized:null
+uid:g3
 
 Population:
@@ -304,7 +307,7 @@
 bodysim:1
 selfcol:0
-em_stat:0
-em_dyn:0
-en_assim:0
+em_stat:0.0
+em_dyn:0.0
+en_assim:0.0
 
 Population:
@@ -323,6 +326,6 @@
 bodysim:1
 selfcol:0
-em_stat:0
-em_dyn:0
-en_assim:0
-
+em_stat:0.0
+em_dyn:0.0
+en_assim:0.0
+
Index: /java/main/src/test/resources/netfiles/standard_without_orgs.expt
===================================================================
--- /java/main/src/test/resources/netfiles/standard_without_orgs.expt	(revision 107)
+++ /java/main/src/test/resources/netfiles/standard_without_orgs.expt	(revision 107)
@@ -0,0 +1,280 @@
+sim_params:
+expdef:standard
+usercode:
+autosaveperiod:0
+overwrite:1
+filecomm:1
+lastCheckpoint:@Serialized:165
+createrr:1
+creatwarnfail:0
+importchk:0
+loadchk:0
+groupchk:0
+resetonexpdef:1
+user:@Serialized:null
+identity:-1
+initialgen:X
+capacity:200
+MaxCreated:1
+placement:0
+rotation:0
+creath:0.1
+p_nop:20.0
+evalcount:0
+p_mut:64.0
+p_xov:16.0
+xov_mins:0.0
+selrule:2
+delrule:0
+cr_c:0.0
+cr_life:0.0
+cr_v:1.0
+cr_gl:0.0
+cr_joints:0.0
+cr_nnsiz:0.0
+cr_nncon:0.0
+cr_di:0.0
+cr_vpos:0.0
+cr_vvel:0.0
+cr_norm:0
+cr_simi:0
+Energy0:5000.0
+e_meta:1.0
+feed:0
+feede0:200.0
+foodgen:
+feedtrans:1.0
+aging:0
+stagnation:0
+minfitness:0.0
+boostphase:1
+makesound:0
+savebest:0
+log:0
+notes:
+totaltestedcr:165
+totaltests:165
+wrldtyp:0
+wrldsiz:20.0
+wrldmap:
+wrldwat:-1.0
+wrldbnd:0
+wrldg:1.0
+simtype:0
+nnspeed:1.0
+odeshape:0
+odestep:0.05
+odemusclemin:0.0
+odemusclemax:10.0
+odemusclespeed:1.0
+odeairdrag:0.01
+odewaterdrag:0.5
+odewaterbuoy:1.0
+odeseed:0
+odesepsticks:0
+odeworlderp:0.2
+odeworldcfm:1e-05
+odecolmumin:0.1
+odecolmumax:5.0
+odecolbounce:0.1
+odecolbouncevel:0.01
+odecolsoftcfm:0.0
+odecolsofterp:0.0
+odecol2mumin:0.1
+odecol2mumax:1.0
+odecol2bounce:0.1
+odecol2bouncevel:0.01
+odecol2softcfm:0.0
+odecol2softerp:0.0
+gen_hilite:1
+gen_extmutinfo:0
+genoper_f0:0
+genoper_f1:0
+genoper_f2:0
+genoper_f3:0
+genoper_f4:0
+neuadd_N:1
+neuadd_Nu:0
+neuadd_G:1
+neuadd_T:1
+neuadd_S:1
+neuadd_Constant:1
+neuadd_Bend_muscle:1
+neuadd_Rotation_muscle:1
+neuadd_D:0
+neuadd_Fuzzy:0
+neuadd_VEye:0
+neuadd_VMotor:0
+neuadd_Sti:0
+neuadd_LMu:0
+neuadd_Water:0
+neuadd_Energy:0
+neuadd_Ch:0
+neuadd_ChMux:0
+neuadd_ChSel:0
+neuadd_Rnd:0
+neuadd_Sin:0
+neuadd_Delay:0
+neuadd_PIDV:0
+neuadd_Sf:0
+neuadd_Thr:0
+neuadd_Nn:0
+neuadd_SeeLight:0
+neuadd_PIDP:0
+neuadd_Light:0
+neuadd_SeeLight2:0
+f0_nodel_tag:1
+f0_nomod_tag:1
+f0_p_new:5.0
+f0_p_del:5.0
+f0_p_swp:10.0
+f0_p_pos:10.0
+f0_p_mas:10.0
+f0_p_frc:10.0
+f0_p_ing:10.0
+f0_p_asm:10.0
+f0_p_vsiz:0.0
+f0_j_new:5.0
+f0_j_del:5.0
+f0_j_stm:10.0
+f0_j_stf:10.0
+f0_j_rsf:10.0
+f0_j_vred:0.0
+f0_j_vgrn:0.0
+f0_j_vblu:0.0
+f0_n_new:5.0
+f0_n_del:5.0
+f0_n_prp:10.0
+f0_c_new:5.0
+f0_c_del:5.0
+f0_c_wei:10.0
+f1_xo_propor:0
+f1_smX:0.05
+f1_smJunct:0.02
+f1_smComma:0.02
+f1_smModif:0.1
+f1_mut_exmod:EeAaSsDdGgBbHh
+f1_nmNeu:0.05
+f1_nmConn:0.1
+f1_nmProp:0.1
+f1_nmWei:1.0
+f1_nmVal:0.05
+f2_mutAddOper:0.4
+f2_mutJointElem:0.33
+f2_mutNeuroElem:0.33
+f2_mutConnElem:0.33
+f2_mutDelOper:0.1
+f2_mutHandleOper:0.3
+f2_mutPropOper:0.2
+f3_mutSubstitution:0.6
+f3_mutSubstPerChar:0.1
+f3_mutDelIns:0.1
+f3_mutDelInsPerChar:0.05
+f3_mutDelInsLength:5
+f3_mutDuplication:0.05
+f3_mutTranslocation:0.15
+f3_xovGeneTransfer:0.8
+f3_xovCrossingOver:0.2
+f4_mut_add:50.0
+f4_mut_add_div:20.0
+f4_mut_add_conn:15.0
+f4_mut_add_neupar:5.0
+f4_mut_add_rep:10.0
+f4_mut_add_simp:50.0
+f4_mut_del:20.0
+f4_mut_mod:30.0
+genkonw0:1
+genkonw1:1
+genkonw2:1
+genkonw3:1
+genkonw4:1
+randinit:0.01
+nnoise:0.0
+touchrange:1.0
+bnoise_struct:0.0
+bnoise_vel:0.0
+ncl_N:1
+ncl_Nu:1
+ncl_G:1
+ncl_T:1
+ncl_S:1
+ncl_Constant:1
+ncl_Bend_muscle:1
+ncl_Rotation_muscle:1
+ncl_D:1
+ncl_Fuzzy:1
+ncl_VEye:1
+ncl_VMotor:1
+ncl_Sti:1
+ncl_LMu:1
+ncl_Water:1
+ncl_Energy:1
+ncl_Ch:1
+ncl_ChMux:1
+ncl_ChSel:1
+ncl_Rnd:1
+ncl_Sin:1
+ncl_Delay:1
+ncl_PIDV:1
+ncl_Sf:1
+ncl_Thr:1
+ncl_Nn:1
+ncl_SeeLight:1
+ncl_PIDP:1
+ncl_Light:1
+ncl_SeeLight2:1
+simil_method:0
+simil_parts:0.0
+simil_partdeg:1.0
+simil_neuro:0.5
+symPosSteps:10
+symAlphaSteps:20
+symBetaSteps:20
+minjoint:0.0
+maxjoint:2.0
+
+GenePool:
+name:Genotypes
+fitness:return 0.0+this.velocity*1.0;
+fitfun:0
+fitm:2.0
+fitma:2.0
+
+Population:
+name:Creatures
+energy:1
+death:1
+nnsim:2
+perfperiod:100
+stabilperiod:100
+killnostable:1000000
+stabledist:0.01
+enableperf:2
+colmask:13
+selfmask:65537
+othermask:131073
+bodysim:1
+selfcol:0
+em_stat:0.0
+em_dyn:0.0
+en_assim:0.0
+
+Population:
+name:Food
+energy:1
+death:1
+nnsim:0
+perfperiod:100
+stabilperiod:100
+killnostable:1000000
+stabledist:0.01
+enableperf:0
+colmask:148
+selfmask:131074
+othermask:65538
+bodysim:1
+selfcol:0
+em_stat:0.0
+em_dyn:0.0
+en_assim:0.0
+
