[Avida-SVN] r1589 - in branches/collect: . Avida.xcodeproj source/actions source/classification source/cpu source/main source/targets source/targets/avida source/targets/avida-viewer support/config tests

blwalker at myxo.css.msu.edu blwalker at myxo.css.msu.edu
Tue May 22 09:50:55 PDT 2007


Author: blwalker
Date: 2007-05-22 12:50:55 -0400 (Tue, 22 May 2007)
New Revision: 1589

Added:
   branches/collect/source/targets/unit-tests/
   branches/collect/tests/_avida_GA_lim_res/
   branches/collect/tests/_task_optimize_lim_res/
   branches/collect/tests/string_match_embed3/
Modified:
   branches/collect/Avida.vcproj
   branches/collect/Avida.xcodeproj/project.pbxproj
   branches/collect/CMakeLists.txt
   branches/collect/source/actions/PopulationActions.cc
   branches/collect/source/actions/PrintActions.cc
   branches/collect/source/classification/cClassificationManager.cc
   branches/collect/source/classification/cClassificationManager.h
   branches/collect/source/classification/cLineage.cc
   branches/collect/source/classification/cLineage.h
   branches/collect/source/cpu/cCPUMemory.h
   branches/collect/source/cpu/cHardwareGX.cc
   branches/collect/source/cpu/cHardwareGX.h
   branches/collect/source/main/cAvidaConfig.h
   branches/collect/source/main/cEnvironment.cc
   branches/collect/source/main/cMutationRates.h
   branches/collect/source/main/cOrganism.h
   branches/collect/source/main/cPhenotype.cc
   branches/collect/source/main/cPhenotype.h
   branches/collect/source/main/cPopulation.cc
   branches/collect/source/main/cPopulation.h
   branches/collect/source/main/cReactionResult.cc
   branches/collect/source/main/cReactionResult.h
   branches/collect/source/main/cTaskContext.h
   branches/collect/source/main/cTaskLib.cc
   branches/collect/source/main/cWorld.cc
   branches/collect/source/targets/avida-viewer/viewer.cc
   branches/collect/source/targets/avida/primitive.cc
   branches/collect/support/config/avida.cfg
   branches/collect/support/config/default-gx.org
Log:

Ported r1524:1587 from development.  Resolved some purely textual conflicts involving cclade and task_value; I don't know why they didn't merge cleanly in the first place.



Modified: branches/collect/Avida.vcproj
===================================================================
--- branches/collect/Avida.vcproj	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/Avida.vcproj	2007-05-22 16:50:55 UTC (rev 1589)
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="UTF-8"?>
+<?xml version="1.0" encoding="Windows-1252"?>
 <VisualStudioProject
 	ProjectType="Visual C++"
 	Version="8.00"
@@ -39,7 +39,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="&quot;$(ProjectDir)source\tools&quot;;&quot;$(ProjectDir)source\targets\avida-viewer&quot;;&quot;$(ProjectDir)source\platform\msvc2005&quot;;&quot;$(ProjectDir)source\platform\msvc2005\pdcurses&quot;;&quot;$(ProjectDir)source\main&quot;;&quot;$(ProjectDir)source\drivers&quot;;&quot;$(ProjectDir)source\cpu&quot;;&quot;$(ProjectDir)source\classification&quot;;&quot;$(ProjectDir)source\analyze&quot;;&quot;$(ProjectDir)source\actions&quot;;&quot;$(ProjectDir)source&quot;"
+				AdditionalIncludeDirectories="&quot;$(ProjectDir)source\tools&quot;;&quot;$(ProjectDir)source\targets\avida-viewer&quot;;&quot;$(ProjectDir)source\platform\msvc2005&quot;;&quot;$(ProjectDir)source\platform\msvc2005\pdcurses&quot;;&quot;$(ProjectDir)source\main&quot;;&quot;$(ProjectDir)source\drivers&quot;;&quot;$(ProjectDir)source\cpu&quot;;&quot;$(ProjectDir)source\classification&quot;;&quot;$(ProjectDir)source\analyze&quot;;&quot;$(ProjectDir)source\actions&quot;;&quot;$(ProjectDir)source&quot;;&quot;$(ProjectDir)source\platform&quot;"
 				PreprocessorDefinitions="NOMACROS;DEBUG;WIN32;_WIN32"
 				MinimalRebuild="true"
 				BasicRuntimeChecks="3"
@@ -121,7 +121,7 @@
 				FavorSizeOrSpeed="1"
 				OmitFramePointers="true"
 				WholeProgramOptimization="true"
-				AdditionalIncludeDirectories="&quot;$(ProjectDir)source\tools&quot;;&quot;$(ProjectDir)source\targets\avida-viewer&quot;;&quot;$(ProjectDir)source\platform\msvc2005&quot;;&quot;$(ProjectDir)source\platform\msvc2005\pdcurses&quot;;&quot;$(ProjectDir)source\main&quot;;&quot;$(ProjectDir)source\drivers&quot;;&quot;$(ProjectDir)source\cpu&quot;;&quot;$(ProjectDir)source\classification&quot;;&quot;$(ProjectDir)source\analyze&quot;;&quot;$(ProjectDir)source\actions&quot;;&quot;$(ProjectDir)source&quot;"
+				AdditionalIncludeDirectories="&quot;$(ProjectDir)source\tools&quot;;&quot;$(ProjectDir)source\targets\avida-viewer&quot;;&quot;$(ProjectDir)source\platform\msvc2005&quot;;&quot;$(ProjectDir)source\platform\msvc2005\pdcurses&quot;;&quot;$(ProjectDir)source\main&quot;;&quot;$(ProjectDir)source\drivers&quot;;&quot;$(ProjectDir)source\cpu&quot;;&quot;$(ProjectDir)source\classification&quot;;&quot;$(ProjectDir)source\analyze&quot;;&quot;$(ProjectDir)source\actions&quot;;&quot;$(ProjectDir)source&quot;;&quot;$(ProjectDir)source\platform&quot;"
 				PreprocessorDefinitions="NOMACROS;NDEBUG;WIN32;_WIN32"
 				ExceptionHandling="1"
 				RuntimeLibrary="0"
@@ -449,6 +449,14 @@
 				>
 			</File>
 			<File
+				RelativePath=".\source\cpu\cHardwareGX.cc"
+				>
+			</File>
+			<File
+				RelativePath=".\source\cpu\cHardwareGX.h"
+				>
+			</File>
+			<File
 				RelativePath=".\source\cpu\cHardwareManager.h"
 				>
 			</File>
@@ -869,6 +877,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\source\platform\FloatingPoint.h"
+				>
+			</File>
+			<File
 				RelativePath=".\source\tools\functions.h"
 				>
 			</File>

Modified: branches/collect/Avida.xcodeproj/project.pbxproj
===================================================================
--- branches/collect/Avida.xcodeproj/project.pbxproj	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/Avida.xcodeproj/project.pbxproj	2007-05-22 16:50:55 UTC (rev 1589)
@@ -97,6 +97,7 @@
 		706C6FFF0B83F265003174C1 /* cInstSet.cc in Sources */ = {isa = PBXBuildFile; fileRef = 706C6FFE0B83F265003174C1 /* cInstSet.cc */; };
 		706C70000B83F265003174C1 /* cInstSet.cc in Sources */ = {isa = PBXBuildFile; fileRef = 706C6FFE0B83F265003174C1 /* cInstSet.cc */; };
 		706C70010B83F265003174C1 /* cInstSet.cc in Sources */ = {isa = PBXBuildFile; fileRef = 706C6FFE0B83F265003174C1 /* cInstSet.cc */; };
+		707045F00BCEA0D9000F9B9A /* cHardwareGX.cc in Sources */ = {isa = PBXBuildFile; fileRef = 423335880BC067E3000DF681 /* cHardwareGX.cc */; };
 		7073165D097C6C8F00815164 /* cParser.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7073165B097C6C8F00815164 /* cParser.cc */; };
 		70731665097C6DF500815164 /* cASLibrary.cc in Sources */ = {isa = PBXBuildFile; fileRef = 70731663097C6DF500815164 /* cASLibrary.cc */; };
 		7073166B097C6E0C00815164 /* cASSymbol.cc in Sources */ = {isa = PBXBuildFile; fileRef = 70731669097C6E0C00815164 /* cASSymbol.cc */; };
@@ -216,6 +217,8 @@
 		70B1A6520B7E237F00067486 /* cHardwareExperimental.cc in Sources */ = {isa = PBXBuildFile; fileRef = 70B1A64F0B7E237F00067486 /* cHardwareExperimental.cc */; };
 		70B1A7430B7E3FFD00067486 /* instset-experimental.cfg in CopyFiles */ = {isa = PBXBuildFile; fileRef = 70B1A7420B7E3FFD00067486 /* instset-experimental.cfg */; };
 		70B1A75A0B7E431F00067486 /* experimental.org in CopyFiles */ = {isa = PBXBuildFile; fileRef = 70B1A7590B7E431F00067486 /* experimental.org */; };
+		70B6514F0BEA6FCC002472ED /* main.cc in Sources */ = {isa = PBXBuildFile; fileRef = 701EF27E0BEA5D2300DAE168 /* main.cc */; };
+		70B651B70BEA9AEC002472ED /* unit-tests in CopyFiles */ = {isa = PBXBuildFile; fileRef = 70B6514C0BEA6FAD002472ED /* unit-tests */; };
 		70BCB22E0AB7B23D003FF331 /* cArgContainer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 70BCB21C0AB7ADA6003FF331 /* cArgContainer.cc */; };
 		70BCB2350AB7B26B003FF331 /* cArgContainer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 70BCB21C0AB7ADA6003FF331 /* cArgContainer.cc */; };
 		70C054ED0A4F6FD2002703C1 /* PopulationActions.cc in Sources */ = {isa = PBXBuildFile; fileRef = 70C054C90A4F6E19002703C1 /* PopulationActions.cc */; };
@@ -427,6 +430,16 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		70B651B50BEA9AC2002472ED /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = work;
+			dstSubfolderSpec = 16;
+			files = (
+				70B651B70BEA9AEC002472ED /* unit-tests in CopyFiles */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		70DCAD08097AF7CC002F8733 /* CopyFiles */ = {
 			isa = PBXCopyFilesBuildPhase;
 			buildActionMask = 2147483647;
@@ -472,6 +485,7 @@
 		701D9382094CBA69008B845F /* cDriverManager.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cDriverManager.cc; sourceTree = "<group>"; };
 		701D93E6094CBF71008B845F /* cDefaultAnalyzeDriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cDefaultAnalyzeDriver.h; sourceTree = "<group>"; };
 		701D93E7094CBF71008B845F /* cDefaultAnalyzeDriver.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cDefaultAnalyzeDriver.cc; sourceTree = "<group>"; };
+		701EF27E0BEA5D2300DAE168 /* main.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = main.cc; sourceTree = "<group>"; };
 		7027621909D73E5900741717 /* cOrgSourceMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cOrgSourceMessage.h; sourceTree = "<group>"; };
 		7027621A09D73E7700741717 /* cOrgSinkMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cOrgSinkMessage.h; sourceTree = "<group>"; };
 		702D4EF508DA5328007BA469 /* cEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cEnvironment.h; sourceTree = "<group>"; };
@@ -600,6 +614,7 @@
 		707CE51D0A9E49A50022D19C /* config.html */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.html.documentation; path = config.html; sourceTree = "<group>"; };
 		707CE7490AA333060022D19C /* actions.html */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.html.documentation; path = actions.html; sourceTree = "<group>"; };
 		707CE7500AA334120022D19C /* analyze.html */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.html.documentation; path = analyze.html; sourceTree = "<group>"; };
+		707D71280C00B9B300DD4D49 /* FloatingPoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FloatingPoint.h; sourceTree = "<group>"; };
 		708051A70A1F65FE00CBB8B6 /* SaveLoadActions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SaveLoadActions.h; sourceTree = "<group>"; };
 		708051A80A1F65FE00CBB8B6 /* SaveLoadActions.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SaveLoadActions.cc; sourceTree = "<group>"; };
 		708051BA0A1F66B400CBB8B6 /* cActionLibrary.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cActionLibrary.cc; sourceTree = "<group>"; };
@@ -787,6 +802,7 @@
 		70B1A7420B7E3FFD00067486 /* instset-experimental.cfg */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = "instset-experimental.cfg"; sourceTree = "<group>"; };
 		70B1A7590B7E431F00067486 /* experimental.org */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = experimental.org; sourceTree = "<group>"; };
 		70B3984E0947B29D0018F09D /* tManagedPointerArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tManagedPointerArray.h; sourceTree = "<group>"; };
+		70B6514C0BEA6FAD002472ED /* unit-tests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "unit-tests"; sourceTree = BUILT_PRODUCTS_DIR; };
 		70BCB21B0AB7ADA6003FF331 /* cArgContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cArgContainer.h; sourceTree = "<group>"; };
 		70BCB21C0AB7ADA6003FF331 /* cArgContainer.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cArgContainer.cc; sourceTree = "<group>"; };
 		70BCB2470AB7B634003FF331 /* cArgSchema.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cArgSchema.h; sourceTree = "<group>"; };
@@ -910,7 +926,7 @@
 		DCC315CE076253A5008F7A48 /* environment.rotate */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = environment.rotate; sourceTree = "<group>"; };
 		DCC315D0076253A5008F7A48 /* task_event_gen.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = task_event_gen.cc; sourceTree = "<group>"; };
 		DCC315D1076253A5008F7A48 /* task_event_gen.old.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = task_event_gen.old.cc; sourceTree = "<group>"; };
-		DCC3164D07626CF3008F7A48 /* avida */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "compiled.mach-o.executable"; path = avida; sourceTree = BUILT_PRODUCTS_DIR; };
+		DCC3164D07626CF3008F7A48 /* avida */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = avida; sourceTree = BUILT_PRODUCTS_DIR; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -929,6 +945,13 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		70B6514A0BEA6FAD002472ED /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		70DCAD07097AF7CC002F8733 /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
@@ -965,6 +988,14 @@
 			path = drivers;
 			sourceTree = "<group>";
 		};
+		701EF27D0BEA5D2300DAE168 /* unit-tests */ = {
+			isa = PBXGroup;
+			children = (
+				701EF27E0BEA5D2300DAE168 /* main.cc */,
+			);
+			path = "unit-tests";
+			sourceTree = "<group>";
+		};
 		70422A1B091B141000A5E67F /* analyze */ = {
 			isa = PBXGroup;
 			children = (
@@ -1131,6 +1162,7 @@
 				70DCAC55097AF730002F8733 /* avida */,
 				70DCAC56097AF730002F8733 /* avida-s */,
 				70DCAC58097AF730002F8733 /* avida-viewer */,
+				701EF27D0BEA5D2300DAE168 /* unit-tests */,
 				703CA3710A50734500AB4DB4 /* SConscript */,
 			);
 			path = targets;
@@ -1226,8 +1258,9 @@
 		70DCF4FF09CF81E400924128 /* platform */ = {
 			isa = PBXGroup;
 			children = (
+				70DCF50009CF823500924128 /* tcmalloc */,
 				703CA3700A5072E600AB4DB4 /* SConscript */,
-				70DCF50009CF823500924128 /* tcmalloc */,
+				707D71280C00B9B300DD4D49 /* FloatingPoint.h */,
 			);
 			path = platform;
 			sourceTree = "<group>";
@@ -1616,6 +1649,7 @@
 				700E2B83085DE50C00CF158A /* avida-viewer */,
 				70DCAD1C097AF7CC002F8733 /* avida-s */,
 				70AA941909D486AE006A24C8 /* libtcmalloc.a */,
+				70B6514C0BEA6FAD002472ED /* unit-tests */,
 			);
 			name = Products;
 			sourceTree = "<group>";
@@ -1668,6 +1702,23 @@
 			productReference = 70AA941909D486AE006A24C8 /* libtcmalloc.a */;
 			productType = "com.apple.product-type.library.static";
 		};
+		70B6514B0BEA6FAD002472ED /* unit-tests */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 70B651570BEA700B002472ED /* Build configuration list for PBXNativeTarget "unit-tests" */;
+			buildPhases = (
+				70B651490BEA6FAD002472ED /* Sources */,
+				70B6514A0BEA6FAD002472ED /* Frameworks */,
+				70B651B50BEA9AC2002472ED /* CopyFiles */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "unit-tests";
+			productName = "unit-tests";
+			productReference = 70B6514C0BEA6FAD002472ED /* unit-tests */;
+			productType = "com.apple.product-type.tool";
+		};
 		70DCAC9D097AF7CC002F8733 /* avida-s */ = {
 			isa = PBXNativeTarget;
 			buildConfigurationList = 70DCAD17097AF7CC002F8733 /* Build configuration list for PBXNativeTarget "avida-s" */;
@@ -1721,6 +1772,7 @@
 				70DCAC9D097AF7CC002F8733 /* avida-s */,
 				700E2AF3085DE50C00CF158A /* avida-viewer */,
 				70AA941809D486AE006A24C8 /* tcmalloc */,
+				70B6514B0BEA6FAD002472ED /* unit-tests */,
 			);
 		};
 /* End PBXProject section */
@@ -1894,6 +1946,7 @@
 				7099EF580B2FBC86001269F6 /* cTextViewerDriver_Base.cc in Sources */,
 				70B1A6520B7E237F00067486 /* cHardwareExperimental.cc in Sources */,
 				706C70010B83F265003174C1 /* cInstSet.cc in Sources */,
+				707045F00BCEA0D9000F9B9A /* cHardwareGX.cc in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1907,6 +1960,14 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		70B651490BEA6FAD002472ED /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				70B6514F0BEA6FCC002472ED /* main.cc in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		70DCAC9F097AF7CC002F8733 /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
@@ -2428,6 +2489,70 @@
 			};
 			name = Profile;
 		};
+		70B651580BEA700B002472ED /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				INSTALL_PATH = "$(HOME)/bin";
+				PREBINDING = NO;
+				PRODUCT_NAME = "unit-tests";
+				ZERO_LINK = YES;
+			};
+			name = Development;
+		};
+		70B651590BEA700B002472ED /* Deployment-G4 */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_MODEL_TUNING = G5;
+				INSTALL_PATH = "$(HOME)/bin";
+				PREBINDING = NO;
+				PRODUCT_NAME = "unit-tests";
+				ZERO_LINK = YES;
+			};
+			name = "Deployment-G4";
+		};
+		70B6515A0BEA700B002472ED /* Deployment-G5 */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_MODEL_TUNING = G5;
+				INSTALL_PATH = "$(HOME)/bin";
+				PREBINDING = NO;
+				PRODUCT_NAME = "unit-tests";
+				ZERO_LINK = YES;
+			};
+			name = "Deployment-G5";
+		};
+		70B6515B0BEA700B002472ED /* Deployment-Universal */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_MODEL_TUNING = G5;
+				INSTALL_PATH = "$(HOME)/bin";
+				PREBINDING = NO;
+				PRODUCT_NAME = "unit-tests";
+				ZERO_LINK = YES;
+			};
+			name = "Deployment-Universal";
+		};
+		70B6515C0BEA700B002472ED /* Profile */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_MODEL_TUNING = G5;
+				INSTALL_PATH = "$(HOME)/bin";
+				PREBINDING = NO;
+				PRODUCT_NAME = "unit-tests";
+				ZERO_LINK = YES;
+			};
+			name = Profile;
+		};
 		70DCAD18097AF7CC002F8733 /* Development */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
@@ -2595,6 +2720,18 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = "Deployment-G4";
 		};
+		70B651570BEA700B002472ED /* Build configuration list for PBXNativeTarget "unit-tests" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				70B651580BEA700B002472ED /* Development */,
+				70B651590BEA700B002472ED /* Deployment-G4 */,
+				70B6515A0BEA700B002472ED /* Deployment-G5 */,
+				70B6515B0BEA700B002472ED /* Deployment-Universal */,
+				70B6515C0BEA700B002472ED /* Profile */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = "Deployment-G4";
+		};
 		70DCAD17097AF7CC002F8733 /* Build configuration list for PBXNativeTarget "avida-s" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (

Modified: branches/collect/CMakeLists.txt
===================================================================
--- branches/collect/CMakeLists.txt	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/CMakeLists.txt	2007-05-22 16:50:55 UTC (rev 1589)
@@ -30,8 +30,13 @@
 # This section defines default builtin compiler options
 # ------------------------------------------------------------------------------
 IF(UNIX)
-  SET(COMPILER_WARNING_FLAGS "-Wextra -Wno-unknown-pragmas -Wconversion -Wno-trigraphs")
-  SET(COMPILER_OPTIMIZATION_FLAGS "-ffast-math -fno-rtti -funroll-loops -fstrict-aliasing -ftree-vectorize -fvisibility-inlines-hidden")
+  IF (CMAKE_CXX_COMPILER MATCHES ".*pathCC.*")
+    SET(COMPILER_WARNING_FLAGS "")
+    SET(COMPILER_OPTIMIZATION_FLAGS "-ffast-math -fno-rtti -funroll-loops -fstrict-aliasing -OPT:Olimit=0")
+  ELSE (CMAKE_CXX_COMPILER MATCHES ".*pathCC.*")
+    SET(COMPILER_WARNING_FLAGS "-Wextra -Wno-unknown-pragmas -Wconversion -Wno-trigraphs")
+    SET(COMPILER_OPTIMIZATION_FLAGS "-ffast-math -fno-rtti -funroll-loops -fstrict-aliasing -ftree-vectorize -fvisibility-inlines-hidden")
+  ENDIF (CMAKE_CXX_COMPILER MATCHES ".*pathCC.*")
 
   # Four types of c++ compilations:
   # - debug (Debug)
@@ -205,6 +210,11 @@
 LIST(APPEND ALL_INC_DIRS ${MAIN_DIR})
 
 
+# The platform directory
+SET(PLATFORM_DIR ${PROJECT_SOURCE_DIR}/source/platform)
+LIST(APPEND ALL_INC_DIRS ${PLATFORM_DIR})
+
+
 # The tools directory
 SET(TOOLS_DIR ${PROJECT_SOURCE_DIR}/source/tools)
 SET(TOOLS_SOURCES
@@ -379,7 +389,20 @@
 ENDIF(AVD_TASK_EVENT_GEN)
 
 
+OPTION(AVD_UNIT_TESTS
+  "Enable the unit-tests executable.  Running this target will test various low level functionality."
+  OFF
+)
+IF(AVD_UNIT_TESTS)
+  SET(UNIT_TESTS_DIR source/targets/unit-tests)
+  SET(UNIT_TESTS_SOURCES
+    ${UNIT_TESTS_DIR}/main.cc
+  )
+  ADD_EXECUTABLE(unit-tests ${UNIT_TESTS_SOURCES})
+  INSTALL_TARGETS(/work unit-tests)
+ENDIF(AVD_UNIT_TESTS)
 
+
 # Default Configuration Files
 # - Installed into the work directory alongside selected targets
 # ------------------------------------------------------------------------------
@@ -455,20 +478,20 @@
 
 # By default, compile all unit tests of primitive Avida classes.  Tests
 # are run via 'make test' under unix.
-OPTION(AVD_UNIT_TESTS
+OPTION(AVD_CMAKE_UNIT_TESTS
   "Enable building primitive unit test suites."
   OFF
 )
-IF(AVD_UNIT_TESTS)
+IF(AVD_CMAKE_UNIT_TESTS)
   SET(UNIT_TESTS TRUE)
   INCLUDE (${CMAKE_ROOT}/Modules/Dart.cmake)
   ADD_DEFINITIONS(-DENABLE_UNIT_TESTS)
   ADD_DEFINITIONS(-DUSE_tMemTrack=1)
   ENABLE_TESTING()
-ELSE(AVD_UNIT_TESTS)
+ELSE(AVD_CMAKE_UNIT_TESTS)
   REMOVE_DEFINITIONS(-DENABLE_UNIT_TESTS)
   REMOVE_DEFINITIONS(-DUSE_tMemTrack=1)
-ENDIF(AVD_UNIT_TESTS)
+ENDIF(AVD_CMAKE_UNIT_TESTS)
 
 
 IF(BUILD_AvidaSupportLibs)

Modified: branches/collect/source/actions/PopulationActions.cc
===================================================================
--- branches/collect/source/actions/PopulationActions.cc	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/source/actions/PopulationActions.cc	2007-05-22 16:50:55 UTC (rev 1589)
@@ -34,6 +34,7 @@
 #include "cPopulationCell.h"
 #include "cStats.h"
 #include "cWorld.h"
+#include "cOrganism.h"
 
 
 /*
@@ -542,13 +543,9 @@
 {
 private:
 public:
-  cActionToggleRewardInstruction(cWorld* world, const cString& args) : cAction(world, args) 
-  {
-    //pass
-    //@JMC: m_killprob (and other code) is a meme that hitchiked when I used gabe's event as an example. need to clean it up. 
-  }
+  cActionToggleRewardInstruction(cWorld* world, const cString& args) : cAction(world, args) {}
   
-  static const cString GetDescription() { return "Arguments: [double probability=0.9]"; }
+  static const cString GetDescription() { return "No Arguments"; }
   
   void Process(cAvidaContext& ctx)
   {
@@ -570,19 +567,14 @@
 {
 private:
 public:
-  cActionToggleFitnessValley(cWorld* world, const cString& args) : cAction(world, args) 
-  {
-    //pass
-    //@JMC: m_killprob (and other code) is a meme that hitchiked when I used gabe's event as an example. need to clean it up. 
-  }
+  cActionToggleFitnessValley(cWorld* world, const cString& args) : cAction(world, args) {}
   
-  static const cString GetDescription() { return "Arguments: [double probability=0.9]"; }
+  static const cString GetDescription() { return "No Arguments"; }
   
   void Process(cAvidaContext& ctx)
   {
     if(m_world->GetConfig().FITNESS_VALLEY.Get()) {m_world->GetConfig().FITNESS_VALLEY.Set(0);}
     else{m_world->GetConfig().FITNESS_VALLEY.Set(1);}
-//    m_world->GetConfig().FITNESS_VALLEY.Set(-1* m_world->GetConfig().FITNESS_VALLEY.Get());
   }
 };
 
@@ -1439,7 +1431,7 @@
   void Process(cAvidaContext& ctx)
   {
     for (int i = 0; i < m_world->GetPopulation().GetSize(); i++) {
-      m_world->GetPopulation().GetCell(i).GetOrganism();
+      (m_world->GetPopulation().GetCell(i).GetOrganism())->GetPhenotype();
     }
   }
 };

Modified: branches/collect/source/actions/PrintActions.cc
===================================================================
--- branches/collect/source/actions/PrintActions.cc	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/source/actions/PrintActions.cc	2007-05-22 16:50:55 UTC (rev 1589)
@@ -687,6 +687,92 @@
 
 
 /*
+ This function requires that TRACK_CCLADES be enabled and avida is
+ not in analyze mode.
+ 
+ Parameters
+	filename (cString)
+ Where the clade information should be stored.
+ 
+ Please note the structure to this file is not a matrix.
+ Each line is formatted as follows: 
+ update number_cclades ccladeID0 ccladeID0_count ccladeID1 
+ 
+ @MRR May 2007
+ */
+class cActionPrintCCladeCounts : public cAction
+{
+private:
+		cString filename;
+		bool first_time;
+		
+public:
+			cActionPrintCCladeCounts(cWorld* world, const cString& args)
+			: cAction(world, args)
+		{
+				cString largs(args);
+				filename = (!largs.GetSize()) ? "cclade_count.dat" : largs.PopWord();
+				first_time = true;
+		}
+		
+		static const cString GetDescription() { return "Arguments: [filename = \"cclade_count.dat\"]"; }
+		
+		void Process(cAvidaContext& ctx)
+		{
+			//Handle possible errors
+			if (ctx.GetAnalyzeMode())
+				m_world->GetDriver().RaiseFatalException(1, "PrintCCladeCount requires avida to be in run mode.");
+			
+			if (m_world->GetConfig().TRACK_CCLADES.Get() == 0)
+				m_world->GetDriver().RaiseFatalException(1, "PrintCCladeCount requires coalescence clade tracking to be enabled.");
+			
+			
+			tHashTable<int, int> cclade_count;  //A count for each clade in the population
+			set<int>             clade_ids;
+			
+			cPopulation& pop = m_world->GetPopulation();
+			const int update = m_world->GetStats().GetUpdate();
+			
+			//For each organism in the population, find what coalescence clade it belongs to and count
+			for (int k = 0; k < pop.GetSize(); k++)
+			{
+				if (!pop.GetCell(k).IsOccupied())
+					continue;
+				int cclade_id = pop.GetCell(k).GetOrganism()->GetCCladeLabel();
+				int count = 0;
+				if (!cclade_count.Find(cclade_id,count))
+					clade_ids.insert(cclade_id);
+				cclade_count.SetValue(cclade_id, ++count);
+			}
+			
+			ofstream& fp = m_world->GetDataFileManager().GetOFStream(filename);
+			if (!fp.is_open())
+				m_world->GetDriver().RaiseFatalException(1, "PrintCCladeCount: Unable to open output file.");
+			if (first_time)
+			{
+				fp << "# Each line is formatted as follows:" << endl;
+				fp << "#   update number_cclades ccladeID0 ccladeID0_count ccladeID1" << endl;
+				fp << endl;
+				first_time = false;
+			}
+			fp << update <<  " "
+				<< clade_ids.size() << " ";
+			
+			set<int>::iterator sit = clade_ids.begin();
+			while(sit != clade_ids.end())
+			{
+				int count = 0;
+				cclade_count.Find(*sit, count);
+				fp << *sit << " " << count << " ";
+				sit++;
+			}
+			fp << endl;
+			
+		}
+};
+
+
+/*
  @MRR March 2007
  This function prints out fitness data. The main point is that it
  calculates the average fitness from info from the testCPU + the actual
@@ -1812,6 +1898,8 @@
   action_lib->Register<cActionPrintPhenotypeData>("PrintPhenotypeData");
   action_lib->Register<cActionPrintPhenotypeStatus>("PrintPhenotypeStatus");
   action_lib->Register<cActionPrintDemeStats>("PrintDemeStats");
+	action_lib->Register<cActionPrintCCladeCounts>("PrintCCladeCounts");
+
   
   // Processed Data
   action_lib->Register<cActionPrintData>("PrintData");

Modified: branches/collect/source/classification/cClassificationManager.cc
===================================================================
--- branches/collect/source/classification/cClassificationManager.cc	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/source/classification/cClassificationManager.cc	2007-05-22 16:50:55 UTC (rev 1589)
@@ -1260,7 +1260,29 @@
   fp << endl;
 }
 
+//@MRR Coalescence Clades
+void cClassificationManager::LoadCCladeFounders(const cString& filename)
+{
+	ifstream fin(filename);
+	if (!fin.is_open())
+		m_world->GetDriver().RaiseFatalException(1, "Unable to open coalescence clade ids.");
+	int id;
+	fin >> id;
+	while(!fin.eof())
+	{
+		m_cclade_ids.insert(id);
+		fin >> id;
+	}
+	fin.close();
+}
 
+bool cClassificationManager::IsCCladeFounder(const int id) const
+{
+	set<int>::const_iterator it = m_cclade_ids.find(id);
+	return (it == m_cclade_ids.end()) ? false : true;
+}
+
+
 unsigned int cClassificationManager::FindCRC(const cGenome & in_genome) const
 {
   unsigned int total = 0;

Modified: branches/collect/source/classification/cClassificationManager.h
===================================================================
--- branches/collect/source/classification/cClassificationManager.h	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/source/classification/cClassificationManager.h	2007-05-22 16:50:55 UTC (rev 1589)
@@ -27,6 +27,7 @@
 #define cClassificationManager_h
 
 #include <list>
+#include <set>
 
 #ifndef defs_h
 #include "defs.h"
@@ -96,6 +97,9 @@
   cLineage* m_max_fitness_lineage; // lineage with the single highest fitness
   cLineage* m_dominant_lineage; // the lineage with the largest number of creatures.
   int m_lineage_next_id;
+	
+	// CClade @MRR
+	std::set<int>  m_cclade_ids;
   
   
   // Private Helper Functions
@@ -206,7 +210,10 @@
   void PrintLineageTotals(const cString& filename, bool verbose=false);
   void PrintLineageCurCounts(const cString& filename);
   
-
+	// Coalescence Clade
+	void LoadCCladeFounders(const cString& filename);
+	bool IsCCladeFounder(const int id) const;
+	
   // Utility Functions
   bool SaveClone(std::ofstream& fp);
   bool LoadClone(std::ifstream & fp);

Modified: branches/collect/source/classification/cLineage.cc
===================================================================
--- branches/collect/source/classification/cLineage.cc	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/source/classification/cLineage.cc	2007-05-22 16:50:55 UTC (rev 1589)
@@ -150,3 +150,11 @@
 }
 
 
+tArray<const cGenotype*> cLineage::GetCurrentGenotypes(cAvidaContext& ctx) const
+{
+	tArray<const cGenotype*> genotypes;
+	map<const cGenotype*, int, gt_gentype>::const_iterator it = m_genotype_map.begin();
+	for(; it != m_genotype_map.end(); it++)
+		genotypes.Push(it->first);
+	return genotypes;
+}

Modified: branches/collect/source/classification/cLineage.h
===================================================================
--- branches/collect/source/classification/cLineage.h	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/source/classification/cLineage.h	2007-05-22 16:50:55 UTC (rev 1589)
@@ -27,6 +27,7 @@
 #define cLineage_h
 
 #include <map>
+#include "tArray.h"
 
 class cAvidaContext;
 class cGenotype;
@@ -150,6 +151,8 @@
    * the creation of this lineage
    **/
   double GetLineageStat2 () const { return m_lineage_stat2; }
+	
+	tArray<const cGenotype*> GetCurrentGenotypes(cAvidaContext& ctx) const;
 };
 
 

Modified: branches/collect/source/cpu/cCPUMemory.h
===================================================================
--- branches/collect/source/cpu/cCPUMemory.h	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/source/cpu/cCPUMemory.h	2007-05-22 16:50:55 UTC (rev 1589)
@@ -60,7 +60,7 @@
   cCPUMemory(const cGenome& in_genome) : cGenome(in_genome), flag_array(in_genome.GetSize()) { ; }
   cCPUMemory(const cString& in_string) : cGenome(in_string), flag_array(in_string.GetSize()) { ; }
   //! Construct a cCPUMemory object from a cInstruction range.
-  cCPUMemory(cInstruction* begin, cInstruction* end) : cGenome(begin, end), flag_array(GetSize()) { }
+  cCPUMemory(cInstruction* begin, cInstruction* end) : cGenome(begin, end), flag_array(GetSize()) { ClearFlags(); }
   ~cCPUMemory() { ; }
 
   void operator=(const cCPUMemory& other_memory);
@@ -103,6 +103,8 @@
 	void ClearFlagCopyMut(int pos)    { flag_array[pos] &= ~MASK_COPYMUT;  }
   void ClearFlagInjected(int pos)   { flag_array[pos] &= ~MASK_INJECTED; }
     
+  void Append(const cInstruction& in_inst) { Insert(GetSize(), in_inst); }
+  void Append(const cGenome& in_genome) { Insert(GetSize(), in_genome); }
   void Insert(int pos, const cInstruction& in_inst);
   void Insert(int pos, const cGenome& in_genome);
   void Remove(int pos, int num_insts=1);

Modified: branches/collect/source/cpu/cHardwareGX.cc
===================================================================
--- branches/collect/source/cpu/cHardwareGX.cc	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/source/cpu/cHardwareGX.cc	2007-05-22 16:50:55 UTC (rev 1589)
@@ -21,6 +21,7 @@
  */
 #include <climits>
 #include <fstream>
+#include <algorithm>
 #include "cHardwareGX.h"
 #include "cAvidaContext.h"
 #include "cCPUTestInfo.h"
@@ -44,7 +45,12 @@
 
 using namespace std;
 
+//! A small helper struct to make deleting a little easier.
+struct delete_functor {
+  template <typename T> void operator()(T *ptr) { delete ptr; }
+};
 
+
 tInstLib<cHardwareGX::tMethod>* cHardwareGX::s_inst_slib = cHardwareGX::initInstLib();
 
 tInstLib<cHardwareGX::tMethod>* cHardwareGX::initInstLib(void)
@@ -237,7 +243,29 @@
     tInstLibEntry<tMethod>("die", &cHardwareGX::Inst_Die),
 	    
     // Placebo instructions
-    tInstLibEntry<tMethod>("skip", &cHardwareGX::Inst_Skip)
+    tInstLibEntry<tMethod>("skip", &cHardwareGX::Inst_Skip),
+    
+    // Gene Expression Instructions
+    tInstLibEntry<tMethod>("p-alloc", &cHardwareGX::Inst_NewExecutableProgramid),
+    tInstLibEntry<tMethod>("g-alloc", &cHardwareGX::Inst_NewGenomeProgramid),
+    tInstLibEntry<tMethod>("p-copy", &cHardwareGX::Inst_ProgramidCopy),
+    tInstLibEntry<tMethod>("p-divide", &cHardwareGX::Inst_ProgramidDivide),
+    
+    tInstLibEntry<tMethod>("site", &cHardwareGX::Inst_Site),
+    tInstLibEntry<tMethod>("bind", &cHardwareGX::Inst_Bind),
+    tInstLibEntry<tMethod>("bind2", &cHardwareGX::Inst_Bind2),
+    tInstLibEntry<tMethod>("if-bind", &cHardwareGX::Inst_IfBind),
+    tInstLibEntry<tMethod>("if-bind2", &cHardwareGX::Inst_IfBind2),
+    tInstLibEntry<tMethod>("num-sites", &cHardwareGX::Inst_NumSites),
+
+    // These are dummy instructions used for making mutiple programids
+    // look like one genome (for purposes of passing to offspring and printing).
+    // They need to be included but should have ZERO probabilities!!!
+    tInstLibEntry<tMethod>("PROGRAMID", &cHardwareGX::Inst_Nop),
+    tInstLibEntry<tMethod>("READABLE", &cHardwareGX::Inst_Nop),
+    tInstLibEntry<tMethod>("BINDABLE", &cHardwareGX::Inst_Nop),
+    tInstLibEntry<tMethod>("EXECUTABLE", &cHardwareGX::Inst_Nop)
+    
   };
   
   const int n_size = sizeof(s_n_array)/sizeof(cNOPEntryCPU);
@@ -266,35 +294,58 @@
 cHardwareGX::cHardwareGX(cWorld* world, cOrganism* in_organism, cInstSet* in_m_inst_set)
 : cHardwareBase(world, in_organism, in_m_inst_set)
 {
+  m_last_unique_id_assigned = 0;
   m_functions = s_inst_slib->GetFunctions();
-  m_programids.push_back(programid_ptr(new cProgramid(in_organism->GetGenome(), this)));
-  m_current = m_programids.back();
-  Reset();                            // Setup the rest of the hardware...
+  Reset();   // Setup the rest of the hardware...also creates initial programid(s) from genome
 }
 
 
 /*! Destructor; delete all programids. */
 cHardwareGX::~cHardwareGX() 
 {
-  for(programid_list::iterator i=m_programids.begin(); i!=m_programids.end(); ++i) {
-    delete *i;
-  }
+  std::for_each(m_programids.begin(), m_programids.end(), delete_functor());
 }  
 
 
-/*! Reset this cHardwareGX to a known state.  Removes all the cProgramids, creates
-a new cProgramid from the germ.
+/*! Reset this cHardwareGX to a known state.  
+Removes all the current cProgramids, and creates new cProgramids from the germ.
 */
 void cHardwareGX::Reset()
 {
+  // Clear the current list of programids.
+  std::for_each(m_programids.begin(), m_programids.end(), delete_functor());
+  m_programids.clear(); 
+ 
+  // And add any programids specified by the "genome."
+  cGenome genome = organism->GetGenome();
+  
+  // These specify the range of instructions that will be used to create a new
+  // programid.  The range of instructions used to create a programid is:
+  // [begin, end), that is, the instruction pointed to by end is *not* copied.
+  cInstruction* begin=&genome[0];
+  cInstruction* end=&begin[genome.GetSize()];
+  cInstruction* i=0;
+  // Find the first instance of a PROGRAMID instruction.
+  begin = std::find_if(begin, end, bind2nd(equal_to<cInstruction>(), GetInstSet().GetInst("PROGRAMID")));
+  while(begin!=end) {
+    // Find the boundary of this programid.
+    i = std::find_if(begin+1, end, bind2nd(equal_to<cInstruction>(), GetInstSet().GetInst("PROGRAMID")));
+    AddProgramid(new cProgramid(cGenome(begin, i), this));
+    begin = i;
+  }
+  
+  assert(m_programids.size()>0);  
+  
+  // Sanity, oh, where is my sanity?
+  bool has_executable=false;
+  bool has_bindable=false;
   for(programid_list::iterator i=m_programids.begin(); i!=m_programids.end(); ++i) {
-    delete *i;
+    has_executable = has_executable || (*i)->GetExecutable();
+    has_bindable = has_bindable || (*i)->GetBindable();
   }
+  assert(has_bindable && has_executable);
   
-  m_programids.clear();
-  m_programids.push_back(programid_ptr(new cProgramid(organism->GetGenome(), this)));
   m_current = m_programids.back();
-
   m_mal_active = false;
   m_executedmatchstrings = false;
   
@@ -308,36 +359,10 @@
     inst_cost[i] = m_inst_set->GetCost(cInstruction(i));
     inst_ft_cost[i] = m_inst_set->GetFTCost(cInstruction(i));
   }
-#endif 
-  
+#endif
 }
 
-//void cHardwareGX::cLocalThread::operator=(const cLocalThread& in_thread)
-//{
-//  m_id = in_thread.m_id;
-//  for (int i = 0; i < NUM_REGISTERS; i++) reg[i] = in_thread.reg[i];
-//  for (int i = 0; i < NUM_HEADS; i++) heads[i] = in_thread.heads[i];
-//  stack = in_thread.stack;
-//}
-//
-//void cHardwareGX::cLocalThread::Reset(cHardwareBase* in_hardware, int in_id)
-//{
-//  m_id = in_id;
-//  
-//  for (int i = 0; i < NUM_REGISTERS; i++) reg[i] = 0;
-//  for (int i = 0; i < NUM_HEADS; i++) heads[i].Reset(in_hardware);
-//  
-//  stack.Clear();
-//  cur_stack = 0;
-//  cur_head = nHardware::HEAD_IP;
-//  read_label.Clear();
-//  next_label.Clear();
-//}
 
-
-
-// This function processes the very next command in the genome, and is made
-// to be as optimized as possible.  This is the heart of avida.
 /*! In cHardwareGX, SingleProcess is something of a misnomer.  Each time this method
   is called, each cProgramid executes a single instruction.
   */
@@ -346,25 +371,59 @@
   cPhenotype& phenotype = organism->GetPhenotype();
 
   organism->SetRunning(true);
+  m_just_divided = false;
   phenotype.IncTimeUsed();
 
-  for(programid_list::iterator i=m_programids.begin(); i!=m_programids.end(); ++i) {
-    // Set the currently-executing cProgramid.
+  // A temporary list of the current programids in this organism.
+  programid_list runnable(m_programids.begin(), m_programids.end());
+
+  // Execute one instruction for each programid.
+  for(programid_list::iterator i=runnable.begin(); i!=runnable.end(); ++i) {
+    // Currently executing programid.
     m_current = *i;
     
-    // Find the instruction to be executed.
-    const cInstruction& cur_inst = IP().GetInst();
-
-    m_advance_ip = true;
-    SingleProcess_ExecuteInst(ctx, cur_inst);
-    if (m_advance_ip == true) {
-      IP().Advance();
+    // Print the status of this CPU at each step...
+    if (m_tracer != NULL) m_tracer->TraceHardware(*this);
+    
+    if(m_current->GetExecute()) {
+      // In case the IP is modified by this instruction, make sure that it wraps 
+      // around to the beginning of the genome.
+      IP().Adjust();
+      
+      // Find the instruction to be executed.
+      const cInstruction& cur_inst = IP().GetInst();
+      
+      m_advance_ip = true;
+      SingleProcess_ExecuteInst(ctx, cur_inst);
+      
+      // Break out if we just divided b/c the number of programids 
+      // will have changed and it won't be obvious how to continue
+      if (m_just_divided) break;
+      if (m_advance_ip == true) { 
+        IP().Advance();
+      }
+      
+      // Update this programid stat
+      m_current->IncCPUCyclesUsed();  
     }
-    
-    // Update phenotype.
-    phenotype.IncCPUCyclesUsed();  
   }
+  m_current = 0;
+  
+  // Now kill old programids.
+  unsigned int on_p = 0;
+  while(on_p < m_programids.size()) {
+    if(m_programids[on_p]->GetCPUCyclesUsed() > MAX_PROGRAMID_AGE) {
+      RemoveProgramid(on_p);
+    } else {
+      on_p++;
+    }
+  }
 
+  m_current = m_programids.back(); // m_current must always point to a programid!
+
+  // Update phenotype. Note the difference between these cpu cycles and the per-programid ones...
+  phenotype.IncCPUCyclesUsed(); 
+
   // Kill creatures who have reached their max num of instructions executed.
   const int max_executed = organism->GetMaxExecuted();
   if ((max_executed > 0 && phenotype.GetTimeUsed() >= max_executed)
@@ -467,11 +526,11 @@
   return true;
 }
 
-// This method will handle the actuall execution of an instruction
-// within single process, once that function has been finalized.
+
+/*! This method executes one instruction for one programid. */
 bool cHardwareGX::SingleProcess_ExecuteInst(cAvidaContext& ctx, const cInstruction& cur_inst) 
 {
-  // Copy Instruction locally to handle stochastic effects
+  // Copy the instruction in case of execution errors.
   cInstruction actual_inst = cur_inst;
   
 #ifdef EXECUTION_ERRORS
@@ -479,12 +538,11 @@
   if (organism->TestExeErr()) actual_inst = m_inst_set->GetRandomInst(ctx);
 #endif /* EXECUTION_ERRORS */
   
-  // Get a pointer to the corrisponding method...
+  // Get the index for the instruction.
   int inst_idx = m_inst_set->GetLibFunctionIndex(actual_inst);
   
   // Mark the instruction as executed
   IP().SetFlagExecuted();
-	
   
 #if INSTRUCTION_COUNT
   // instruction execution count incremeneted
@@ -533,6 +591,16 @@
 */
 void cHardwareGX::PrintStatus(ostream& fp)
 {
+  //\todo clean up references
+  
+  // Extra information about this programid
+  fp << "MemSpace:" << m_current->GetID() << "   Programid ID:" << m_current->m_unique_id;
+  if (m_current->GetExecute()) fp << " EXECUTING";
+  if (m_current->GetExecutable()) fp << " EXECUTABLE";
+  if (m_current->GetBindable()) fp << " BINDABLE";
+  if (m_current->GetReadable()) fp << " READABLE";
+  fp << endl;
+
   fp << organism->GetPhenotype().GetCPUCyclesUsed() << " ";
   fp << "IP:" << IP().GetPosition() << "    ";
   
@@ -540,18 +608,11 @@
     fp << static_cast<char>('A' + i) << "X:" << GetRegister(i) << " ";
     fp << setbase(16) << "[0x" << GetRegister(i) << "]  " << setbase(10);
   }
-  
-  // Add some extra information if additional time costs are used for instructions,
-  // leave this out if there are no differences to keep it cleaner
-  if ( organism->GetPhenotype().GetTimeUsed() != organism->GetPhenotype().GetCPUCyclesUsed() )
-  {
-    fp << "  EnergyUsed:" << organism->GetPhenotype().GetTimeUsed();
-  }
   fp << endl;
   
-  fp << "  R-Head:" << GetHead(nHardware::HEAD_READ).GetPosition() << " "
-    << "W-Head:" << GetHead(nHardware::HEAD_WRITE).GetPosition()  << " "
-    << "F-Head:" << GetHead(nHardware::HEAD_FLOW).GetPosition()   << "  "
+  fp << "  R-Head:" << GetHead(nHardware::HEAD_READ).GetMemSpace() << ":" << GetHead(nHardware::HEAD_READ).GetPosition() << " "
+    << "W-Head:" << GetHead(nHardware::HEAD_WRITE).GetMemSpace() << ":" << GetHead(nHardware::HEAD_WRITE).GetPosition() << " "
+    << "F-Head:" << GetHead(nHardware::HEAD_FLOW).GetMemSpace() << ":" << GetHead(nHardware::HEAD_FLOW).GetPosition() << "  "
     << "RL:" << GetReadLabel().AsString() << "   "
     << endl;
 
@@ -564,17 +625,15 @@
 //      fp << " Ox" << setw(8) << GetStack(i, stack_id, 0);
 //    fp << setfill(' ') << setbase(10) << endl;
 //  }
-  
+
   fp << "  Mem (" << GetMemory().GetSize() << "):"
-		  << "  " << GetMemory().AsString()
-		  << endl;
+      << "  " << GetMemory().AsString()
+      << endl;
   fp.flush();
 }
 
 
 
-
-
 /////////////////////////////////////////////////////////////////////////
 // Method: cHardwareGX::FindLabel(direction)
 //
@@ -838,20 +897,22 @@
 */
 void cHardwareGX::InjectCode(const cGenome & inject_code, const int line_num)
 {
-  m_programids.push_back(programid_ptr(new cProgramid(inject_code, this)));
-  programid_ptr injected = m_programids.back();
-  
+  programid_ptr injected = new cProgramid(inject_code, this);
+
   // Set instruction flags on the injected code
   for(int i=0; i<injected->m_memory.GetSize(); ++i) {
     injected->m_memory.SetFlagInjected(i);
   }
+
+  AddProgramid(injected);
+  
   organism->GetPhenotype().IsModified() = true;
 }
 
 
 void cHardwareGX::ReadInst(const int in_inst)
 {
-  if (m_inst_set->IsNop( cInstruction(in_inst) )) {
+  if(m_inst_set->IsNop(cInstruction(in_inst))) {
     GetReadLabel().AddNop(in_inst);
   } else {
     GetReadLabel().Clear();
@@ -2818,6 +2879,69 @@
 }
 
 
+/*! This instruction allocates a new programid with a zero length genome
+and moves the write head of the current programid to it.
+*/
+bool cHardwareGX::Inst_NewProgramid(cAvidaContext& ctx, bool executable, bool bindable, bool readable)
+{
+  // Do some maintenance on the programid where the write head was previously.
+  // (1) Adjust the number of heads on it; this could make it executable!
+  // (2) \todo Delete if it has no instructions or is below a certain size?
+  int write_head_contacted = GetHead(nHardware::HEAD_WRITE).GetMemSpace();
+  m_programids[write_head_contacted]->RemoveContactingHead(GetHead(nHardware::HEAD_WRITE));
+  GetHead(nHardware::HEAD_WRITE).Set(0, m_current->m_id); // Immediately set the write head back to itself
+  
+  // If we've reached the programid limit, then deal with that
+  if(m_programids.size() >= MAX_PROGRAMIDS) {
+    //Decide on a programid to destroy, currently highest number of cpu cycles executed
+    //\todo more methods of choosing..
+  
+    if (PROGRAMID_REPLACEMENT_METHOD == 0) {
+      // Don't replace (they can still die of old age!)
+      return false;
+    } else if(PROGRAMID_REPLACEMENT_METHOD == 1) {
+      // Replace oldest programid
+      int destroy_index = -1;
+      int max_cpu_cycles_used = -1;
+      for (unsigned int i=0; i<m_programids.size(); i++) {
+        if (m_programids[i]->GetCPUCyclesUsed() > max_cpu_cycles_used) {
+          max_cpu_cycles_used = m_programids[i]->GetCPUCyclesUsed();
+          destroy_index = i;
+        }
+      }
+      assert(destroy_index>=0);
+      RemoveProgramid(destroy_index);
+      
+      // Also replace anything that its WRITE head contacted (unless itself)...
+      // to prevent accumulating partially copied programids
+      if(write_head_contacted != destroy_index) {
+        RemoveProgramid(write_head_contacted);
+      }
+    }
+  }
+  
+  // Create the new programid and add it to the list
+  cGenome new_genome(1);
+  programid_ptr new_programid = new cProgramid(new_genome, this);
+  new_programid->m_executable = executable;
+  new_programid->m_bindable = bindable;
+  new_programid->m_readable = readable;
+  AddProgramid(new_programid);
+  
+  // Set the write head to the newly allocated programid
+  new_programid->AddContactingHead(GetHead(nHardware::HEAD_WRITE));
+  GetHead(nHardware::HEAD_WRITE).Set(0, new_programid->GetID());
+  
+  return true;
+}
+
+bool cHardwareGX::Inst_Site(cAvidaContext& ctx)
+{
+  // Do nothing except move past the label
+  ReadLabel();
+  return true;
+}
+
 /*! This instruction reads the trailing label and tries to match it against other 
 programids in the CPU.  Note: labels that follow a match instruction in the 
 programid to be matched against are *ignored*.  Note that match should be a
@@ -2828,58 +2952,497 @@
 
 \todo Have to determine the correct placement of the heads on Bind.  If we're not
 careful, we'll allow two RNAPs to bind to each other and start copying each other's
-genome.  Probably a bad idea.
+genome.  Probably a bad idea. @JEB Well, at least those selfish solutions would die.
+Temp Soln @JEB -- added a flag to programids so that only certain programids are bindable
 */
-bool cHardwareGX::Inst_Match(cAvidaContext& ctx) {
+bool cHardwareGX::Inst_Bind(cAvidaContext& ctx) 
+{
   // Get the label that we're trying to match.
+  // Do this first to advance IP past it.
   ReadLabel();
 
-  // Now, select another programid to match against.  To start with, let's 
-  // look at all our programids and pick the first one that matches.  This will
-  // need to be revisited.
+  // Binding fails if we are already bound!
+  cHeadProgramid& read = GetHead(nHardware::HEAD_READ);
+  if(read.GetMemSpace() != m_current->GetID()) return false;
+  cHeadProgramid& write = GetHead(nHardware::HEAD_WRITE);
+
+  // Now, select another programid to match against.
+  // Go through all *other* programids looking for matches 
+  std::vector<cMatchSite> all_matches;
   for(programid_list::iterator i=m_programids.begin(); i!=m_programids.end(); ++i) {
-    std::pair<bool, cMatchSite> match = (*i)->Matches(GetLabel());
+    // Don't bind to ourself, or to whatever programid our write head is attached to.
+    if((*i != m_current) && ((*i)->GetID() != write.GetMemSpace())) {
+      std::vector<cMatchSite> matches = (*i)->Sites(GetLabel());
+      all_matches.insert(all_matches.end(), matches.begin(), matches.end());
+    }
+  }  
+  
+  // The instruction failed if there were no matches
+  if(all_matches.size() == 0) return false;
+  
+  // Otherwise set the read head to a random match
+  unsigned int c = ctx.GetRandom().GetUInt(all_matches.size());
+  
+  // Ok, it matched.  Bind the current programid's read head to the matched site.
+  m_current->Bind(nHardware::HEAD_READ, all_matches[c]);
+
+  // And we're done.
+  return true;
+}
+
+
+/*! This instruction attempts to locate two programids that have the same site.
+If two such programids are found, BX is set to 2, otherwise BX is set to 0.
+
+This instruction is well-suited for finding two genomes.  For example, the following
+instruction sequence may be used to locate two genomes with an origin of replication,
+and if found, trigger a cell division:
+bind2
+nop-B
+nop-C
+if-not-0
+p-divide
+*/
+bool cHardwareGX::Inst_Bind2(cAvidaContext& ctx)
+{
+  // Get the label we're searching for.
+  ReadLabel();
+  
+  // Search for matches to this label.
+  std::vector<cMatchSite> bindable;
+  for(programid_list::iterator i=m_programids.begin(); i!=m_programids.end(); ++i) {
+    if(*i != m_current) {
+      std::vector<cMatchSite> matches = (*i)->Sites(GetLabel());
+      // Now, we only want one match from each programid; we'll take a random one.
+      if(matches.size()>0) {
+        bindable.push_back(matches[ctx.GetRandom().GetInt(matches.size())]);
+      }
+    }
+  }
+  
+  // Select two of the matches at random.
+  if(bindable.size()>=2) {
+    int first = ctx.GetRandom().GetInt(bindable.size());
+    int second = ctx.GetRandom().GetInt(bindable.size());
+    while(first == second) { second = ctx.GetRandom().GetUInt(bindable.size()); }
+    assert(bindable[first].m_programid->GetID() != bindable[second].m_programid->GetID());
+    assert(bindable[first].m_programid->GetBindable());
+    assert(bindable[second].m_programid->GetBindable());
+    assert(bindable[first].m_programid->GetReadable());
+    assert(bindable[second].m_programid->GetReadable());
+
+    // If the caller is already bound to other programids, detach.
+    m_current->Detach();
     
-    if(match.first == true) {
-      // Ok, it matched.  Bind the current programid to the matched site.
-      // For right now, we only support read-head binding.
-      m_current->Bind(nHardware::HEAD_READ, match.second);
+    // And attach this programid's read and write heads to the indexed organisms.
+    // It *is* possible that the caller could do "bad things" now.
+    m_current->Bind(nHardware::HEAD_READ, bindable[first]);
+    m_current->Bind(nHardware::HEAD_WRITE, bindable[second]);
+
+    // Finally, set BX to indicate that bind2 worked, and return.
+    GetRegister(REG_BX) = 2;
+    return true;
+  }
+  
+  // Bind2 didn't work.
+  GetRegister(REG_BX) = 0;
+  return false;
+}
+
+
+bool cHardwareGX::Inst_IfBind(cAvidaContext& ctx) 
+{
+  // Normal Bind
+  bool ret = Inst_Bind(ctx);
+  
+  //Skip the next instruction if binding was not successful
+  if (!ret) IP().Advance();
+  
+  return ret;
+}
+
+
+bool cHardwareGX::Inst_IfBind2(cAvidaContext& ctx)
+{
+  // Normal Bind2
+  bool ret = Inst_Bind2(ctx);
+  
+  //Skip the next instruction if binding was not successful
+  if (!ret) IP().Advance();
+  
+  return ret;
+}
+
+
+/*! This instruction puts the total number of binding sites found in BX 
+Currently it is used to keep track of whether genome division has completed.*/
+bool cHardwareGX::Inst_NumSites(cAvidaContext& ctx)
+{
+  // Get the label that we're trying to match.
+  ReadLabel();
+
+  // Go through all *other* programids counting matches 
+  int num_sites = 0;
+  for(programid_list::iterator i=m_programids.begin(); i!=m_programids.end(); ++i) {
+    if (*i != m_current) {
+      num_sites += (*i)->Sites(GetLabel()).size();
+    }
+  }  
+  
+  GetRegister(REG_BX) = num_sites;
+  return true;
+}
+
+
+/*! This instruction is like h-copy, except:
+(1) It does nothing if the read and write head are not on OTHER programids
+(2) It dissociates the read head if it encounters the complement of the label that was used in the
+    match instruction that put the read head on its current target
+*/
+bool cHardwareGX::Inst_ProgramidCopy(cAvidaContext& ctx)
+{
+  cHeadProgramid& write = GetHead(nHardware::HEAD_WRITE);
+  cHeadProgramid& read = GetHead(nHardware::HEAD_READ);
+  read.Adjust(); // Strange things can happen (like we're reading from a programid that was being written).
+  
+  // Don't copy if this programid's write or read head is on itself
+  if(read.GetMemSpace() == m_current->GetID()) return false;
+  if(write.GetMemSpace() == m_current->GetID()) return false;
+  
+  // Don't copy if the source is not readable
+  if(!m_programids[read.GetMemSpace()]->GetReadable()) return false;
+
+  // If a copy is mutated in after a bind2, then the read head could be at the 
+  // end of a genome.  The copy fails, and we should probably break the bind, too.
+  if(read.GetPosition() >= read.GetMemory().GetSize()) {
+    m_current->Detach();
+    return false;
+  }
+  
+  // Keep track of whether the last non-NOP we copied was a site
+  if(GetInstSet().IsNop(read.GetInst())) {
+    m_current->m_copying_label.AddNop(GetInstSet().GetNopMod(read.GetInst()));
+  } else {
+    m_current->m_copying_site = (read.GetInst() == GetInstSet().GetInst("site"));
+    m_current->m_copying_label.Clear();
+  }
+  
+  // Allocate space for one additional instruction if the write head is at the end
+  // Otherwise the write head will improperly 
+  if(write.GetMemory().GetSize() == write.GetPosition() + 1) {
+    write.GetMemory().Resize(write.GetMemory().GetSize() + 1);
+  }
+  
+  // \todo The timing of deletion, change, insertion mutation checks matters
+  // I'm not sure this is right @JEB
+    
+  // Normal h-copy, unless a deletion occured
+  if (!organism->TestCopyDel(ctx)) {
+      // Normal h-copy
+    bool ret = Inst_HeadCopy(ctx);
+  }
+  
+  // Divide Insertion
+  if (organism->TestCopyIns(ctx)) {
+    write.GetMemory().Insert(write.GetPosition(), GetInstSet().GetRandomInst(ctx));
+    // Advance the write head;
+    write++;
+  }
+  
+  // Peek at the next inst to see if it is a NOP
+  // If it isn't, then we can compare the label and possibly fall off  
+  if(m_current->m_copying_site) {
+    if((!GetInstSet().IsNop(read.GetInst()) && (m_current->m_terminator_label == m_current->m_copying_label))) {
+      // Move read head off of old target and back to itself
+      read.GetProgramid()->RemoveContactingHead(read);
+      read.Set(0, m_current->m_id);
       
-      // And we're done.
+      //Shrink the programid we were on by one inst
+      if (write.GetMemory().GetSize()>1)
+      {
+        write.GetMemory().Resize( write.GetMemory().GetSize() - 1 );
+      }
+      
+      // \to do, we would apply insertion/deletion on divide instructions here
+      // if we want them to happen for each new programid that is produced
+      //  // Handle Divide Mutations...
+      
+      // This would be equivalent to
+      // Divide_DoMutations(ctx, mut_multiplier);
+      // But that operates on m_child_genome, currently
+      
       return true;
     }
   }
+   
+  return true;
+}
+
+
+/*! This instruction creates a new organism by randomly dividing the programids with
+the daughter cell. Currently we convert the daughter genomes back into one list with pseudo-instructions
+telling us where new programids start and some of their properties. This is pretty inefficient.
+*/
+bool cHardwareGX::Inst_ProgramidDivide(cAvidaContext& ctx)
+{
+  //This stuff is usually set by Divide_CheckViable, leaving it zero causes problems
+  cPhenotype& phenotype = organism->GetPhenotype();
+  organism->GetPhenotype().SetLinesExecuted(1);
+  organism->GetPhenotype().SetLinesCopied(1);
   
-  // If nothing matched, we're done; but the instruction didn't really work.
-  return false;
+  // Let's make sure that things seem sane.
+  cHeadProgramid& read = GetHead(nHardware::HEAD_READ); // The parent.
+  cHeadProgramid& write = GetHead(nHardware::HEAD_WRITE); // The offspring.
+  
+  // If either of these heads are on m_current, this instruction fails.
+  if(read.GetMemSpace() == m_current->GetID()) return false;
+  if(write.GetMemSpace() == m_current->GetID()) return false;
+
+  // It should never be the case that the read and write heads are on the same programid.
+  assert(read.GetMemSpace() != write.GetMemSpace());
+  // Actually, it can happen with bind2 @JEB
+  
+  // If the read and write heads are on the same programid, then fail
+  if (read.GetMemSpace() == write.GetMemSpace()) return false;
+  
+  // If we're not bound to two bindable programids, this instruction fails.
+  if(!m_programids[read.GetMemSpace()]->GetBindable()) return false;
+  if(!m_programids[write.GetMemSpace()]->GetBindable()) return false;
+  
+  // Now, let's keep track of two different lists of programids, one for the parent,
+  // and one for the offspring.
+  programid_list parent;
+  programid_list offspring;
+  // We're also going to do all our work on a temporary list, so that we can fail
+  // without affecting the state of the caller.
+  programid_list all(m_programids);
+  // This is a list of fragments, to be deleted once we've passed the viability check.
+  programid_list fragments;
+
+  // The currently executing programid called the divide instruction.  The caller
+  // is (hopefully) a DNA polymerase, therefore it knows which genome fragments go where.
+  parent.push_back(m_programids[read.GetMemSpace()]); // The parent's genome.
+  all[read.GetMemSpace()] = 0;
+  offspring.push_back(m_programids[write.GetMemSpace()]); // The offspring's genome.
+  //offspring.back()->SetBindable(true);
+  all[write.GetMemSpace()] = 0;
+  
+  // Locate and remove all incomplete genomes, identified by programids that have
+  // write heads on them.
+  for(programid_list::iterator i=all.begin(); i!=all.end(); ++i) {
+    // Does this programid currently have it's write head somewhere?
+    if((*i != 0) && ((*i)->GetHead(nHardware::HEAD_WRITE).GetMemSpace() != (*i)->GetID())) {
+      // Yes - It is likely an incomplete genome fragment, so don't
+      // allow it to propagate.
+      fragments.push_back(all[(*i)->GetHead(nHardware::HEAD_WRITE).GetMemSpace()]);
+      all[(*i)->GetHead(nHardware::HEAD_WRITE).GetMemSpace()] = 0;
+    }
+  }
+  
+  // Divvy up the programids.
+  for(programid_list::iterator i=all.begin(); i!=all.end(); ++i) {
+    if(*i != 0) {
+      if(ctx.GetRandom().GetUInt(2) == 0) {
+        // Offspring!
+        offspring.push_back(*i);
+      } else {
+        // Parent!
+        parent.push_back(*i);
+      }
+    }
+  }
+    
+  ///// Failure conditions (custom divide_check_viable)
+  // It is possible that the divide kills the child and the parent
+  // Each must have genomic programids of some minimum length
+  // and an executable programid (otherwise it is inviable)
+  // For now we leave a zombie mother to die of old age
+  // but do not permit creating an inviable daughter
+
+  // Conditions for successful replication
+  int num_daughter_programids = 0;
+  int daughter_genome_length = 0;
+  bool daughter_has_executable = false;
+  bool daughter_has_bindable = false;
+  
+  // Calculate these conditions.
+  for(programid_list::iterator i=offspring.begin(); i!=offspring.end(); ++i) {
+    ++num_daughter_programids;
+    if((*i)->GetReadable()) {
+      daughter_genome_length += (*i)->GetMemory().GetSize();
+    }
+    daughter_has_executable = daughter_has_executable || (*i)->GetExecutable();
+    daughter_has_bindable = daughter_has_bindable || (*i)->GetBindable();
+  }
+  assert(daughter_has_bindable); // We know this should be there...
+  
+  // And check them.  Note that if this check fails, we have *not* modified the
+  // state of the calling programid.
+  if((num_daughter_programids == 0) 
+     || (!daughter_has_executable) 
+     || (daughter_genome_length < 50)) { 
+    // \todo link to original genome length
+    return false;
+  }
+  
+  // Ok, we're good to go.  We have to create the offspring's genome and delete the
+  // offspring's programids from m_programids.
+  cCPUMemory& child_genome = organism->ChildGenome();
+  child_genome.Resize(1);
+  if (m_world->GetVerbosity() >= VERBOSE_DETAILS) std::cout << "-=OFFSPRING=-" << endl;
+  for(programid_list::iterator i=offspring.begin(); i!=offspring.end(); ++i) {
+    (*i)->AppendLinearGenome(child_genome);
+    if (m_world->GetVerbosity() >= VERBOSE_DETAILS) (*i)->PrintGenome(std::cout);
+    delete *i;
+    *i = 0;
+  }
+  
+  // Now clean up the parent.
+  m_programids.clear();
+  if (m_world->GetVerbosity() >= VERBOSE_DETAILS) std::cout << "-=PARENT=-" << endl;
+  for(programid_list::iterator i=parent.begin(); i!=parent.end(); ++i) {
+    AddProgramid(*i);
+    if (m_world->GetVerbosity() >= VERBOSE_DETAILS) (*i)->PrintGenome(std::cout);
+  }  
+  
+  // And delete the fragments.
+  for(programid_list::iterator i=fragments.begin(); i!=fragments.end(); ++i) {
+    delete *i;
+  }
+    
+  // Activate the child
+  bool parent_alive = organism->ActivateDivide(ctx);
+
+  // Mother viability checks could go here.  
+  m_just_divided = true;
+  return true;
 }
 
 
-/*! This instruction runs asynchronously compared to the rest of the cProgramid,
-and it is exectued ONLY when a cProgramid disassociates from another.  cProgramids
-are not required to have this instruction in their genome.
+//! Adds a new programid to the current cHardwareGX.
+void cHardwareGX::AddProgramid(programid_ptr programid) 
+{ 
+  programid->m_id = m_programids.size();
+  programid->ResetHeads();
+//  programid->ResetCPUCyclesUsed();
+  programid->m_contacting_heads = 0;
+  m_programids.push_back(programid);   
+}
 
-IF a cProgramid disassociates AND it has this instruction, then its HEAD_IP is
-updated to point to this instruction.
 
-\todo What if a cProgramid has multiple Inst_OnDisassociates?
-*/
-bool cHardwareGX::Inst_OnDisassociate(cAvidaContext& ctx) {
-  return false;
+void cHardwareGX::RemoveProgramid(unsigned int remove_index) 
+{
+  assert(remove_index<m_programids.size());
+  
+  programid_ptr save=m_current;  
+  m_current = m_programids[remove_index];
+  unsigned int write_head_contacted = (unsigned int)GetHead(nHardware::HEAD_WRITE).GetMemSpace();
+  
+  // First update the contacting head count for any cProgramids the heads 
+  // of the programid to be removed might have been on
+  m_current->Detach();
+//  m_programids[GetHead(nHardware::HEAD_READ).GetMemSpace()]->RemoveContactingHead(GetHead(nHardware::HEAD_READ));
+//  m_programids[GetHead(nHardware::HEAD_WRITE).GetMemSpace()]->RemoveContactingHead(GetHead(nHardware::HEAD_WRITE));
+
+  // Update the programid list
+  delete *(m_programids.begin()+remove_index);
+  m_programids.erase(m_programids.begin()+remove_index);
+  // Add adjust all the programid ids from the removed programid to the end.
+  for(programid_list::iterator i=m_programids.begin()+remove_index; i!=m_programids.end(); ++i) {
+    --(*i)->m_id;
+  }
+
+  // We also need to make sure heads are on the correct memory
+  // spaces, since that indexing changes with the programid list
+  for(unsigned int i=0; i< m_programids.size(); i++) {
+    programid_ptr p = m_programids[i];
+    for(int j=0; j<NUM_HEADS; j++) {
+      // We removed the thing they were writing from or reading to
+      // For now, just put the write head back on themselves (inactivating further copies)
+      // Might want to also reset the read head..
+      if (p->m_heads[j].GetMemSpace() == (int)remove_index) {
+        p->m_heads[j].Set(0, p->m_id);
+      } else if (p->m_heads[j].GetMemSpace() > (int)remove_index) {
+        p->m_heads[j].Set(p->m_heads[j].GetPosition(), p->m_heads[j].GetMemSpace() - 1);
+      }
+    }
+  }
+  
+  // Finally, also delete whatever programid our write head contacted (if not ourself!)
+  if(write_head_contacted != remove_index) {
+    RemoveProgramid( (write_head_contacted > remove_index) ? write_head_contacted - 1 : write_head_contacted);
+  }
+
+  m_current = save;
 }
 
 
 /*! Construct this cProgramid, and initialize hardware resources.
 */
-cHardwareGX::cProgramid::cProgramid(const cGenome& genome, cHardwareBase* cpu) 
-: m_offspring(0)
-, m_memory(genome) {
+cHardwareGX::cProgramid::cProgramid(const cGenome& genome, cHardwareGX* hardware)
+: m_memory(genome)
+, m_executable(false)
+, m_bindable(false)
+, m_readable(false)
+, m_copying_site(false)
+, m_cpu_cycles_used(0)
+, m_gx_hardware(hardware)
+, m_unique_id(hardware->m_last_unique_id_assigned++)
+{
+  assert(m_gx_hardware!=0);
   for(int i=0; i<NUM_HEADS; ++i) {
-    m_heads[i].Reset(cpu);
+    m_heads[i].Reset(hardware);
   }
+
+  // Check what flags should be set on this programid.
+  for(int i=0; i<m_memory.GetSize();) {
+    if(m_memory[i]==GetInst("PROGRAMID")) { 
+      m_memory.Remove(i);
+      continue;
+    }
+    if(m_memory[i]==GetInst("EXECUTABLE")) { 
+      m_memory.Remove(i); 
+      m_executable=true;
+      continue;
+    }
+    if(m_memory[i]==GetInst("BINDABLE")) { 
+      m_memory.Remove(i);
+      m_bindable=true;
+      continue;
+    }
+    if(m_memory[i]==GetInst("READABLE")) { 
+      m_memory.Remove(i);
+      m_readable=true;
+      continue;
+    }
+    ++i;
+  }
 }
 
 
+/*! Append this programid's genome to the passed in genome.  Include the tags
+that specify what this programid is capable of.
+*/
+void cHardwareGX::cProgramid::AppendLinearGenome(cCPUMemory& genome) {
+  genome.Append(GetInst("PROGRAMID"));
+  if(GetExecutable()) { genome.Append(GetInst("EXECUTABLE")); }
+  if(GetBindable()) { genome.Append(GetInst("BINDABLE")); }
+  if(GetReadable()) { genome.Append(GetInst("READABLE")); }
+  genome.Append(m_memory);
+}
+
+
+void cHardwareGX::cProgramid::PrintGenome(std::ostream& out) {
+  out << "Programid ID: " << m_id << " UID:" << m_unique_id << endl;
+  if(GetExecutable()) out << " EXECUTABLE";
+  if(GetBindable()) out << " BINDABLE";
+  if(GetReadable()) out << " READABLE";
+  out << endl;
+  out << " Mem (" << GetMemory().GetSize() << "):" << " " << GetMemory().AsString() << endl;
+  out.flush();
+}
+
+
 /*! This method attempts to match this cProgramid with the passed-in label.  If the
 match is succesful, it returns true and a cMatchSite object that may be used to bind
 to the programid.  If the match is unsuccessful, it return false and the cMatchSite
@@ -2889,8 +3452,79 @@
 to the the passed-in label.  A number of configuration options (will eventually)
 control how precisely the NOPs must be related (e.g., exact, all-but-one, etc.).
 */
-std::pair<bool, cHardwareGX::cMatchSite> cHardwareGX::cProgramid::Matches(const cCodeLabel& label) {
-  return std::make_pair(false, cMatchSite());
+std::vector<cHardwareGX::cMatchSite> cHardwareGX::cProgramid::Sites(const cCodeLabel& label) 
+{
+  std::vector<cHardwareGX::cMatchSite> matches;
+  if(!m_bindable) return matches;
+  
+  cInstruction site_inst = m_gx_hardware->GetInstSet().GetInst("site");
+  
+  // Create a new search head at the beginning of our memory space
+  // \to do doesn't properly find wrap-around matches overlapping the origin of the memory
+  
+  //Find the first non-NOP and start there (this allows ups to wrap around correctly)
+  cHeadCPU search_head(m_gx_hardware, 0, m_id);
+  int first_non_nop = -1;
+  do {
+    if ( !m_gx_hardware->m_inst_set->IsNop(search_head.GetInst()) )
+    {
+      first_non_nop = search_head.GetPosition();
+      break;
+    }
+    search_head++;
+  } while (search_head.GetPosition() != 0);
+  
+  // This genome is all NOPs...
+  if (first_non_nop == -1) return matches;
+  
+  //keep track of the first time we find a non-NOP instruction (finish when we reach it a second time)
+  int site_pos = -1;
+  cCodeLabel site_label;
+  
+  // Start at this instruction
+  search_head.Set(first_non_nop, m_id);
+  do {
+  
+    if (search_head.GetInst() == site_inst)
+    {
+      site_pos = search_head.GetPosition();
+      site_label.Clear();
+    }
+    else if ( m_gx_hardware->m_inst_set->IsNop(search_head.GetInst()) && (site_pos != -1) )
+    {
+      // Add NOPs to the current label
+      site_label.AddNop( m_gx_hardware->m_inst_set->GetNopMod( search_head.GetInst() ) );
+    }
+    else // Any other non-NOP instruction means to stop looking for terminator matches
+    {
+      site_pos = -1;
+    }
+     
+    // Is the next inst a NOP?
+    // If not, then check our current label for termination
+    if (site_pos != -1)
+    {
+      int old_pos = search_head.GetPosition();
+      search_head++;
+      if ( !m_gx_hardware->m_inst_set->IsNop( search_head.GetInst()) )
+      {
+        if ( site_label == label )
+        {
+          cMatchSite match;
+          match.m_programid = this;
+          match.m_site = site_pos; // We return is exactly on the site
+          match.m_label = site_label;
+          matches.push_back(match);
+        }
+      }
+      
+      // Grrr. Heads don't wrap backwards properly!~! Can't just search_head--; No idea why.
+      search_head.Set(old_pos, m_id);
+    }
+    
+    search_head++;
+  } while ( search_head.GetPosition() != first_non_nop ); // back at the beginning 
+
 }
 
 
@@ -2899,14 +3533,31 @@
 location in the genome of the other cProgramid, but this will be extended later.
 */
 void cHardwareGX::cProgramid::Bind(nHardware::tHeads head, cMatchSite& site) {
+  // We set the terminator site label to the complement of the one that was bound.
+  m_terminator_label = site.m_label;
+  m_terminator_label.Rotate(1, NUM_NOPS);
+  
+  // Set the head.
+  if(GetHead(head).GetMemSpace() != GetID()) {
+    // Head is somewhere else; remove it
+    m_gx_hardware->m_programids[GetHead(head).GetMemSpace()]->RemoveContactingHead(GetHead(head));
+  }
+  
+  // Now attach it to the passed-in match site
+  m_gx_hardware->m_programids[site.m_programid->GetID()]->AddContactingHead(GetHead(head));
+  GetHead(head).Set(site.m_site, site.m_programid->GetID());
 }
 
 
-/*! Disassociate is called when this cProgramids's read head traverses over the
-complement of the label that was used to Bind this cProgramid to another.  When
-called, Disassociate removes this cProgramid's read head from the bound cProgramid,
-searches for an Inst_OnDisassociate in its own genome, and, if found, updates this
-cProgramid's IP to point to it.
+/*! This method detaches the caller's heads from programids that it is connected
+to.  It also updates the head contact counts.
 */
-void cHardwareGX::cProgramid::Disassociate() {
+void cHardwareGX::cProgramid::Detach() {
+  int head = GetHead(nHardware::HEAD_WRITE).GetMemSpace();
+  m_gx_hardware->m_programids[head]->RemoveContactingHead(GetHead(nHardware::HEAD_WRITE));
+  GetHead(nHardware::HEAD_WRITE).Set(0, GetID());
+  
+  head = GetHead(nHardware::HEAD_READ).GetMemSpace();
+  m_gx_hardware->m_programids[head]->RemoveContactingHead(GetHead(nHardware::HEAD_READ));
+  GetHead(nHardware::HEAD_READ).Set(0, GetID());
 }

Modified: branches/collect/source/cpu/cHardwareGX.h
===================================================================
--- branches/collect/source/cpu/cHardwareGX.h	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/source/cpu/cHardwareGX.h	2007-05-22 16:50:55 UTC (rev 1589)
@@ -19,8 +19,12 @@
  *  new CPU, so that's what we're doing.  Eventually we'll need to revisit this.
  *
  * \todo There should be better ways for promoter regions to work.  Right now,
- *  we stop at the first one encountered.
+ * look for exact matches only and they have equal probabilities @JEB
  *
+ * \todo We need to abstract cOrganism and derive a new class
+ * that can accommodate multiple genome fragments.
+ *
+ *
  *  Copyright 1999-2007 Michigan State University. All rights reserved.
  *
  *  This program is free software; you can redistribute it and/or
@@ -43,6 +47,7 @@
 
 #include <iomanip>
 #include <vector>
+#include <list>
 #include <utility>
 #include "cCodeLabel.h"
 #include "cHeadCPU.h"
@@ -66,7 +71,8 @@
 
 /*! Each organism may have a cHardwareGX structure that keeps track of the 
 * current status of simulated hardware.  This particular CPU architecture is
-* designed to explore the evolution of gene expression.
+* designed to explore the evolution of gene expression and also the effect
+* of having persistent "protein-like" pieces of code that continually execute in parallel.
 */
 class cHardwareGX : public cHardwareBase
 {
@@ -78,6 +84,16 @@
   static const int NUM_HEADS = nHardware::NUM_HEADS >= NUM_REGISTERS ? nHardware::NUM_HEADS : NUM_REGISTERS;
   static const int NUM_NOPS = 3; //!< Number of NOPS that cHardwareGX supports.
 
+  //!< \todo JEB Make these config options
+  static const unsigned int MAX_PROGRAMIDS = 32; //!< Number of cProgramids that an organism can allocate.
+  static const int PROGRAMID_REPLACEMENT_METHOD = 0;
+   //!< Controls what happens when we try to allocate a new cProgramid, but are up against the limit
+  // 0 = Fail if no programids available
+  // 1 = Replace the programid that has completed the most instructions
+  static const int MAX_PROGRAMID_AGE = 2000; // Number of inst a cProgramid executes before ceasing to exist
+
+  unsigned int m_last_unique_id_assigned; // Counter so programids can be assigned unique IDs for tracking
+
   //! Enums for the different supported registers.
   enum tRegisters { REG_AX=0, REG_BX, REG_CX };
   
@@ -89,9 +105,24 @@
   struct cMatchSite {
     cMatchSite() : m_programid(0), m_site(0) { }
     cProgramid* m_programid; //!< The programid matched against; 0 if not matched.
-    cInstruction* m_site; //!< Location in the cProgramid where a match occurred; 0 if not matched.
+    int m_site; //!< Location in the cProgramid where a match occurred; 0 if not matched.
     cCodeLabel m_label; //!< The label that was matched against.
   };
+
+  /*! cHeadProgramid is just cHeadCPU with a link back to the programid
+  so that we can tell when a head is on the programid that owns it.
+  */
+  class cHeadProgramid : public cHeadCPU 
+  {
+  private:
+    cProgramid* m_programid;
+  public:
+    cHeadProgramid() : cHeadCPU(), m_programid(NULL) {  }
+    ~cHeadProgramid() { ; }
+      
+    void SetProgramid(cProgramid* _programid) { m_programid = _programid; }
+    cProgramid* GetProgramid() { return m_programid; }
+  };
   
   /*! cProgramid is the "heart" of the gene expression hardware.  It encapsulates
     the genome fragment that is used by both active and passive elements within
@@ -104,35 +135,97 @@
     
     \todo Need to rework cHeadCPU to not need a pointer to cHardwareBase.
     */
-  struct cProgramid {
+  class cProgramid {
+  public:
     //! Constructs a cProgramid from a genome and CPU.
-    cProgramid(const cGenome& genome, cHardwareBase* cpu);
+    cProgramid(const cGenome& genome, cHardwareGX* hardware);
     //! Returns whether and where this cProgramid matches the passed-in label.
-    std::pair<bool, cMatchSite> Matches(const cCodeLabel& label);
+    std::vector<cHardwareGX::cMatchSite> Sites(const cCodeLabel& label);
     //! Binds one of this cProgramid's heads to the passed-in match site.
     void Bind(nHardware::tHeads head, cMatchSite& site);
-    //! Called when this cProgramid "falls off" the cProgramid it is bound to.
-    void Disassociate();
+    //! Detaches this cProgramid's heads from bound cProgramids.
+    void Detach();
     
-    programid_ptr m_offspring; //!< An offspring of this cProgramid; may be null.
-    cCodeLabel m_terminator; //!< The label that this cProgramid must traverse to disassociate.
+    // Programids keep a count of the total number
+    // of READ + WRITE heads of other programids that 
+    // have been placed on them. They only execute
+    // if free of other heads and also initialized as executable.
+    void RemoveContactingHead(cHeadProgramid& head) {
+      if(head.GetProgramid()->GetID() == m_id) return;
+      assert(m_contacting_heads > 0);
+      m_contacting_heads--; 
+    }
+    
+    void AddContactingHead(cHeadProgramid& head) { 
+      if(head.GetProgramid()->GetID() == m_id) return; 
+      m_contacting_heads++; 
+    }
+    
+    void ResetHeads() {
+      for(int i=0; i<NUM_HEADS; ++i) {
+        m_heads[i].SetProgramid(this);
+        m_heads[i].Reset(m_gx_hardware, m_id);
+      }
+    }
+    
+    // Accessors
+    bool GetExecute() { return m_executable && (m_contacting_heads == 0); }
+    bool GetExecutable() { return m_executable; }
+    bool GetBindable() { return m_bindable; }
+    bool GetReadable() { return m_readable; }
+    int  GetID() { return m_id; }
+    int  GetCPUCyclesUsed() { return m_cpu_cycles_used; }
+    void ResetCPUCyclesUsed() { m_cpu_cycles_used = 0; }
+    cInstruction GetInst(cString inst) { assert(m_gx_hardware); return m_gx_hardware->GetInstSet().GetInst(inst); }
+
+    const cCPUMemory& GetMemory() const { return m_memory; }
+    
+    //! Append this programid's genome to the passed-in genome in linear format (includes tags).
+    void AppendLinearGenome(cCPUMemory& genome);
+
+    //! Print this programid's genome, in linear format.
+    void PrintGenome(std::ostream& out);
+    
+    cHeadProgramid& GetHead(int head_id) { return m_heads[head_id]; }
+    
+    // Assignment
+    void SetExecutable(bool _executable) { m_executable = _executable; }
+    void SetBindable(bool _bindable) { m_bindable = _bindable; }
+    void SetReadable(bool _readable) { m_readable = _readable; }
+
+    void IncCPUCyclesUsed() { m_cpu_cycles_used++; }
+    
+    cHardwareGX* m_gx_hardware;  //!< Back reference
+    int m_id; //!< Each programid is cross-referenced to a memory space. 
+              // The index in cHardwareGX::m_programids and cHeadCPU::GetMemSpace() must match up.
+              // A programid also needs to be kept aware of its current index.
+    int m_unique_id; // ID unique to this programid (per hardware)          
+              
+    int m_contacting_heads; //!< The number of read/write heads on this programid from other programids. 
+    bool m_executable;  //!< Is this programid ever executable? Currently, a programid with head from another cProgramid on it is also stopped. 
+    bool m_bindable; //!< Is this programid bindable, i.e. can other programids put their read heads on it?
+    bool m_readable; //!< Is this programid readable?
+    int m_cpu_cycles_used; //!< Number of cpu cycles this programid has used.
+
+    bool m_copying_site; //! Are we in the middle of copying a "site" (which could cause termination)
+    cCodeLabel m_copying_label; //! The current site label that we are copying
+    cCodeLabel m_terminator_label; //!< The label that this cProgramid must traverse to disassociate.
+
+    // Core variables maintained from previous incarnation as a thread
     cCodeLabel m_readLabel; //!< ?
     cCodeLabel m_nextLabel; //!< ?
     cCPUMemory m_memory; //!< This cProgramid's genome fragment.
     cCPUStack m_stack; //!< This cProgramid's stack (no global stack).
-    cHeadCPU m_heads[NUM_HEADS]; //!< This cProgramid's heads.
+    cHeadProgramid m_heads[NUM_HEADS]; //!< This cProgramid's heads.
     int m_regs[NUM_REGISTERS]; //!< This cProgramid's registers.
   };
   
-
-  
 protected:
   static tInstLib<tMethod>* initInstLib(void); //!< Initialize the instruction library.
   static tInstLib<tMethod>* s_inst_slib; //!< Instruction library (method pointers for all instructions).
 
   programid_list m_programids; //!< The list of cProgramids.
   programid_ptr m_current; //!< The currently-executing cProgramid.
-
   
   // --------  Member Variables  --------
   const tMethod* m_functions;
@@ -141,6 +234,7 @@
   bool m_mal_active;         // Has an allocate occured since last divide?
   bool m_advance_ip;         // Should the IP advance after this instruction?
   bool m_executedmatchstrings;	// Have we already executed the match strings instruction?
+  bool m_just_divided; // Did we just divide (in which case end execution of programids until next cycle).
 
   // Instruction costs...
 #if INSTRUCTION_COSTS
@@ -153,25 +247,25 @@
   bool SingleProcess_ExecuteInst(cAvidaContext& ctx, const cInstruction& cur_inst);
   
   // --------  Stack Manipulation...  --------
-  inline void StackPush(int value) { m_current->m_stack.Push(value); }
-  inline int StackPop() { return m_current->m_stack.Pop(); }
-  inline void StackFlip() { m_current->m_stack.Flip(); }
-  inline void StackClear() { m_current->m_stack.Clear(); }
+  inline void StackPush(int value) { assert(m_current); m_current->m_stack.Push(value); }
+  inline int StackPop() { assert(m_current); return m_current->m_stack.Pop(); }
+  inline void StackFlip() { assert(m_current); m_current->m_stack.Flip(); }
+  inline void StackClear() { assert(m_current); m_current->m_stack.Clear(); }
   inline void SwitchStack() { }
   
   // --------  Head Manipulation (including IP)  --------
   void AdjustHeads();
   
   // --------  Label Manipulation  -------
-  const cCodeLabel& GetLabel() const { return m_current->m_nextLabel; }
-  cCodeLabel& GetLabel() { return m_current->m_nextLabel; }
+  const cCodeLabel& GetLabel() const { assert(m_current); return m_current->m_nextLabel; }
+  cCodeLabel& GetLabel() { assert(m_current); return m_current->m_nextLabel; }
   void ReadLabel(int max_size=nHardware::MAX_LABEL_SIZE);
   cHeadCPU FindLabel(int direction);
   int FindLabel_Forward(const cCodeLabel & search_label, const cGenome& search_genome, int pos);
   int FindLabel_Backward(const cCodeLabel & search_label, const cGenome& search_genome, int pos);
   cHeadCPU FindLabel(const cCodeLabel & in_label, int direction);
-  const cCodeLabel& GetReadLabel() const { return m_current->m_readLabel; }
-  cCodeLabel& GetReadLabel() { return m_current->m_readLabel; }
+  const cCodeLabel& GetReadLabel() const { assert(m_current); return m_current->m_readLabel; }
+  cCodeLabel& GetReadLabel() { assert(m_current); return m_current->m_readLabel; }
 
   // ---------- Instruction Helpers -----------
   int FindModifiedRegister(int default_register);
@@ -211,33 +305,36 @@
 
 
   // --------  Stack Manipulation...  --------
-  inline int GetStack(int depth=0, int stack_id=-1, int in_thread=-1) const { return m_current->m_stack.Get(depth); }
+  inline int GetStack(int depth=0, int stack_id=-1, int in_thread=-1) const { assert(m_current); return m_current->m_stack.Get(depth); }
   inline int GetNumStacks() const { return 2; }
   
   // --------  Head Manipulation (including IP)  --------
-  const cHeadCPU& GetHead(int head_id) const { return m_current->m_heads[head_id]; }
-  cHeadCPU& GetHead(int head_id) { return m_current->m_heads[head_id];}
-  const cHeadCPU& GetHead(int head_id, int thread) const { return m_current->m_heads[head_id]; }
-  cHeadCPU& GetHead(int head_id, int thread) { return m_current->m_heads[head_id];}
+  const cHeadProgramid& GetHead(int head_id) const { assert(m_current); return m_current->m_heads[head_id]; }
+  cHeadProgramid& GetHead(int head_id) { assert(m_current); return m_current->m_heads[head_id];}
+  const cHeadProgramid& GetHead(int head_id, int thread) const { assert(m_current); return m_current->m_heads[head_id]; }
+  cHeadProgramid& GetHead(int head_id, int thread) { assert(m_current); return m_current->m_heads[head_id];}
   int GetNumHeads() const { return NUM_HEADS; }
   
-  const cHeadCPU& IP() const { return m_current->m_heads[nHardware::HEAD_IP]; }
-  cHeadCPU& IP() { return m_current->m_heads[nHardware::HEAD_IP]; }
-  const cHeadCPU& IP(int thread) const { return m_current->m_heads[nHardware::HEAD_IP]; }
-  cHeadCPU& IP(int thread) { return m_current->m_heads[nHardware::HEAD_IP]; }
+  const cHeadCPU& IP() const { assert(m_current); return m_current->m_heads[nHardware::HEAD_IP]; }
+  cHeadCPU& IP() { assert(m_current); return m_current->m_heads[nHardware::HEAD_IP]; }
+  const cHeadCPU& IP(int thread) const { assert(m_current); return m_current->m_heads[nHardware::HEAD_IP]; }
+  cHeadCPU& IP(int thread) { assert(m_current); return m_current->m_heads[nHardware::HEAD_IP]; }
   
   
   // --------  Memory Manipulation  --------
-  const cCPUMemory& GetMemory() const { return m_current->m_memory; }
-  cCPUMemory& GetMemory() { return m_current->m_memory; }
-  const cCPUMemory& GetMemory(int value) const { return m_current->m_memory; }
-  cCPUMemory& GetMemory(int value) { return m_current->m_memory; }
-  int GetNumMemSpaces() const { return 1; }
+  //<! Each programid counts as a memory space.
+  // Heads from one programid can end up on another,
+  // so be careful to fix these when changing the programid list.
+  const cCPUMemory& GetMemory() const { assert(m_current); return m_current->m_memory; }
+  cCPUMemory& GetMemory() { assert(m_current); return m_current->m_memory; }
+  const cCPUMemory& GetMemory(int value) const { return m_programids[value]->m_memory; }
+  cCPUMemory& GetMemory(int value) { return m_programids[value]->m_memory; }
+  int GetNumMemSpaces() const { return m_programids.size(); }
   
   
   // --------  Register Manipulation  --------
-  const int GetRegister(int reg_id) const { return m_current->m_regs[reg_id]; }
-  int& GetRegister(int reg_id) { return m_current->m_regs[reg_id]; }
+  const int GetRegister(int reg_id) const { assert(m_current); return m_current->m_regs[reg_id]; }
+  int& GetRegister(int reg_id) { assert(m_current); return m_current->m_regs[reg_id]; }
   int GetNumRegisters() const { return NUM_REGISTERS; }  
   
   // --------  Thread Manipuluation --------
@@ -440,8 +537,22 @@
   bool Inst_Skip(cAvidaContext& ctx);
   
   // -= Gene expression instructions =-
-  bool Inst_Match(cAvidaContext& ctx); //!< Attempt to match the currently executing cProgramid against other cProgramids.
-  bool Inst_OnDisassociate(cAvidaContext& ctx); //!< Called automatically when a cProgramid disassociates.
+  bool Inst_NewProgramid(cAvidaContext& ctx, bool executable, bool bindable, bool readable); //!< Allocate a new programid and place the write head there.
+  bool Inst_NewExecutableProgramid(cAvidaContext& ctx) { return Inst_NewProgramid(ctx, true, false, false); } //!< Allocate a "protein". Cannot be bound or read.
+  bool Inst_NewGenomeProgramid(cAvidaContext& ctx) { return Inst_NewProgramid(ctx, false, true, true); } //!< Allocate a "genomic" fragment. Cannot execute.
+  
+  bool Inst_Site(cAvidaContext& ctx); //!< A binding site (execution simply advances past label)
+  bool Inst_Bind(cAvidaContext& ctx); //!< Attempt to match the currently executing cProgramid against other cProgramids.
+  bool Inst_Bind2(cAvidaContext& ctx); //!< Attempt to locate two programids with the same site.
+  bool Inst_IfBind(cAvidaContext& ctx); //!< Attempt to match the currently executing cProgramid against other cProgramids. Execute next inst if successful.
+  bool Inst_IfBind2(cAvidaContext& ctx); //!< Attempt to match and bind two programids.
+  bool Inst_NumSites(cAvidaContext& ctx); //!< Count the number of corresponding binding sites
+  bool Inst_ProgramidCopy(cAvidaContext& ctx); //!< Like h-copy, but fails if read/write heads not on other programids and will not write over
+  bool Inst_ProgramidDivide(cAvidaContext& ctx); //!< Like h-divide, 
+  
+  //!< Add/Remove a new programid to/from the list and give it the proper index within the list so we keep track of memory spaces...
+  void AddProgramid(programid_ptr programid);
+  void RemoveProgramid(unsigned int remove_index);  
 };
 
 

Modified: branches/collect/source/main/cAvidaConfig.h
===================================================================
--- branches/collect/source/main/cAvidaConfig.h	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/source/main/cAvidaConfig.h	2007-05-22 16:50:55 UTC (rev 1589)
@@ -352,6 +352,10 @@
   CONFIG_ADD_VAR(ANALYZE_OPTION_1, cString, "", "String variable accessible from analysis scripts");
   CONFIG_ADD_VAR(ANALYZE_OPTION_2, cString, "", "String variable accessible from analysis scripts");
 
+		CONFIG_ADD_GROUP(SECOND_PASS_GROUP, "Tracking metrics known after the running experiment previously");
+	CONFIG_ADD_VAR(TRACK_CCLADES, int, 0, "Enable tracking of coalescence clades");
+	CONFIG_ADD_VAR(TRACK_CCLADES_IDS, cString, "coalescence.ids", "File storing coalescence IDs");
+	
 #endif
   
   void Load(const cString& filename, const bool& crash_if_not_found);

Modified: branches/collect/source/main/cEnvironment.cc
===================================================================
--- branches/collect/source/main/cEnvironment.cc	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/source/main/cEnvironment.cc	2007-05-22 16:50:55 UTC (rev 1589)
@@ -827,12 +827,13 @@
     }
 
     const double task_quality = m_tasklib.TestOutput(taskctx);
+	
 
     // If this task wasn't performed, move on to the next one.
     if (task_quality == 0.0) continue;
     
     // Mark this task as performed...
-    result.MarkTask(task_id, task_quality);
+    result.MarkTask(task_id, task_quality, taskctx.GetTaskValue());
 
     // And let's process it!
     DoProcesses(ctx, cur_reaction->GetProcesses(), resource_count, rbins_count, task_quality, task_cnt, i, result);

Modified: branches/collect/source/main/cMutationRates.h
===================================================================
--- branches/collect/source/main/cMutationRates.h	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/source/main/cMutationRates.h	2007-05-22 16:50:55 UTC (rev 1589)
@@ -92,6 +92,8 @@
 
   bool TestPointMut(cAvidaContext& ctx) const { return ctx.GetRandom().P(exec.point_mut_prob); }
   bool TestCopyMut(cAvidaContext& ctx) const { return ctx.GetRandom().P(copy.mut_prob); }
+  bool TestCopyIns(cAvidaContext& ctx) const { return ctx.GetRandom().P(divide.ins_prob); }
+  bool TestCopyDel(cAvidaContext& ctx) const { return ctx.GetRandom().P(divide.del_prob); }
   bool TestDivideMut(cAvidaContext& ctx) const { return ctx.GetRandom().P(divide.divide_mut_prob); }
   bool TestDivideIns(cAvidaContext& ctx) const { return ctx.GetRandom().P(divide.divide_ins_prob); }
   bool TestDivideDel(cAvidaContext& ctx) const { return ctx.GetRandom().P(divide.divide_del_prob); }

Modified: branches/collect/source/main/cOrganism.h
===================================================================
--- branches/collect/source/main/cOrganism.h	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/source/main/cOrganism.h	2007-05-22 16:50:55 UTC (rev 1589)
@@ -95,9 +95,11 @@
   int m_id;                               // unique id for each org, is just the number it was born
   int m_lineage_label;                    // a lineages tag; inherited unchanged in offspring
   cLineage* m_lineage;                    // A lineage descriptor... (different from label)
-  tArray<double> m_rbins;				  // Holds amount of resources internal to org
+	int cclade_id;				                  // @MRR Coalescence clade information (set in cPopulation)
+  tArray<double> m_rbins;				          // Holds amount of resources internal to org
+  
+	// Other stats
 
-  // Other stats
   cCPUMemory m_child_genome; // Child genome, while under construction.
   sCPUStats m_cpu_stats;     // Info for statistics
 
@@ -161,13 +163,16 @@
   void SetLineage(cLineage* in_lineage) { m_lineage = in_lineage; }
   cLineage* GetLineage() const { return m_lineage; }
   
-  const tArray<double>& GetRBins() const { return m_rbins; }
+	void SetCCladeLabel( int in_label ) { cclade_id = in_label; };  //@MRR
+	int  GetCCladeLabel() const { return cclade_id; }
+	
+	const tArray<double>& GetRBins() const { return m_rbins; }
   tArray<double>& GetRBins() { return m_rbins; }
   double GetRBin(int index) { return m_rbins[index]; }
   void SetRBins(const tArray<double>& rbins_in);
   void SetRBin(const int index, const double value);
   void AddToRBin(const int index, const double value);
-  
+
   int GetMaxExecuted() const { return m_max_executed; }
   
   cCPUMemory& ChildGenome() { return m_child_genome; }
@@ -243,6 +248,8 @@
 
   // --------  Mutation Rate Convenience Methods  --------
   bool TestCopyMut(cAvidaContext& ctx) const { return m_mut_rates.TestCopyMut(ctx); }
+  bool TestCopyIns(cAvidaContext& ctx) const { return m_mut_rates.TestCopyIns(ctx); }
+  bool TestCopyDel(cAvidaContext& ctx) const { return m_mut_rates.TestCopyDel(ctx); }
   bool TestDivideMut(cAvidaContext& ctx) const { return m_mut_rates.TestDivideMut(ctx); }
   bool TestDivideIns(cAvidaContext& ctx) const { return m_mut_rates.TestDivideIns(ctx); }
   bool TestDivideDel(cAvidaContext& ctx) const { return m_mut_rates.TestDivideDel(ctx); }

Modified: branches/collect/source/main/cPhenotype.cc
===================================================================
--- branches/collect/source/main/cPhenotype.cc	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/source/main/cPhenotype.cc	2007-05-22 16:50:55 UTC (rev 1589)
@@ -45,6 +45,7 @@
   , cur_internal_task_count(m_world->GetEnvironment().GetNumTasks())
   , eff_task_count(m_world->GetEnvironment().GetNumTasks())
   , cur_task_quality(m_world->GetEnvironment().GetNumTasks())  
+  , cur_task_value(m_world->GetEnvironment().GetNumTasks())  
   , cur_internal_task_quality(m_world->GetEnvironment().GetNumTasks())
   , cur_rbins_total(m_world->GetNumResources())
   , cur_rbins_avail(m_world->GetNumResources())
@@ -57,6 +58,7 @@
   , last_internal_task_count(m_world->GetEnvironment().GetNumTasks())
   , last_reaction_add_reward(m_world->GetEnvironment().GetReactionLib().GetSize())  
   , last_task_quality(m_world->GetEnvironment().GetNumTasks())
+  , last_task_value(m_world->GetEnvironment().GetNumTasks())
   , last_internal_task_quality(m_world->GetEnvironment().GetNumTasks())
   , last_rbins_total(m_world->GetNumResources())
   , last_rbins_avail(m_world->GetNumResources())
@@ -141,6 +143,7 @@
   cur_internal_task_count.SetAll(0);
   eff_task_count.SetAll(0);
   cur_task_quality.SetAll(0);
+  cur_task_value.SetAll(0);
   cur_internal_task_quality.SetAll(0);
   cur_rbins_total.SetAll(0);
   cur_rbins_avail.SetAll(0);
@@ -160,6 +163,7 @@
   last_task_count           = parent_phenotype.last_task_count;
   last_internal_task_count  = parent_phenotype.last_internal_task_count;
   last_task_quality         = parent_phenotype.last_task_quality;
+  last_task_value			= parent_phenotype.last_task_value;
   last_internal_task_quality= parent_phenotype.last_internal_task_quality;
   last_rbins_total           = parent_phenotype.last_rbins_total;
   last_rbins_avail           = parent_phenotype.last_rbins_avail;
@@ -239,6 +243,7 @@
   cur_internal_task_count.SetAll(0);
   eff_task_count.SetAll(0);
   cur_task_quality.SetAll(0);
+  cur_task_value.SetAll(0);
   cur_internal_task_quality.SetAll(0);
   cur_rbins_total.SetAll(0);
   cur_rbins_avail.SetAll(0);
@@ -257,6 +262,7 @@
   last_task_count.SetAll(0);
   last_internal_task_count.SetAll(0);
   last_task_quality.SetAll(0);
+  last_task_value.SetAll(0);
   last_internal_task_quality.SetAll(0);
   last_rbins_total.SetAll(0);
   last_rbins_avail.SetAll(0);
@@ -341,6 +347,7 @@
   last_task_count           = cur_task_count;
   last_internal_task_count  = cur_internal_task_count;
   last_task_quality         = cur_task_quality;
+  last_task_value			= cur_task_value;
   last_internal_task_quality= cur_internal_task_quality;
   last_rbins_total           = cur_rbins_total;
   last_rbins_avail           = cur_rbins_avail;
@@ -357,6 +364,7 @@
   cur_internal_task_count.SetAll(0);
   eff_task_count.SetAll(0);
   cur_task_quality.SetAll(0);
+  cur_task_value.SetAll(0);
   cur_internal_task_quality.SetAll(0);
   cur_rbins_total.SetAll(0);
   cur_rbins_avail.SetAll(0);
@@ -449,9 +457,10 @@
   last_task_count           = cur_task_count;
   last_internal_task_count  = cur_internal_task_count;
   last_task_quality         = cur_task_quality;
+  last_task_value			= cur_task_value;
   last_internal_task_quality= cur_internal_task_quality;
-  last_rbins_total           = cur_rbins_total;
-  last_rbins_avail           = cur_rbins_avail;
+  last_rbins_total          = cur_rbins_total;
+  last_rbins_avail          = cur_rbins_avail;
   last_reaction_count       = cur_reaction_count;
   last_reaction_add_reward  = cur_reaction_add_reward;
   last_inst_count           = cur_inst_count;
@@ -465,6 +474,7 @@
   cur_internal_task_count.SetAll(0);
   eff_task_count.SetAll(0);
   cur_task_quality.SetAll(0);
+  cur_task_value.SetAll(0);
   cur_internal_task_quality.SetAll(0);
   cur_rbins_total.SetAll(0);
   cur_rbins_avail.SetAll(0);
@@ -657,6 +667,7 @@
     	cur_task_quality[i]+= result.TaskQuality(i);
     	if(result.UsedEnvResource() == false) { cur_internal_task_quality[i] += result.TaskQuality(i); }
     }
+	cur_task_value[i] = result.TaskValue(i);
   }
   for (int i = 0; i < num_reactions; i++) {
     if (result.ReactionTriggered(i) == true) cur_reaction_count[i]++;

Modified: branches/collect/source/main/cPhenotype.h
===================================================================
--- branches/collect/source/main/cPhenotype.h	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/source/main/cPhenotype.h	2007-05-22 16:50:55 UTC (rev 1589)
@@ -108,6 +108,7 @@
   tArray<int> cur_internal_task_count;        // Total times each task was performed using internal resources
   tArray<int> eff_task_count;                 // Total times each task was performed (resetable during the life of the organism)
   tArray<double> cur_task_quality;            // Average (total?) quality with which each task was performed
+  tArray<double> cur_task_value;			  // Value with which this phenotype performs task
   tArray<double> cur_internal_task_quality;   // Average (total?) quaility with which each task using internal resources was performed
   tArray<double> cur_rbins_total;              // Total amount of resources collected
   tArray<double> cur_rbins_avail;              // Total amount of internal resources available
@@ -134,6 +135,7 @@
   tArray<int> last_task_count;
   tArray<int> last_internal_task_count;
   tArray<double> last_task_quality;
+  tArray<double> last_task_value;
   tArray<double> last_internal_task_quality;
   tArray<double> last_rbins_total;
   tArray<double> last_rbins_avail;
@@ -255,6 +257,7 @@
   const tArray<int>& GetCurInternalTaskCount() const { assert(initialized == true); return cur_internal_task_count; }
   void ClearEffTaskCount() { assert(initialized == true); eff_task_count.SetAll(0); }
   const tArray<double> & GetCurTaskQuality() const { assert(initialized == true); return cur_task_quality; }
+  const tArray<double> & GetCurTaskValue() const { assert(initialized == true); return cur_task_value; }
   const tArray<double> & GetCurInternalTaskQuality() const { assert(initialized == true); return cur_internal_task_quality; }
   const tArray<double>& GetCurRBinsTotal() const { assert(initialized == true); return cur_rbins_total; }
   const tArray<double>& GetCurRBinsAvail() const { assert(initialized == true); return cur_rbins_avail; }
@@ -274,6 +277,7 @@
   const tArray<int>& GetLastTaskCount() const { assert(initialized == true); return last_task_count; }
   const tArray<int>& GetLastInternalTaskCount() const { assert(initialized == true); return last_internal_task_count; }
   const tArray<double>& GetLastTaskQuality() const { assert(initialized == true); return last_task_quality; }
+  const tArray<double>& GetLastTaskValue() const { assert(intialized == true); return last_task_value; }
   const tArray<double>& GetLastInternalTaskQuality() const { assert(initialized == true); return last_internal_task_quality; }
   const tArray<double>& GetLastRBinsTotal() const { assert(initialized == true); return last_rbins_total; }
   const tArray<double>& GetLastRBinsAvail() const { assert(initialized == true); return last_rbins_avail; }

Modified: branches/collect/source/main/cPopulation.cc
===================================================================
--- branches/collect/source/main/cPopulation.cc	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/source/main/cPopulation.cc	2007-05-22 16:50:55 UTC (rev 1589)
@@ -280,7 +280,9 @@
     // Do lineage tracking for the new organisms.
     LineageSetupOrganism(child_array[i], parent_organism.GetLineage(),
                          parent_organism.GetLineageLabel(), parent_genotype);
-    
+		
+		//By default, store the parent cclade, this may get modified in ActivateOrgansim (@MRR)
+		child_array[i]->SetCCladeLabel(parent_organism.GetCCladeLabel());
   }
   
   
@@ -393,6 +395,8 @@
   environment.SetupInputs(ctx, target_cell.input_array);
   
   // Update the archive...
+	
+	
   in_genotype->AddOrganism();
   
   if (old_genotype != NULL) {
@@ -418,7 +422,10 @@
   // Statistics...
   m_world->GetStats().RecordBirth(target_cell.GetID(), in_genotype->GetID(),
                                   in_organism->GetPhenotype().ParentTrue());
-                                  
+	
+	// @MRR Do coalescence clade set up for new organisms.
+	CCladeSetupOrganism(in_organism ); 
+	
   //count how many times MERIT_BONUS_INST (rewarded instruction) is in the genome
   //only relevant if merit is proportional to # times MERIT_BONUS_INST is in the genome
   int rewarded_instruction = m_world->GetConfig().MERIT_BONUS_INST.Get();
@@ -1294,6 +1301,31 @@
 
 
 /**
+This function will set up coalescence clade information.  If this feature is activated in the configuration,
+ a list of coalescence genotype ids must be read in initially.  These are furnished by doing an initial run 
+ with the same seed and setup and retrieving information from the final dominant lineage and coalescence points.
+ 
+ The value is either (by default) inherited from the parent or the organism's genotypeID if it is known
+ to be a coalescence id.
+ 
+ Defaulting is established in Inject or ActivateOffspring methods of this class.
+ 
+ @MRR May 2007
+ **/
+void cPopulation::CCladeSetupOrganism(cOrganism* organism)
+{
+		int gen_id = organism->GetGenotype()->GetID();	
+		if (m_world->GetConfig().TRACK_CCLADES.Get() > 0)
+		{
+			if (m_world->GetClassificationManager().IsCCladeFounder(gen_id))
+			{	
+				organism->SetCCladeLabel(gen_id);
+			}
+		}
+}
+
+
+/**
 * This function directs which position function should be used.  It
  * could have also been done with a function pointer, but the dividing
  * of an organism takes enough time that this will be a negligible addition,
@@ -2265,6 +2297,9 @@
   cAvidaContext& ctx = m_world->GetDefaultContext();
   
   cOrganism* new_organism = new cOrganism(m_world, ctx, new_genotype->GetGenome());
+	
+	//Coalescense Clade Setup
+	new_organism->SetCCladeLabel(-1);  
   
   // Set the genotype...
   new_organism->SetGenotype(new_genotype);

Modified: branches/collect/source/main/cPopulation.h
===================================================================
--- branches/collect/source/main/cPopulation.h	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/source/main/cPopulation.h	2007-05-22 16:50:55 UTC (rev 1589)
@@ -131,7 +131,8 @@
   void InjectClone(int cell_id, cOrganism& orig_org);
 
   void LineageSetupOrganism(cOrganism* organism, cLineage* lineage, int lin_label, cGenotype* parent_genotype = NULL);
-
+	void CCladeSetupOrganism(cOrganism* organism); 
+	
   // Must be called to activate *any* organism in the population.
   void ActivateOrganism(cAvidaContext& ctx, cOrganism* in_organism, cPopulationCell& target_cell);
 

Modified: branches/collect/source/main/cReactionResult.cc
===================================================================
--- branches/collect/source/main/cReactionResult.cc	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/source/main/cReactionResult.cc	2007-05-22 16:50:55 UTC (rev 1589)
@@ -34,6 +34,7 @@
   , resources_detected(num_resources)
   , tasks_done(num_tasks)
   , tasks_quality(num_tasks)
+  , tasks_value(num_tasks)
   , reactions_triggered(num_reactions)
   , reaction_add_bonus(num_reactions)
   , bonus_add(0.0)
@@ -56,6 +57,7 @@
   resources_detected.SetAll(-1.0);
   tasks_done.SetAll(false);
   tasks_quality.SetAll(0.0);
+  tasks_value.SetAll(0.0);
   reactions_triggered.SetAll(false);
   reaction_add_bonus.SetAll(0.0);
 
@@ -91,11 +93,12 @@
  lethal = flag;
 }
 
-void cReactionResult::MarkTask(int id, const double quality)
+void cReactionResult::MarkTask(int id, const double quality, const double value)
 {
   ActivateReaction();
   tasks_done[id] = true;
   tasks_quality[id] = quality;
+  tasks_value[id] = value;
 }
 
 
@@ -168,3 +171,9 @@
 	return tasks_quality[id];
 }
 
+double cReactionResult::TaskValue(int id)
+{
+	if (GetActive() == false) return 0;
+	return tasks_value[id];
+}
+

Modified: branches/collect/source/main/cReactionResult.h
===================================================================
--- branches/collect/source/main/cReactionResult.h	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/source/main/cReactionResult.h	2007-05-22 16:50:55 UTC (rev 1589)
@@ -37,6 +37,7 @@
   tArray<double> resources_detected;  //Initialize to -1.0
   tArray<bool> tasks_done;
   tArray<double> tasks_quality;
+  tArray<double> tasks_value;
   tArray<bool> reactions_triggered;
   tArray<double> reaction_add_bonus; 
   double bonus_add;
@@ -62,7 +63,7 @@
   void Produce(int id, double num);
   void Detect(int id, double num);
   void Lethal(bool flag);
-  void MarkTask(int id, const double quality=1);
+  void MarkTask(int id, const double quality=1, const double value=0);
 
   void MarkReaction(int id);
   void AddBonus(double value, int id);
@@ -77,6 +78,7 @@
   bool ReactionTriggered(int id);
   bool TaskDone(int id);
   double TaskQuality(int id);
+  double TaskValue(int id);
   double GetAddBonus() { return bonus_add; }
   double GetReactionAddBonus(const int i) { return reaction_add_bonus[i]; }
   double GetMultBonus() { return bonus_mult; }

Modified: branches/collect/source/main/cTaskContext.h
===================================================================
--- branches/collect/source/main/cTaskContext.h	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/source/main/cTaskContext.h	2007-05-22 16:50:55 UTC (rev 1589)
@@ -55,7 +55,11 @@
   tBuffer<int>* m_received_messages;
   int m_logic_id;
   bool m_on_divide;
-  
+
+  // for optimize tasks actual value of function org is outputting, for all others nothing
+  // implemented for now...
+  double m_task_value;	
+
   cTaskEntry* m_task_entry;
   tHashTable<void*, cTaskState*>* m_task_states;
 
@@ -77,6 +81,7 @@
     , m_task_entry(NULL)
     , m_task_states(NULL)
   {
+	  m_task_value = 0;
   }
   
   inline int GetInputAt(int index) { return m_interface->GetInputAt(index); }
@@ -90,6 +95,8 @@
   inline int GetLogicId() const { return m_logic_id; }
   inline void SetLogicId(int v) { m_logic_id = v; }
   inline bool GetOnDivide() const { return m_on_divide; }
+  inline void SetTaskValue(double v) { m_task_value = v; }
+  inline double GetTaskValue() { return m_task_value; }
   
   inline void SetTaskEntry(cTaskEntry* in_entry) { m_task_entry = in_entry; }
   inline cTaskEntry* GetTaskEntry() { return m_task_entry; }

Modified: branches/collect/source/main/cTaskLib.cc
===================================================================
--- branches/collect/source/main/cTaskLib.cc	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/source/main/cTaskLib.cc	2007-05-22 16:50:55 UTC (rev 1589)
@@ -35,6 +35,7 @@
 #include <cstdlib>
 #include <cmath>
 #include <climits>
+#include <iomanip>
 
 // Various workarounds for Visual Studio shortcomings
 #if AVIDA_PLATFORM(WINDOWS)
@@ -347,7 +348,7 @@
 
    // Optimization Tasks
   if (name == "optimize")
-	  Load_Optimize(name, info, envreqs, errors);
+    Load_Optimize(name, info, envreqs, errors);
 
   if (name == "mult")
     Load_Mult(name, info, envreqs, errors);
@@ -371,13 +372,13 @@
   if (name == "comm_echo")
     NewTask(name, "Echo of Neighbor's Input", &cTaskLib::Task_CommEcho, REQ_NEIGHBOR_INPUT);
   else if (name == "comm_not")
-	  NewTask(name, "Not of Neighbor's Input", &cTaskLib::Task_CommNot, REQ_NEIGHBOR_INPUT);
+    NewTask(name, "Not of Neighbor's Input", &cTaskLib::Task_CommNot, REQ_NEIGHBOR_INPUT);
 
   // Network Tasks
   if (name == "net_send")
-	  NewTask(name, "Successfully Sent Network Message", &cTaskLib::Task_NetSend);
+    NewTask(name, "Successfully Sent Network Message", &cTaskLib::Task_NetSend);
   else if (name == "net_receive")
-	  NewTask(name, "Successfully Received Network Message", &cTaskLib::Task_NetReceive);
+    NewTask(name, "Successfully Received Network Message", &cTaskLib::Task_NetReceive);
   
   
   
@@ -1844,62 +1845,62 @@
 
 double cTaskLib::Task_MatchStr(cTaskContext& ctx) const
 {
-	tBuffer<int> temp_buf(ctx.GetOutputBuffer());
-	//	if (temp_buf[0] != 357913941) return 0;
+  tBuffer<int> temp_buf(ctx.GetOutputBuffer());
+  //  if (temp_buf[0] != 357913941) return 0;
 
-	//	temp_buf.Pop(); // pop the signal value off of the buffer
+  //  temp_buf.Pop(); // pop the signal value off of the buffer
 
-	const cString& string_to_match = ctx.GetTaskEntry()->GetArguments().GetString(0);
-	int string_index;
-	int num_matched = 0;
-	int test_output;
+  const cString& string_to_match = ctx.GetTaskEntry()->GetArguments().GetString(0);
+  int string_index;
+  int num_matched = 0;
+  int test_output;
   int max_num_matched = 0;
 
-	if (temp_buf.GetNumStored() > 0) {
-		test_output = temp_buf[0];
-	
-		for (int j = 0; j < string_to_match.GetSize(); j++) {	
-			string_index = string_to_match.GetSize() - j - 1; // start with last char in string
-			int k = 1 << j;
-			if ((string_to_match[string_index] == '0' && !(test_output & k)) ||
+  if (temp_buf.GetNumStored() > 0) {
+    test_output = temp_buf[0];
+  
+    for (int j = 0; j < string_to_match.GetSize(); j++) {  
+      string_index = string_to_match.GetSize() - j - 1; // start with last char in string
+      int k = 1 << j;
+      if ((string_to_match[string_index] == '0' && !(test_output & k)) ||
           (string_to_match[string_index] == '1' && (test_output & k))) num_matched++;
-		}
-		max_num_matched = num_matched;
-	}
+    }
+    max_num_matched = num_matched;
+  }
 
-	bool used_received = false;
-	if (ctx.GetReceivedMessages()) {
-		tBuffer<int> received(*(ctx.GetReceivedMessages()));
-		for (int i = 0; i < received.GetNumStored(); i++) {
-			test_output = received[i];
-			num_matched = 0;
-			
+  bool used_received = false;
+  if (ctx.GetReceivedMessages()) {
+    tBuffer<int> received(*(ctx.GetReceivedMessages()));
+    for (int i = 0; i < received.GetNumStored(); i++) {
+      test_output = received[i];
+      num_matched = 0;
+      
       for (int j = 0; j < string_to_match.GetSize(); j++) {
-				string_index = string_to_match.GetSize() - j - 1; // start with last char in string
-				int k = 1 << j;
-				if ((string_to_match[string_index]=='0' && !(test_output & k)) ||
+        string_index = string_to_match.GetSize() - j - 1; // start with last char in string
+        int k = 1 << j;
+        if ((string_to_match[string_index]=='0' && !(test_output & k)) ||
             (string_to_match[string_index]=='1' && (test_output & k))) num_matched++;
-			}
-			
+      }
+      
       if (num_matched > max_num_matched) {
-				max_num_matched = num_matched;
-				used_received = true;
-			}
-		}
-	}
+        max_num_matched = num_matched;
+        used_received = true;
+      }
+    }
+  }
 
-	double bonus = 0.0;
-	// return value between 0 & 1 representing the percentage of string that was matched
-	double base_bonus = static_cast<double>(max_num_matched) * 2.0 / static_cast<double>(string_to_match.GetSize()) - 1;
-	
-	if (base_bonus > 0.0) {
-		bonus = pow(base_bonus, 2);
-		if (used_received)
+  double bonus = 0.0;
+  // return value between 0 & 1 representing the percentage of string that was matched
+  double base_bonus = static_cast<double>(max_num_matched) * 2.0 / static_cast<double>(string_to_match.GetSize()) - 1;
+  
+  if (base_bonus > 0.0) {
+    bonus = pow(base_bonus, 2);
+    if (used_received)
       m_world->GetStats().AddMarketItemUsed();
-		else
-			m_world->GetStats().AddMarketOwnItemUsed();
-	}
-	return bonus;
+    else
+      m_world->GetStats().AddMarketOwnItemUsed();
+  }
+  return bonus;
 }
 
 
@@ -2116,115 +2117,132 @@
 
 void cTaskLib::Load_Optimize(const cString& name, const cString& argstr, cEnvReqs& envreqs, tList<cString>* errors)
 {
-	cArgSchema schema;
+  cArgSchema schema;
 
-	// Integer Arguments
-	schema.AddEntry("function", 0, cArgSchema::SCHEMA_INT);
-	schema.AddEntry("binary", 1, 0);
-	schema.AddEntry("varlength", 2, 8);
-	// Double Arguments
-	schema.AddEntry("basepow", 0, 2.0);
-	schema.AddEntry("max_Fx", 1, 1.0);
-	schema.AddEntry("min_Fx", 2, 0.0);
+  // Integer Arguments
+  schema.AddEntry("function", 0, cArgSchema::SCHEMA_INT);
+  schema.AddEntry("binary", 1, 0);
+  schema.AddEntry("varlength", 2, 8);
+  // Double Arguments
+  schema.AddEntry("basepow", 0, 2.0);
+  schema.AddEntry("maxFx", 1, 1.0);
+  schema.AddEntry("minFx", 2, 0.0);
 
 
-	cArgContainer* args = cArgContainer::Load(argstr, schema, errors);
-	if (args) 
-	{
-		if (args->GetInt(1))
-		{
-			envreqs.SetMinOutputs(args->GetInt(2)*2);
-		}
-		else 
-		{
-			// once have ability to change args should in each of these cases change the max/min
-			// to the appropriate defaults for this function
-			switch (args->GetInt(0))
-			{
-			case 1:
-				envreqs.SetMinOutputs(1);
-			case 2:
-				envreqs.SetMinOutputs(2);
-			case 3:
-				envreqs.SetMinOutputs(2);
-			};
-		}
+  cArgContainer* args = cArgContainer::Load(argstr, schema, errors);
+  if (args) 
+  {
+    if (args->GetInt(1))
+    {
+      envreqs.SetMinOutputs(args->GetInt(2)*2);
+    }
+    else 
+    {
+      // once have ability to change args should in each of these cases change the max/min
+      // to the appropriate defaults for this function
+      switch (args->GetInt(0))
+      {
+      case 1:
+        envreqs.SetMinOutputs(1);
+      case 2:
+        envreqs.SetMinOutputs(2);
+      case 3:
+        envreqs.SetMinOutputs(2);
+      };
+    }
 
-		NewTask(name, "Optimize", &cTaskLib::Task_Optimize, 0, args);
-	}
+    NewTask(name, "Optimize", &cTaskLib::Task_Optimize, 0, args);
+  }
 }
 
 double cTaskLib::Task_Optimize(cTaskContext& ctx) const
 {
-	// if the org hasn't output yet enough numbers, just return without completing any tasks
-	if (ctx.GetOutputBuffer().GetNumStored() < ctx.GetOutputBuffer().GetCapacity()) 
-		return 0;
+  // if the org hasn't output yet enough numbers, just return without completing any tasks
+  if (ctx.GetOutputBuffer().GetNumStored() < ctx.GetOutputBuffer().GetCapacity()) return 0;
 
-	double quality = 0.0;
+  double quality = 0.0;
 
-	// which function are we currently checking?
-	const int function = ctx.GetTaskEntry()->GetArguments().GetInt(0);
+  // which function are we currently checking?
+  const int function = ctx.GetTaskEntry()->GetArguments().GetInt(0);
 
-	 // always get x&y, at least for now, turn it into a double between 0 and 1
-	double y, x;
+   // always get x&y, at least for now, turn it into a double between 0 and 1
+  double y, x, Fx;
 
-	 const cArgContainer& args = ctx.GetTaskEntry()->GetArguments();
-	 if (args.GetInt(1))
-	 {
-		int len = args.GetInt(2);
-		double base_pow = args.GetDouble(0);
-		double tempX = 0, tempY=0, tot=0;
-		for (int i=len-1; i>=0; i--)
-		{
-			tempX += ctx.GetOutputBuffer()[i+len]*pow(base_pow,(len-1)-i);
-			tempY += ctx.GetOutputBuffer()[i]*pow(base_pow,(len-1)-i);
-			tot += pow(base_pow,i);
-		}
-		x = (double)tempX/tot;
-		y = (double)tempY/tot;
-	 }
-	 else
-	 {
-		x = (double)ctx.GetOutputBuffer()[0] / 0xffffffff;
-		y = (double)ctx.GetOutputBuffer()[1] / 0xffffffff;	
-	 }
+  const cArgContainer& args = ctx.GetTaskEntry()->GetArguments();
+  if (args.GetInt(1)) {
+    int len = args.GetInt(2);
+    double base_pow = args.GetDouble(0);
+    double tempX = 0, tempY = 0, tot = 0;
+    for (int i = len - 1; i >= 0; i--) {
+      tempX += ctx.GetOutputBuffer()[i + len] * pow(base_pow, (len - 1) - i);
+      tempY += ctx.GetOutputBuffer()[i] * pow(base_pow, (len - 1) - i);
+      tot += pow(base_pow, double(i));
+    }
+    x = tempX / tot;
+    y = tempY / tot;
+  } else {
+    x = abs(double(ctx.GetOutputBuffer()[0]) / 0xffffffff);
+    y = abs(double(ctx.GetOutputBuffer()[1]) / 0xffffffff);
+  }
 
-	 switch(function)
-	 {
-	 case 1:
-		 quality = 1 - x;
-		 break;
+  switch(function) {
+    case 1:
+	  Fx = x;		// F1
+      break;
 
-	 case 2:
-		 quality = 1 - ((1+y)*(1-sqrt(x/(1+y))))/2.0;	// F2
-		 break;
+    case 2:
+      Fx = (1.0 + y) * (1.0 - sqrt(x / (1.0 + y)));   // F2
+      break;
 
-	 case 3:
-		 quality = 1 - ((1+y)*(1-pow(x/(1+y),2)))/2.0;	// F3
-		 break;
+    case 3:
+      Fx = (1.0 + y) * (1.0 - pow(x / (1.0 + y), 2.0));  // F3
+      break;
 
-	 case 4:
-		 quality = 1 - (( (1+y)*(1 - sqrt(x/(1+y)) - (x/(1+y))*sin(3.14159*x*10) ) +.76) / 2.76);
-		 break;
+    case 4:
+      Fx = (1.0 + y) * (1.0 - sqrt(x / (1.0 + y)) - (x / (1.0 + y)) * sin(3.14159 * x * 10.0));
+	  break;
 
-	 default:
-		 quality = .001;
-	 }
+    case 5:
+      x = x * -2.0;
+      Fx = x*x + y*y;
+      break;
 
-	 // because want org to only have 1 shot to use outputs for all functions at once, even if they
-	 // output numbers that give a quality of 0 on a function, still want to mark it as completed
-	 // so give it a very low quality instead of 0 (if using limited resources they still will get
-	 // no reward because set the minimum consumed to max*.001, meaning even if they get the max
-	 // possible fraction they'll be below minimum allowed consumed and will consume nothing
+    case 6:
+      x = x * -2.0;
+      Fx = (x + 2.0)*(x + 2.0) + y*y;
+      break;
 
-	 if (quality > 1)
-		 cout << "\n\nquality > 1, wtf?!\n\n";
-	 if (quality < .001)
-		 return .001;
-	 else
-		 return quality;
+    case 7:
+      x = x * 4.0;
+      Fx = sqrt(x) + y;
+      break;
 
-	return 0;
+    case 8:
+      x = x * 4.0;
+      Fx = sqrt(4.0 - x) + y;
+      break;
+
+    default:
+      quality = .001;
+  }
+  ctx.SetTaskValue(Fx);
+  quality = (args.GetDouble(1) - Fx + .001) / (args.GetDouble(1) - args.GetDouble(2) + .001);
+  
+  // because want org to only have 1 shot to use outputs for all functions at once, even if they
+  // output numbers that give a quality of 0 on a function, still want to mark it as completed
+  // so give it a very low quality instead of 0 (if using limited resources they still will get
+  // no reward because set the minimum consumed to max*.001, meaning even if they get the max
+  // possible fraction they'll be below minimum allowed consumed and will consume nothing
+
+  if (quality > 1)
+    cout << "\n\nquality > 1!\n\n";
+  
+  if (quality < .001)
+    return .001;
+  else
+    return quality;
+
+  return 0;
 }
 
 void cTaskLib::Load_Mult(const cString& name, const cString& argstr, cEnvReqs& envreqs, tList<cString>* errors)

Modified: branches/collect/source/main/cWorld.cc
===================================================================
--- branches/collect/source/main/cWorld.cc	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/source/main/cWorld.cc	2007-05-22 16:50:55 UTC (rev 1589)
@@ -102,8 +102,11 @@
   for (int i = 0; i < inst_set.GetSize(); i++)
     m_stats->SetInstName(i, inst_set.GetName(i));
   
+  // @MRR CClade Tracking
+	if (m_conf->TRACK_CCLADES.Get() > 0)
+		m_class_mgr->LoadCCladeFounders(m_conf->TRACK_CCLADES_IDS.Get());
   
-  m_pop = new cPopulation(this);
+	m_pop = new cPopulation(this);
   
   // Setup Event List
   m_event_list = new cEventList(this);
@@ -112,6 +115,7 @@
     ExitAvida(-1);
   }
   
+	
   
   const bool revert_fatal = m_conf->REVERT_FATAL.Get() > 0.0;
   const bool revert_neg = m_conf->REVERT_DETRIMENTAL.Get() > 0.0;

Modified: branches/collect/source/targets/avida/primitive.cc
===================================================================
--- branches/collect/source/targets/avida/primitive.cc	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/source/targets/avida/primitive.cc	2007-05-22 16:50:55 UTC (rev 1589)
@@ -30,10 +30,14 @@
 #include "cDriverManager.h"
 #include "cWorld.h"
 
+#include "FloatingPoint.h"
+
 using namespace std;
 
 int main(int argc, char * argv[])
 {
+  SetupFloatingPointEnvironment();
+  
   // Catch Interrupt making sure to close appropriately
   signal(SIGINT, ExitAvida);
 

Modified: branches/collect/source/targets/avida-viewer/viewer.cc
===================================================================
--- branches/collect/source/targets/avida-viewer/viewer.cc	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/source/targets/avida-viewer/viewer.cc	2007-05-22 16:50:55 UTC (rev 1589)
@@ -30,10 +30,16 @@
 #include "cTextViewerDriver.h"
 #include "cWorld.h"
 
+#include "FloatingPoint.h"
+
 using namespace std;
 
+
 int main(int argc, char * argv[])
 {
+  SetupFloatingPointEnvironment();
+  
+  
   // Catch Interrupt making sure to close appropriately
   signal(SIGINT, ExitAvida);
 

Copied: branches/collect/source/targets/unit-tests (from rev 1587, development/source/targets/unit-tests)

Modified: branches/collect/support/config/avida.cfg
===================================================================
--- branches/collect/support/config/avida.cfg	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/support/config/avida.cfg	2007-05-22 16:50:55 UTC (rev 1589)
@@ -255,3 +255,8 @@
 MT_CONCURRENCY 1   # Number of concurrent analyze threads
 ANALYZE_OPTION_1   # String variable accessible from analysis scripts
 ANALYZE_OPTION_2   # String variable accessible from analysis scripts
+
+### SECOND_PASS_GROUP ###
+# Tracking metrics known after the running experiment previously
+TRACK_CCLADES 0                    # Enable tracking of coalescence clades
+TRACK_CCLADES_IDS coalescence.ids  # File storing coalescence IDs

Modified: branches/collect/support/config/default-gx.org
===================================================================
--- branches/collect/support/config/default-gx.org	2007-05-22 16:41:10 UTC (rev 1588)
+++ branches/collect/support/config/default-gx.org	2007-05-22 16:50:55 UTC (rev 1589)
@@ -1,20 +1,88 @@
-nop-A		# Origin of replication.
-nop-B		# Beginning of RNAP.
-match		# Attempt to match against a nop-B.
-  nop-B
-h-copy		# Copy from read-head to write-head (requires a match).
-on-da		# When the complement of nop-B is reached...
-  sever		# Sever the link between RNAP and it's transcription target.
-nop-C		# End of RNAP.
-nop-C		# ...
-nop-B		# Beginning of DNAP.
-match		# Attempt to match against a nop-A/nop-B.
+PROGRAMID
+READABLE
+BINDABLE
+site	# Origin of replication
+nop-A
+nop-B
+site	# Label and empty space
+nop-C
+nop-C
+nop-C
+nop-C
+nop-C
+nop-C
+nop-C
+nop-C
+nop-C
+nop-C
+site	# Start RNAP
+nop-B
+if-bind	# Move read head to site with matching label
+  nop-B    
+  p-alloc # If there was a match, then allocate another *executable* programid
+p-copy	# Copy the next instruction
+site 
+nop-C	# End of RNAP
+site	# Label and empty space
+nop-C
+nop-C
+nop-C
+nop-C
+nop-C
+nop-C
+nop-C
+nop-C
+nop-C
+nop-C
+site	# Start DNAP
+nop-B
+if-bind	# Move read head to matching site
   nop-A
   nop-B
-h-copy		# Copy from read-head to write-head (requires a match).
-on-da		# When the complement of nop-A/nop-B is reached...
-  h-divide	# Divide!
-nop-C		# End of DNAP.
-nop-C		# ...
-nop-B		# Replication terminator.
+  g-alloc # If there was a match, then allocate another *genome* programid
+p-copy	# Copy the next instruction
+site 
+nop-C	# End of DNAP
+site	# Site and empty space
 nop-C
+nop-C
+nop-C
+nop-C
+nop-C
+nop-C
+nop-C
+nop-C
+nop-C
+nop-C
+site
+nop-B	# Cell-cycle programid.  This programid is responsible for
+if-bind2 # locating two genomes and then triggering the divide process.
+  nop-B
+  nop-C
+  p-divide
+site
+nop-C	# End of cell-cycle programid..
+site	# Site and empty space.
+nop-C
+nop-C
+nop-C
+nop-C
+nop-C
+nop-C
+nop-C
+nop-C
+nop-C
+nop-C
+site
+nop-B
+nop-C
+PROGRAMID # This is the initial RNAP molecule
+EXECUTABLE
+site 
+nop-B
+if-bind	# Move read head to site with matching label
+  nop-B    
+  p-alloc # If there was a match, then allocate another *executable* programid
+p-copy	# Copy the next instruction
+site 
+nop-C

Copied: branches/collect/tests/_avida_GA_lim_res (from rev 1587, development/tests/_avida_GA_lim_res)

Copied: branches/collect/tests/_task_optimize_lim_res (from rev 1587, development/tests/_task_optimize_lim_res)

Copied: branches/collect/tests/string_match_embed3 (from rev 1587, development/tests/string_match_embed3)




More information about the Avida-cvs mailing list