[avida-cvs] avida CVS commits: /current/source/cpu 4stack_head.cc 4stack_head.hh Makefile.am code_label.cc code_label.hh cpu_defs.hh cpu_head.cc cpu_head.hh cpu_memory.cc cpu_memory.hh cpu_stack.cc cpu_stack.hh cpu_stats.hh cpu_test_info.cc cpu_test_info.hh hardware_4stack.cc hardware_4stack.hh hardware_4stack_constants.hh hardware_4stack_thread.cc hardware_4stack_thread.hh hardware_base.cc hardware_base.hh hardware_cpu.cc hardware_cpu.hh hardware_cpu_thread.cc hardware_cpu_thread.hh hardware_factory.cc hardware_factory.hh hardware_util.cc hardware_util.hh memory_flags.cc memory_flags.hh test_cpu.cc test_cpu.hh test_util.cc test_util.hh /current/source/event Makefile.am event.cc event.hh event_factory.cc event_factory.hh event_factory_manager.cc event_factory_manager.hh event_list.cc event_list.hh event_list_entry.cc event_list_entry.hh event_list_iterator.cc event_list_iterator.hh event_triggers.cc event_triggers.hh population_event.cc population_event.hh population_event_factory.cc population_event_factory.hh /current/source/main Makefile.am analyze.cc analyze.hh analyze_command.hh analyze_command_def.hh analyze_command_def_base.hh analyze_flow_command.hh analyze_flow_command_def.hh analyze_function.hh analyze_genotype.cc analyze_genotype.hh analyze_util.cc analyze_util.hh avida.cc avida.hh avida_driver_analyze.cc avida_driver_analyze.hh avida_driver_base.cc avida_driver_base.hh avida_driver_population.cc avida_driver_population.hh avida_triggers.hh birth_chamber.cc birth_chamber.hh callback_util.cc callback_util.hh config.cc config.hh environment.cc environment.hh fitness_matrix.cc fitness_matrix.hh genebank.cc genebank.hh genome.cc genome.hh genome_util.cc genome_util.hh genotype.cc genotype.hh genotype_batch.hh genotype_birth_data.cc genotype_birth_data.hh genotype_control.cc genotype_control.hh genotype_macros.hh genotype_test_data.cc genotype_test_data.hh inject_genebank.cc inject_genebank.hh inject_genebank_macros.hh inject_genotype.cc inject_genotype.hh inject_genotype_birth_data.cc inject_genotype_birth_data.hh inject_genotype_control.cc inject_genotype_control.hh inject_genotype_element.hh inject_genotype_queue.cc inject_genotype_queue.hh inst_lib_base.hh inst_set.cc inst_set.hh inst_util.cc inst_util.hh instruction.cc instruction.hh landscape.cc landscape.hh lineage.cc lineage.hh lineage_control.cc lineage_control.hh local_mutations.cc local_mutations.hh mutation.cc mutation.hh mutation_lib.cc mutation_lib.hh mutation_macros.hh mutation_rates.cc mutation_rates.hh mx_code_array.cc mx_code_array.hh my_code_array_less_than.hh org_message.cc org_message.hh organism.cc organism.hh phenotype.cc phenotype.hh population.cc population.hh population_cell.cc population_cell.hh population_interface.cc population_interface.hh primitive.cc primitive.hh reaction.cc reaction.hh reaction_lib.cc reaction_lib.hh reaction_macros.hh reaction_process.cc reaction_process.hh reaction_requisite.cc reaction_requisite.hh reaction_result.cc reaction_result.hh resource.cc resource.hh resource_count.cc resource_count.hh resource_count_macros.hh resource_lib.cc resource_lib.hh resource_macros.hh spatial_count_elem.cc spatial_count_elem.hh spatial_res_count.cc spatial_res_count.hh species.cc species.hh species_control.cc species_control.hh species_queue.cc species_queue.hh stats.cc stats.hh task_entry.cc task_entry.hh task_lib.cc task_lib.hh /current/source/testsuites Makefile.am /current/source/testsuites/functional_testsuites Makefile.am /current/source/testsuites/functional_testsuites/config unix.exp /current/source/testsuites/functional_testsuites/default.md5sum analyze.cfg environment.cfg events.cfg genesis inst_set.default md5sum.exp md5sum.sh organism.default /current/source/testsuites/functional_testsuites/default.tail analyze.cfg detail_pop.100.last_line.expected environment.cfg events.cfg genesis inst_set.default organism.default tail.exp tail.sh /current/source/testsuites/functional_testsuites/default.tail.disabled analyze.cfg environment.cfg events.cfg genesis inst_set.default organism.default tail.exp tail.sh /current/source/testsuites/functional_testsuites/tedious.tail.disabled analyze.cfg environment.cfg events.cfg genesis inst_set.default organism.default tail.exp tail.sh /current/source/testsuites/unit_testsuites 4stack_head.t.cc Makefile.am analyze.t.cc analyze_command.t.cc analyze_command_def.t.cc analyze_command_def_base.t.cc analyze_flow_command.t.cc analyze_flow_command_def.t.cc analyze_function.t.cc analyze_genotype.t.cc analyze_util.t.cc avida.t.cc avida_driver_analyze.t.cc avida_driver_base.t.cc avida_driver_population.t.cc avida_triggers.t.cc birth_chamber.t.cc block_struct.t.cc callback_util.t.cc config.t.cc const_schedule.t.cc cpu_head.t.cc cpu_memory.t.cc cpu_stack.t.cc cpu_test_info.t.cc data_entry.t.cc data_file.t.cc data_file_manager.t.cc data_manager_base.t.cc default_message_display.t.cc environment.t.cc event.t.cc event_factory.t.cc event_factory_manager.t.cc event_list.t.cc event_list_entry.t.cc event_list_iterator.t.cc file.t.cc fitness_matrix.t.cc fixed_coords.t.cc functions.t.cc genebank.t.cc genesis.t.cc genome.t.cc genome_util.t.cc genotype.t.cc genotype_batch.t.cc genotype_birth_data.t.cc genotype_control.t.cc hardware_4stack.t.cc hardware_4stack_thread.t.cc hardware_base.t.cc hardware_cpu.t.cc hardware_cpu_thread.t.cc hardware_factory.t.cc hardware_util.t.cc help_alias.t.cc help_entry.t.cc help_full_entry.t.cc help_manager.t.cc help_type.t.cc histogram.t.cc indexed_block_struct.t.cc init_file.t.cc inject_genebank.t.cc inject_genotype.t.cc inject_genotype_birth_data.t.cc inject_genotype_control.t.cc inject_genotype_element.t.cc inject_genotype_queue.t.cc inst_lib_base.t.cc inst_set.t.cc inst_util.t.cc integrated_schedule.t.cc integrated_schedule_node.t.cc landscape.t.cc lineage.t.cc lineage_control.t.cc local_mutations.t.cc message_class.t.cc message_closure.t.cc message_display.t.cc message_type.t.cc mutation.t.cc mutation_lib.t.cc mutation_rates.t.cc mx_code_array.t.cc my_code_array_less_than.t.cc org_message.t.cc organism.t.cc phenotype.t.cc population.t.cc population_cell.t.cc population_event.t.cc population_event_factory.t.cc population_interface.t.cc prob_schedule.t.cc random.t.cc reaction.t.cc reaction_lib.t.cc reaction_process.t.cc reaction_result.t.cc ref_block.t.cc resource.t.cc resource_count.t.cc resource_lib.t.cc running_average.t.cc scaled_block.t.cc schedule.t.cc spatial_count_elem.t.cc spatial_res_count.t.cc species.t.cc species_control.t.cc species_queue.t.cc stats.t.cc string.t.cc string_iterator.t.cc string_list.t.cc string_util.t.cc tArgDataEntry.t.cc tArray.t.cc tBuffer.t.cc tDataEntry.t.cc tDataEntryBase.t.cc tDataEntryCommand.t.cc tDataManager.t.cc tDictionary.t.cc tList.t.cc tMatrix.t.cc tVector.t.cc task_entry.t.cc task_lib.t.cc template.t.cc test_cpu.t.cc test_util.t.cc tools.t.cc uint.t.cc weighted_index.t.cc /current/source/testsuites/unit_testsuites/level_0 Makefile.am count_tracker.t.cc cpu_stats.t.cc double_sum.t.cc event_triggers.t.cc fixed_block.t.cc genotype_test_data.t.cc int_sum.t.cc memory_flags.t.cc merit.t.cc template.t.cc /current/source/testsuites/unit_testsuites/level_1 Makefile.am code_label.t.cc instruction.t.cc /current/source/tools Makefile.am block_struct.cc block_struct.hh const_schedule.cc const_schedule.hh count_tracker.cc count_tracker.hh data_entry.cc data_entry.hh data_file.cc data_file.hh data_file_manager.cc data_file_manager.hh data_manager_base.cc data_manager_base.hh default_message_display.cc default_message_display.hh double_sum.cc double_sum.hh file.cc file.hh fixed_block.cc fixed_block.hh fixed_coords.hh functions.hh genesis.cc genesis.hh help_alias.cc help_alias.hh help_entry.hh help_full_entry.hh help_manager.cc help_manager.hh help_type.cc help_type.hh histogram.cc histogram.hh indexed_block_struct.cc indexed_block_struct.hh init_file.cc init_file.hh int_sum.cc int_sum.hh integrated_schedule.cc integrated_schedule.hh integrated_schedule_node.cc integrated_schedule_node.hh merit.cc merit.hh message_class.hh message_closure.hh message_display.cc message_display.hh message_display_hdrs.hh message_type.hh prob_schedule.cc prob_schedule.hh random.cc random.hh ref_block.cc ref_block.hh running_average.cc running_average.hh scaled_block.cc scaled_block.hh schedule.cc schedule.hh string.cc string.hh string_iterator.cc string_iterator.hh string_list.cc string_list.hh string_util.cc string_util.hh tArgDataEntry.hh tArray.hh tBuffer.hh tDataEntry.hh tDataEntryBase.hh tDataEntryCommand.hh tDataManager.hh tDictionary.hh tList.hh tMatrix.hh tMemTrack.hh tVector.hh tools.cc tools.hh uint.hh weighted_index.cc weighted_index.hh win32_mkdir_hack.hh

kaben avida-cvs at alife.org
Tue Nov 25 17:38:06 PST 2003


kaben		Tue Nov 25 09:38:06 2003 EDT

  Added files:                 
    /avida/current/source/cpu	4stack_head.cc 4stack_head.hh 
                             	code_label.cc code_label.hh cpu_head.cc 
                             	cpu_head.hh cpu_test_info.cc 
                             	cpu_test_info.hh 
                             	hardware_4stack_constants.hh 
                             	hardware_4stack_thread.cc 
                             	hardware_4stack_thread.hh 
                             	hardware_cpu_thread.cc 
                             	hardware_cpu_thread.hh memory_flags.cc 
                             	memory_flags.hh 
    /avida/current/source/event	event_list_entry.cc event_list_entry.hh 
                               	event_list_iterator.cc 
                               	event_list_iterator.hh 
                               	event_triggers.cc event_triggers.hh 
                               	population_event.cc population_event.hh 
    /avida/current/source/main	analyze_command.hh 
                              	analyze_command_def.hh 
                              	analyze_command_def_base.hh 
                              	analyze_flow_command.hh 
                              	analyze_flow_command_def.hh 
                              	analyze_function.hh analyze_genotype.cc 
                              	analyze_genotype.hh 
                              	avida_driver_analyze.cc 
                              	avida_driver_analyze.hh 
                              	avida_driver_base.cc 
                              	avida_driver_base.hh 
                              	avida_driver_population.cc 
                              	avida_driver_population.hh 
                              	avida_triggers.hh genotype_batch.hh 
                              	genotype_birth_data.cc 
                              	genotype_birth_data.hh 
                              	genotype_control.cc genotype_control.hh 
                              	genotype_macros.hh genotype_test_data.cc 
                              	genotype_test_data.hh 
                              	inject_genebank_macros.hh 
                              	inject_genotype_birth_data.cc 
                              	inject_genotype_birth_data.hh 
                              	inject_genotype_control.cc 
                              	inject_genotype_control.hh 
                              	inject_genotype_element.hh 
                              	inject_genotype_queue.cc 
                              	inject_genotype_queue.hh 
                              	inst_lib_base.hh instruction.cc 
                              	instruction.hh local_mutations.cc 
                              	local_mutations.hh mutation.cc 
                              	mutation.hh mutation_lib.cc 
                              	mutation_lib.hh mutation_macros.hh 
                              	mutation_rates.cc mutation_rates.hh 
                              	mx_code_array.cc mx_code_array.hh 
                              	my_code_array_less_than.hh 
                              	population_interface.cc 
                              	population_interface.hh primitive.hh 
                              	reaction_lib.cc reaction_lib.hh 
                              	reaction_macros.hh reaction_process.cc 
                              	reaction_process.hh 
                              	reaction_requisite.cc 
                              	reaction_requisite.hh 
                              	resource_count_macros.hh resource_lib.cc 
                              	resource_lib.hh resource_macros.hh 
                              	spatial_count_elem.cc 
                              	spatial_count_elem.hh 
                              	spatial_res_count.cc 
                              	spatial_res_count.hh species_control.cc 
                              	species_control.hh species_queue.cc 
                              	species_queue.hh task_entry.cc 
                              	task_entry.hh task_lib.cc task_lib.hh 
    /avida/current/source/testsuites	Makefile.am 
    /avida/current/source/testsuites/functional_testsuites	Makefile.am 
    /avida/current/source/testsuites/functional_testsuites/config	
                                                                 	unix.exp 
    /avida/current/source/testsuites/functional_testsuites/default.md5sum	
                                                                         	analyze.cfg 
                                                                         	environment.cfg 
                                                                         	events.cfg 
                                                                         	genesis 
                                                                         	inst_set.default 
                                                                         	md5sum.exp 
                                                                         	md5sum.sh 
                                                                         	organism.default 
    /avida/current/source/testsuites/functional_testsuites/default.tail	
                                                                       	analyze.cfg 
                                                                       	detail_pop.100.last_line.expected 
                                                                       	environment.cfg 
                                                                       	events.cfg 
                                                                       	genesis 
                                                                       	inst_set.default 
                                                                       	organism.default 
                                                                       	tail.exp 
                                                                       	tail.sh 
    /avida/current/source/testsuites/functional_testsuites/default.tail.disabled	
                                                                                	analyze.cfg 
                                                                                	environment.cfg 
                                                                                	events.cfg 
                                                                                	genesis 
                                                                                	inst_set.default 
                                                                                	organism.default 
                                                                                	tail.exp 
                                                                                	tail.sh 
    /avida/current/source/testsuites/functional_testsuites/tedious.tail.disabled	
                                                                                	analyze.cfg 
                                                                                	environment.cfg 
                                                                                	events.cfg 
                                                                                	genesis 
                                                                                	inst_set.default 
                                                                                	organism.default 
                                                                                	tail.exp 
                                                                                	tail.sh 
    /avida/current/source/testsuites/unit_testsuites	4stack_head.t.cc 
                                                    	Makefile.am 
                                                    	analyze.t.cc 
                                                    	analyze_command.t.cc 
                                                    	analyze_command_def.t.cc 
                                                    	analyze_command_def_base.t.cc 
                                                    	analyze_flow_command.t.cc 
                                                    	analyze_flow_command_def.t.cc 
                                                    	analyze_function.t.cc 
                                                    	analyze_genotype.t.cc 
                                                    	analyze_util.t.cc 
                                                    	avida.t.cc 
                                                    	avida_driver_analyze.t.cc 
                                                    	avida_driver_base.t.cc 
                                                    	avida_driver_population.t.cc 
                                                    	avida_triggers.t.cc 
                                                    	birth_chamber.t.cc 
                                                    	block_struct.t.cc 
                                                    	callback_util.t.cc 
                                                    	config.t.cc 
                                                    	const_schedule.t.cc 
                                                    	cpu_head.t.cc 
                                                    	cpu_memory.t.cc 
                                                    	cpu_stack.t.cc 
                                                    	cpu_test_info.t.cc 
                                                    	data_entry.t.cc 
                                                    	data_file.t.cc 
                                                    	data_file_manager.t.cc 
                                                    	data_manager_base.t.cc 
                                                    	default_message_display.t.cc 
                                                    	environment.t.cc 
                                                    	event.t.cc 
                                                    	event_factory.t.cc 
                                                    	event_factory_manager.t.cc 
                                                    	event_list.t.cc 
                                                    	event_list_entry.t.cc 
                                                    	event_list_iterator.t.cc 
                                                    	file.t.cc 
                                                    	fitness_matrix.t.cc 
                                                    	fixed_coords.t.cc 
                                                    	functions.t.cc 
                                                    	genebank.t.cc 
                                                    	genesis.t.cc 
                                                    	genome.t.cc 
                                                    	genome_util.t.cc 
                                                    	genotype.t.cc 
                                                    	genotype_batch.t.cc 
                                                    	genotype_birth_data.t.cc 
                                                    	genotype_control.t.cc 
                                                    	hardware_4stack.t.cc 
                                                    	hardware_4stack_thread.t.cc 
                                                    	hardware_base.t.cc 
                                                    	hardware_cpu.t.cc 
                                                    	hardware_cpu_thread.t.cc 
                                                    	hardware_factory.t.cc 
                                                    	hardware_util.t.cc 
                                                    	help_alias.t.cc 
                                                    	help_entry.t.cc 
                                                    	help_full_entry.t.cc 
                                                    	help_manager.t.cc 
                                                    	help_type.t.cc 
                                                    	histogram.t.cc 
                                                    	indexed_block_struct.t.cc 
                                                    	init_file.t.cc 
                                                    	inject_genebank.t.cc 
                                                    	inject_genotype.t.cc 
                                                    	inject_genotype_birth_data.t.cc 
                                                    	inject_genotype_control.t.cc 
                                                    	inject_genotype_element.t.cc 
                                                    	inject_genotype_queue.t.cc 
                                                    	inst_lib_base.t.cc 
                                                    	inst_set.t.cc 
                                                    	inst_util.t.cc 
                                                    	integrated_schedule.t.cc 
                                                    	integrated_schedule_node.t.cc 
                                                    	landscape.t.cc 
                                                    	lineage.t.cc 
                                                    	lineage_control.t.cc 
                                                    	local_mutations.t.cc 
                                                    	message_class.t.cc 
                                                    	message_closure.t.cc 
                                                    	message_display.t.cc 
                                                    	message_type.t.cc 
                                                    	mutation.t.cc 
                                                    	mutation_lib.t.cc 
                                                    	mutation_rates.t.cc 
                                                    	mx_code_array.t.cc 
                                                    	my_code_array_less_than.t.cc 
                                                    	org_message.t.cc 
                                                    	organism.t.cc 
                                                    	phenotype.t.cc 
                                                    	population.t.cc 
                                                    	population_cell.t.cc 
                                                    	population_event.t.cc 
                                                    	population_event_factory.t.cc 
                                                    	population_interface.t.cc 
                                                    	prob_schedule.t.cc 
                                                    	random.t.cc 
                                                    	reaction.t.cc 
                                                    	reaction_lib.t.cc 
                                                    	reaction_process.t.cc 
                                                    	reaction_result.t.cc 
                                                    	ref_block.t.cc 
                                                    	resource.t.cc 
                                                    	resource_count.t.cc 
                                                    	resource_lib.t.cc 
                                                    	running_average.t.cc 
                                                    	scaled_block.t.cc 
                                                    	schedule.t.cc 
                                                    	spatial_count_elem.t.cc 
                                                    	spatial_res_count.t.cc 
                                                    	species.t.cc 
                                                    	species_control.t.cc 
                                                    	species_queue.t.cc 
                                                    	stats.t.cc 
                                                    	string.t.cc 
                                                    	string_iterator.t.cc 
                                                    	string_list.t.cc 
                                                    	string_util.t.cc 
                                                    	tArgDataEntry.t.cc 
                                                    	tArray.t.cc 
                                                    	tBuffer.t.cc 
                                                    	tDataEntry.t.cc 
                                                    	tDataEntryBase.t.cc 
                                                    	tDataEntryCommand.t.cc 
                                                    	tDataManager.t.cc 
                                                    	tDictionary.t.cc 
                                                    	tList.t.cc 
                                                    	tMatrix.t.cc 
                                                    	tVector.t.cc 
                                                    	task_entry.t.cc 
                                                    	task_lib.t.cc 
                                                    	template.t.cc 
                                                    	test_cpu.t.cc 
                                                    	test_util.t.cc 
                                                    	tools.t.cc 
                                                    	uint.t.cc 
                                                    	weighted_index.t.cc 
    /avida/current/source/testsuites/unit_testsuites/level_0	
                                                            	Makefile.am 
                                                            	count_tracker.t.cc 
                                                            	cpu_stats.t.cc 
                                                            	double_sum.t.cc 
                                                            	event_triggers.t.cc 
                                                            	fixed_block.t.cc 
                                                            	genotype_test_data.t.cc 
                                                            	int_sum.t.cc 
                                                            	memory_flags.t.cc 
                                                            	merit.t.cc 
                                                            	template.t.cc 
    /avida/current/source/testsuites/unit_testsuites/level_1	
                                                            	Makefile.am 
                                                            	code_label.t.cc 
                                                            	instruction.t.cc 
    /avida/current/source/tools	const_schedule.cc const_schedule.hh 
                               	count_tracker.cc count_tracker.hh 
                               	data_file.cc data_file.hh 
                               	data_file_manager.cc 
                               	data_file_manager.hh 
                               	data_manager_base.cc 
                               	data_manager_base.hh 
                               	default_message_display.cc 
                               	default_message_display.hh 
                               	double_sum.cc double_sum.hh 
                               	fixed_block.cc fixed_block.hh 
                               	fixed_coords.hh genesis.cc genesis.hh 
                               	help_alias.cc help_alias.hh 
                               	help_entry.hh help_full_entry.hh 
                               	help_manager.cc help_manager.hh 
                               	help_type.cc help_type.hh histogram.cc 
                               	histogram.hh indexed_block_struct.cc 
                               	indexed_block_struct.hh init_file.cc 
                               	init_file.hh int_sum.cc int_sum.hh 
                               	integrated_schedule.cc 
                               	integrated_schedule.hh 
                               	integrated_schedule_node.cc 
                               	integrated_schedule_node.hh 
                               	message_class.hh message_closure.hh 
                               	message_type.hh prob_schedule.cc 
                               	prob_schedule.hh ref_block.cc 
                               	ref_block.hh running_average.cc 
                               	running_average.hh scaled_block.cc 
                               	scaled_block.hh schedule.cc schedule.hh 
                               	string_iterator.cc string_iterator.hh 
                               	tArgDataEntry.hh tDataEntry.hh 
                               	tDataEntryBase.hh tDataEntryCommand.hh 
                               	tDataManager.hh uint.hh 

  Modified files:              
    /avida/current/source/cpu	cpu_defs.hh cpu_memory.cc cpu_memory.hh 
                             	cpu_stack.cc cpu_stack.hh cpu_stats.hh 
                             	hardware_4stack.cc hardware_4stack.hh 
                             	hardware_base.cc hardware_base.hh 
                             	hardware_cpu.cc hardware_cpu.hh 
                             	hardware_factory.cc hardware_factory.hh 
                             	hardware_util.cc hardware_util.hh 
                             	test_cpu.cc test_cpu.hh test_util.cc 
                             	test_util.hh Makefile.am 
    /avida/current/source/event	event.cc event.hh event_factory.cc 
                               	event_factory.hh 
                               	event_factory_manager.cc 
                               	event_factory_manager.hh event_list.cc 
                               	event_list.hh 
                               	population_event_factory.cc 
                               	population_event_factory.hh Makefile.am 
    /avida/current/source/main	analyze.cc analyze.hh analyze_util.cc 
                              	analyze_util.hh avida.cc avida.hh 
                              	birth_chamber.cc birth_chamber.hh 
                              	callback_util.cc callback_util.hh 
                              	config.cc config.hh environment.cc 
                              	environment.hh fitness_matrix.cc 
                              	fitness_matrix.hh genebank.cc 
                              	genebank.hh genome.cc genome.hh 
                              	genome_util.cc genome_util.hh 
                              	genotype.cc genotype.hh 
                              	inject_genebank.cc inject_genebank.hh 
                              	inject_genotype.cc inject_genotype.hh 
                              	inst_set.cc inst_set.hh inst_util.cc 
                              	inst_util.hh landscape.cc landscape.hh 
                              	lineage.cc lineage.hh lineage_control.cc 
                              	lineage_control.hh org_message.cc 
                              	org_message.hh organism.cc organism.hh 
                              	phenotype.cc phenotype.hh population.cc 
                              	population.hh population_cell.cc 
                              	population_cell.hh primitive.cc 
                              	reaction.cc reaction.hh 
                              	reaction_result.cc reaction_result.hh 
                              	resource.cc resource.hh 
                              	resource_count.cc resource_count.hh 
                              	species.cc species.hh stats.cc stats.hh 
                              	Makefile.am 
    /avida/current/source/tools	block_struct.cc block_struct.hh 
                               	data_entry.cc data_entry.hh file.cc 
                               	file.hh functions.hh merit.cc merit.hh 
                               	message_display.cc message_display.hh 
                               	message_display_hdrs.hh random.cc 
                               	random.hh string.cc string.hh 
                               	string_list.cc string_list.hh 
                               	string_util.cc string_util.hh tArray.hh 
                               	tBuffer.hh tDictionary.hh tList.hh 
                               	tMatrix.hh tMemTrack.hh tVector.hh 
                               	tools.cc tools.hh weighted_index.cc 
                               	weighted_index.hh win32_mkdir_hack.hh 
                               	Makefile.am 
  Log:
  
  In process of constructing version 2.0b9.
  - added new set of source code files to cpu, event, main, tools 
    subdirectories.
  - removed testsuites from beneath main subdirectory.
  - added testsuites beneath source subdirectory.
  - added new set of unit testsuites beneath testsuites/unit_testsuites,
    including subdirectories level_0 and level_1.  These last two are
    being used to order execution of unit testsuites according to
    levelization of the files/classes they test.
  
  
  
-------------- next part --------------
Index: avida/current/source/cpu/cpu_defs.hh
diff -u /dev/null avida/current/source/cpu/cpu_defs.hh:1.13
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/cpu/cpu_defs.hh	Tue Nov 25 09:37:54 2003
@@ -0,0 +1,69 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          // 
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef CPU_DEFS_HH
+#define CPU_DEFS_HH
+
+#define TEST_CPU_GENERATIONS 3  // Default generations tested for viability.
+
+#define MAX_TEST_DEPTH       10  // Maximum number of generations tested
+
+//#define FITNESS_NEUTRAL_RANGE (1.0/3600.0)
+#define FITNESS_NEUTRAL_RANGE (0.0)
+#define FITNESS_NEUTRAL_MIN (1.0 - FITNESS_NEUTRAL_RANGE)
+#define FITNESS_NEUTRAL_MAX (1.0 + FITNESS_NEUTRAL_RANGE)
+
+
+// The following defines setup the structure of the CPU.  Changing them
+// (especially the number of registers) could have effects in other parts
+// of the code!
+
+#define MAX_NOPS 4
+#define MAX_LABEL_SIZE 10 
+#define REG_AX 0
+#define REG_BX 1
+#define REG_CX 2
+#define REG_DX 3
+#define NUM_REGISTERS 3
+#define NUM_REG_4STACK 4
+
+
+#define HEAD_IP     0
+#define HEAD_READ   1
+#define HEAD_WRITE  2
+#define HEAD_FLOW   3
+#define NUM_HEADS   4
+
+
+#define STACK_SIZE 10
+#define IO_SIZE 3
+
+#define GEN_RESOURCE   0
+#define NUM_RESOURCES  1
+
+#define FAULT_TYPE_WARNING 0
+#define FAULT_TYPE_ERROR   1
+
+#define FAULT_TYPE_FORK_TH 0
+#define FAULT_TYPE_KILL_TH 0
+
+// Fault locations in CPU executions...
+#define FAULT_LOC_DEFAULT      0
+#define FAULT_LOC_INSTRUCTION  1
+#define FAULT_LOC_JUMP         2
+#define FAULT_LOC_MATH         3
+#define FAULT_LOC_INJECT       4
+#define FAULT_LOC_THREAD_FORK  5
+#define FAULT_LOC_THREAD_KILL  6
+#define FAULT_LOC_ALLOC        7
+#define FAULT_LOC_DIVIDE       8
+#define FAULT_LOC_BCOPY        9
+
+class cInstSet;		// defined in inst_set.hh
+
+#endif
Index: avida/current/source/cpu/cpu_memory.cc
diff -u /dev/null avida/current/source/cpu/cpu_memory.cc:1.12
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/cpu/cpu_memory.cc	Tue Nov 25 09:37:54 2003
@@ -0,0 +1,227 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef CPU_MEMORY_HH
+#include "cpu_memory.hh"
+#endif
+
+using namespace std;
+
+const double MEMORY_INCREASE_FACTOR = 1.5;
+const double MEMORY_SHRINK_TEST_FACTOR = 4.0;
+
+////////////////
+//  cCPUMemory
+////////////////
+
+cCPUMemory::cCPUMemory(int _size) : cGenome(_size), flag_array(_size)
+{
+}
+
+cCPUMemory::cCPUMemory(const cCPUMemory & in_memory)
+  : cGenome(in_memory), flag_array(in_memory.GetSize())
+{
+  for (int i = 0; i < flag_array.GetSize(); i++) {
+    flag_array[i] = in_memory.flag_array[i];
+  }
+}
+
+cCPUMemory::cCPUMemory(const cGenome & in_genome)
+  : cGenome(in_genome), flag_array(in_genome.GetSize())
+{
+}
+
+cCPUMemory::cCPUMemory(const cString & in_string)
+  : cGenome(in_string), flag_array(in_string.GetSize())
+{
+}
+
+cCPUMemory::~cCPUMemory()
+{
+}
+
+
+// ---  Private Methods ---
+
+void cCPUMemory::SloppyResize(int new_size)
+{
+  assert(new_size > 0);
+
+  // Make sure we're really changing the size...
+  if (new_size == active_size) return;
+
+  const int array_size = genome.GetSize();
+
+  // Determine if we need to adjust the allocated array sizes...
+  if (new_size > array_size ||
+      new_size * MEMORY_SHRINK_TEST_FACTOR < array_size) {
+    const int new_array_size = (int) (new_size * MEMORY_INCREASE_FACTOR);
+    genome.Resize(new_array_size);
+    flag_array.Resize(new_array_size);
+  }
+  
+  // And just change the active_size once we're sure it will be in range.
+  active_size = new_size;
+}
+
+
+void cCPUMemory::SloppyInsert(int pos, int num_lines)
+{
+  assert(pos >= 0 && pos <= active_size); // Must insert at a legal position!
+  assert(num_lines > 0);  // Must insert positive number of lines!
+
+  // Re-adjust the size...
+  const int old_size = active_size;
+  const int new_size = active_size + num_lines;
+  SloppyResize(new_size);
+
+  // Shift any lines needed...
+  for (int i = old_size - 1; i >= pos; i--) {
+    genome[i+num_lines] = genome[i];
+    flag_array[i+num_lines] = flag_array[i];
+  }
+}
+
+
+// ---  Public Methods ---
+
+
+void cCPUMemory::operator=(const cCPUMemory & other_memory)
+{
+  SloppyResize(other_memory.active_size);
+
+  // Fill in the new information...
+  for (int i = 0; i < active_size; i++) {
+    genome[i] = other_memory.genome[i];
+    flag_array[i] = other_memory.flag_array[i];
+  }
+}
+
+
+void cCPUMemory::operator=(const cGenome & other_genome)
+{
+  SloppyResize(other_genome.GetSize());
+
+  // Fill in the new information...
+  for (int i = 0; i < active_size; i++) {
+    genome[i] = other_genome[i];
+    flag_array[i].Clear();
+  }
+}
+
+void cCPUMemory::Copy(int to, int from)
+{
+  assert(to >= 0);
+  assert(to < genome.GetSize());
+  assert(from >= 0);
+  assert(from < genome.GetSize());
+
+  genome[to] = genome[from];
+  flag_array[to] = flag_array[from];
+}
+
+void cCPUMemory::Clear()
+{
+  for (int i = 0; i < active_size; i++) {
+    genome[i].SetOp(0);
+    flag_array[i].Clear();
+  }
+}
+
+void cCPUMemory::ClearFlags()
+{
+  for (int i = 0; i < active_size; i++) flag_array[i].Clear();
+}
+
+void cCPUMemory::Reset(int new_size)
+{
+  assert(new_size >= 0);
+
+  SloppyResize(new_size);
+  Clear();
+}
+
+
+void cCPUMemory::Resize(int new_size)
+{
+  assert(new_size >= 0);
+
+  // Do a sloppy resize first, saving old values...
+  const int old_size = active_size;
+  const int old_array_size = genome.GetSize();
+  SloppyResize(new_size);
+  
+  // Clean up all of the old memory that might need it...
+  for (int i = old_size; i < new_size && i < old_array_size; i++) {
+    genome[i].SetOp(0);
+    flag_array[i].Clear();
+  }
+}
+
+
+void cCPUMemory::ResizeOld(int new_size)
+{
+  assert(new_size >= 0);
+
+  // Do a sloppy resize, which will still have old values.
+  SloppyResize(new_size);
+}
+
+
+void cCPUMemory::Insert(int pos, const cInstruction & in_inst)
+{
+  assert(pos >= 0);
+  assert(pos <= genome.GetSize());
+
+  SloppyInsert(pos, 1);
+  genome[pos] = in_inst;
+  flag_array[pos].Clear();
+}
+
+void cCPUMemory::Insert(int pos, const cGenome & in_genome)
+{
+  assert(pos >= 0);
+  assert(pos <= genome.GetSize());
+
+  SloppyInsert(pos, in_genome.GetSize());
+  for (int i = 0; i < in_genome.GetSize(); i++) {
+    genome[i+pos] = in_genome[i];
+    flag_array[i+pos].Clear();
+  }
+}
+
+void cCPUMemory::Remove(int pos, int num_insts)
+{
+  assert(num_insts > 0);                  // Must remove something...
+  assert(pos >= 0);                       // Removal must be in genome.
+  assert(pos + num_insts <= active_size); // Cannot extend past end of genome.
+
+  const int new_size = active_size - num_insts;
+  for (int i = pos; i < new_size; i++) {
+    genome[i] = genome[i + num_insts];
+    flag_array[i] = flag_array[i + num_insts];
+  }
+  SloppyResize(new_size);
+}
+
+void cCPUMemory::Replace(int pos, int num_insts, const cGenome & in_genome)
+{
+  assert(pos >= 0);                       // Replace must be in genome.
+  assert(num_insts >= 0);                 // Cannot replace negative.
+  assert(pos + num_insts <= active_size); // Cannot extend past end!
+
+  const int size_change = in_genome.GetSize() - num_insts;
+
+  // First, get the size right.
+  if (size_change > 0) SloppyInsert(pos, size_change);
+  else if (size_change < 0) Remove(pos, -size_change);
+
+  // Now just copy everything over!
+  for (int i = 0; i < in_genome.GetSize(); i++) {
+    genome[i + pos] = in_genome[i];
+  }
+}
Index: avida/current/source/cpu/cpu_memory.hh
diff -u /dev/null avida/current/source/cpu/cpu_memory.hh:1.7
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/cpu/cpu_memory.hh	Tue Nov 25 09:37:54 2003
@@ -0,0 +1,74 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef CPU_MEMORY_HH
+#define CPU_MEMORY_HH
+
+#ifndef GENOME_HH
+#include "genome.hh"
+#endif
+#ifndef TARRAY_HH
+#include "tArray.hh"
+#endif
+#ifndef MEMORY_FLAGS_HH
+#include "memory_flags.hh"
+#endif
+
+class cGenome;
+class cInstruction;
+class cMemoryFlags; // access
+class cString;
+template <class T> class tArray; // aggregate
+
+class cCPUMemory : public cGenome {
+private:
+  tArray<cMemoryFlags> flag_array;
+
+  // A collection of sloppy instructions to perform oft-used functions that
+  // will need to be cleaned up after this is run.
+  void SloppyResize(int new_size);           // Set size, ignore new contents.
+  void SloppyInsert(int pos, int num_lines); // Add lines, ignore new contents.
+public:
+  explicit cCPUMemory(int _size=1);
+  cCPUMemory(const cCPUMemory & in_memory);
+  cCPUMemory(const cGenome & in_genome);
+  cCPUMemory(const cString & in_string);
+  ~cCPUMemory();
+
+  void operator=(const cCPUMemory & other_memory);
+  void operator=(const cGenome & other_genome);
+  void Copy(int to, int from);
+
+  void Clear();
+  void ClearFlags();
+  void Reset(int new_size);     // Reset size, clearing contents...
+  void Resize(int new_size);    // Reset size, save contents, init to default
+  void ResizeOld(int new_size); // Reset size, save contents, init to previous
+
+  bool FlagCopied(int pos) const     { return flag_array[pos].copied; }
+  bool FlagMutated(int pos) const    { return flag_array[pos].mutated; }
+  bool FlagExecuted(int pos) const   { return flag_array[pos].executed; }
+  bool FlagBreakpoint(int pos) const { return flag_array[pos].breakpoint; }
+  bool FlagPointMut(int pos) const   { return flag_array[pos].point_mut; }
+  bool FlagCopyMut(int pos) const    { return flag_array[pos].copy_mut; }
+  bool FlagInjected(int pos) const   { return flag_array[pos].injected; }
+
+  bool & FlagCopied(int pos)     { return flag_array[pos].copied; }
+  bool & FlagMutated(int pos)    { return flag_array[pos].mutated; }
+  bool & FlagExecuted(int pos)   { return flag_array[pos].executed; }
+  bool & FlagBreakpoint(int pos) { return flag_array[pos].breakpoint; }
+  bool & FlagPointMut(int pos)   { return flag_array[pos].point_mut; }
+  bool & FlagCopyMut(int pos)    { return flag_array[pos].copy_mut; }
+  bool & FlagInjected(int pos)   { return flag_array[pos].injected; }
+
+  void Insert(int pos, const cInstruction & in_inst);
+  void Insert(int pos, const cGenome & in_genome);
+  void Remove(int pos, int num_insts=1);
+  void Replace(int pos, int num_insts, const cGenome & in_genome);
+};
+
+#endif
Index: avida/current/source/cpu/cpu_stack.cc
diff -u /dev/null avida/current/source/cpu/cpu_stack.cc:1.7
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/cpu/cpu_stack.cc	Tue Nov 25 09:37:54 2003
@@ -0,0 +1,77 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#include "cpu_stack.hh"
+
+#include <assert.h>
+#include "string.hh"
+
+using namespace std;
+
+
+cCPUStack::cCPUStack()
+{
+  Clear();
+}
+
+cCPUStack::cCPUStack(const cCPUStack & in_stack)
+{
+  for (int i = 0; i < STACK_SIZE; i++) {
+    stack[i] = in_stack.stack[i];
+  }
+  stack_pointer = in_stack.stack_pointer;
+}
+
+cCPUStack::~cCPUStack()
+{
+}
+
+void cCPUStack::operator=(const cCPUStack & in_stack)
+{
+  for (int i = 0; i < STACK_SIZE; i++) {
+    stack[i] = in_stack.stack[i];
+  }
+  stack_pointer = in_stack.stack_pointer;
+}
+
+void cCPUStack::Flip()
+{
+  int new_stack[STACK_SIZE];
+  int i;
+  for (i = 0; i < STACK_SIZE; i++) new_stack[i] = Pop();
+  for (i = 0; i < STACK_SIZE; i++) Push(new_stack[i]);
+}
+
+bool cCPUStack::OK()
+{
+  assert(stack_pointer < STACK_SIZE); // stack_pointer out of range
+  return true;
+}
+
+void cCPUStack::SaveState(ostream & fp)
+{
+  assert(fp.good());
+  fp<<"cCPUStack"<<" ";
+  // stack (in inverse order so load can just push)
+  for(int i = STACK_SIZE - 1; i >= 0; i-- ){
+    fp<<Get(i)<<" ";
+  }
+  fp<<endl;
+}
+
+void cCPUStack::LoadState(istream & fp)
+{
+  assert(fp.good());
+  cString foo;
+  fp>>foo;
+  assert( foo == "cCPUStack");
+  int value;
+  for( int i=0; i<STACK_SIZE; ++i ){
+    fp>>value;
+    Push(value);
+  }
+}
Index: avida/current/source/cpu/cpu_stack.hh
diff -u /dev/null avida/current/source/cpu/cpu_stack.hh:1.7
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/cpu/cpu_stack.hh	Tue Nov 25 09:37:54 2003
@@ -0,0 +1,82 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef CPU_STACK_HH
+#define CPU_STACK_HH
+
+#include <iostream>
+
+#ifndef CPU_DEFS_HH
+#include "cpu_defs.hh"
+#endif
+
+/**
+ * A CPU stack, used by various hardware components.
+ *
+ * @see cCPUThread, cCPUHead, cHardware
+ **/
+
+class cCPUStack {
+private:
+  int stack[STACK_SIZE];
+  unsigned char stack_pointer;
+public:
+  cCPUStack();
+  cCPUStack(const cCPUStack & in_stack);
+  ~cCPUStack();
+
+  void operator=(const cCPUStack & in_stack);
+
+  inline void Push(int value);
+  inline int Pop();
+  inline int Get(int depth=0) const;
+  inline void Clear();
+  inline int Top();
+  void Flip();
+
+  bool OK();
+
+  void SaveState(std::ostream & fp);
+  void LoadState(std::istream & fp);
+};
+
+
+inline void cCPUStack::Push(int value)
+{
+  if (stack_pointer == 0) stack_pointer = STACK_SIZE - 1;
+  else stack_pointer--;
+  stack[stack_pointer] = value;
+}
+
+inline int cCPUStack::Pop()
+{
+  int value = stack[stack_pointer];
+  stack[stack_pointer] = 0;
+  stack_pointer++;
+  if (stack_pointer == STACK_SIZE) stack_pointer = 0;
+  return value;
+}
+
+inline int cCPUStack::Get(int depth) const
+{
+  int array_pos = depth + stack_pointer;
+  if (array_pos >= STACK_SIZE) array_pos -= STACK_SIZE;
+  return stack[array_pos];
+}
+
+inline void cCPUStack::Clear()
+{
+  for (int i =0; i < STACK_SIZE; i++) { stack[i] = 0; }
+  stack_pointer = 0;
+}
+
+inline int cCPUStack::Top()
+{
+  return stack[stack_pointer];
+}
+
+#endif
Index: avida/current/source/cpu/cpu_stats.hh
diff -u /dev/null avida/current/source/cpu/cpu_stats.hh:1.11
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/cpu/cpu_stats.hh	Tue Nov 25 09:37:54 2003
@@ -0,0 +1,67 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef CPU_STATS_HH
+#define CPU_STATS_HH
+
+/**
+ * Class to facilitate passing information from CPU to Stats.
+ **/
+
+class sCPUStats {
+public:
+  class sMutationStats {
+  public:
+    // Counts of mutations INHERITED FROM PARENT
+    int point_mut_count;
+    int copy_mut_count;
+    int insert_mut_count;
+    int delete_mut_count;
+    int div_mut_count;
+    // Counts of Mutated _Lines_
+    int point_mut_line_count;   // In PARENT
+    int parent_mut_line_count;  // In PARENT
+    int copy_mut_line_count;    // In CHILD
+    // Theses happen by divide, so they should be 0 or 1
+    int divide_mut_count;
+    int divide_insert_mut_count;
+    int divide_delete_mut_count;
+    // Other info needed for mutation calculations
+    int copies_exec;
+
+    void Clear() {
+      point_mut_count = 0;
+      copy_mut_count = 0;
+      insert_mut_count = 0;
+      point_mut_line_count = 0;
+      parent_mut_line_count = 0;
+      copy_mut_line_count = 0;
+      delete_mut_count = 0;
+      div_mut_count=0;
+      divide_mut_count = 0;
+      divide_insert_mut_count = 0;
+      divide_delete_mut_count = 0;
+      copies_exec = 0;
+    }
+  };
+
+
+  // Contiually Set
+  sMutationStats mut_stats;
+
+
+  void Setup(int num_instructions) {
+    (void) num_instructions;
+    mut_stats.Clear();
+  }
+
+  void Clear() {  // Called on any New Creature
+    mut_stats.Clear();
+  }
+};
+
+#endif
Index: avida/current/source/cpu/hardware_4stack.cc
diff -u /dev/null avida/current/source/cpu/hardware_4stack.cc:1.15
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/cpu/hardware_4stack.cc	Tue Nov 25 09:37:54 2003
@@ -0,0 +1,2285 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef HARDWARE_4STACK_HH
+#include "hardware_4stack.hh"
+#endif
+
+#ifndef CONFIG_HH
+#include "config.hh"
+#endif
+#ifndef CPU_TEST_INFO_HH
+#include "cpu_test_info.hh"
+#endif
+#ifndef FUNCTIONS_HH
+#include "functions.hh"
+#endif
+#ifndef GENOME_UTIL_HH
+#include "genome_util.hh"
+#endif
+#ifndef INST_LIB_BASE_HH
+#include "inst_lib_base.hh"
+#endif
+#ifndef INST_SET_HH
+#include "inst_set.hh"
+#endif
+#ifndef MUTATION_HH
+#include "mutation.hh"
+#endif
+#ifndef MUTATION_LIB_HH
+#include "mutation_lib.hh"
+#endif
+#ifndef MUTATION_MACROS_HH
+#include "mutation_macros.hh"
+#endif
+#ifndef ORGANISM_HH
+#include "organism.hh"
+#endif
+#ifndef PHENOTYPE_HH
+#include "phenotype.hh"
+#endif
+#ifndef RANDOM_HH
+#include "random.hh"
+#endif
+#ifndef STRING_UTIL_HH
+#include "string_util.hh"
+#endif
+#ifndef TEST_CPU_HH
+#include "test_cpu.hh"
+#endif
+
+#include <limits.h>
+
+using namespace std;
+
+
+
+
+///////////////
+//  cInstLib4Stack
+///////////////
+
+class cInstLib4Stack : public cInstLibBase {
+  const size_t m_nopmods_array_size;
+  const size_t m_function_array_size;
+  cString *m_nopmod_names;
+  cString *m_function_names;
+  const int *m_nopmods;
+  cHardware4Stack::tHardware4StackMethod *m_functions;
+  static const cInstruction inst_error;
+  static const cInstruction inst_default;
+public:
+  cInstLib4Stack(
+    size_t nopmod_array_size,
+    size_t function_array_size,
+    cString *nopmod_names,
+    cString *function_names,
+    const int *nopmods,
+    cHardware4Stack::tHardware4StackMethod *functions
+  ):m_nopmods_array_size(nopmod_array_size),
+    m_function_array_size(function_array_size),
+    m_nopmod_names(nopmod_names),
+    m_function_names(function_names),
+    m_nopmods(nopmods),
+    m_functions(functions)
+  {}
+  cHardware4Stack::tHardware4StackMethod *GetFunctions(void){ return m_functions; } 
+  const cString &GetName(const unsigned int id) {
+    assert(id < m_function_array_size);
+    return m_function_names[id];
+  }
+  const cString &GetNopName(const unsigned int id) {
+    assert(id < m_nopmods_array_size);
+    return m_nopmod_names[id];
+  }
+  int GetNopMod(const unsigned int id){
+    assert(id < m_nopmods_array_size);
+    return m_nopmods[id];
+  }
+  int GetNopMod(const cInstruction & inst){
+    return GetNopMod(inst.GetOp());
+  }
+  int GetSize(){ return m_function_array_size; }
+  int GetNumNops(){ return m_nopmods_array_size; }
+  cInstruction GetInst(const cString & in_name){
+    for (unsigned int i = 0; i < m_function_array_size; i++) {
+      if (m_function_names[i] == in_name) return cInstruction(i);
+    }
+    return cInstLib4Stack::GetInstError();
+  }
+  const cInstruction & GetInstDefault(){ return inst_default; }
+  const cInstruction & GetInstError(){ return inst_error; }
+};
+
+///////////////
+//  cHardware4Stack
+///////////////
+
+const cInstruction cInstLib4Stack::inst_error(255);
+const cInstruction cInstLib4Stack::inst_default(0);
+cInstLibBase *cHardware4Stack::GetInstLib(){ return s_inst_slib; }
+
+cInstLib4Stack *cHardware4Stack::s_inst_slib = cHardware4Stack::initInstLib();
+cInstLib4Stack *cHardware4Stack::initInstLib(void){
+  struct cNOPEntry4Stack {
+    cNOPEntry4Stack(const cString &name, int nop_mod):name(name), nop_mod(nop_mod){}
+    cString name;
+    int nop_mod;
+  };
+  static const cNOPEntry4Stack s_n_array[] = {
+    cNOPEntry4Stack("Nop-A", STACK_AX),
+    cNOPEntry4Stack("Nop-B", STACK_BX),
+    cNOPEntry4Stack("Nop-C", STACK_CX),
+    cNOPEntry4Stack("Nop-D", STACK_DX),
+  };
+
+  struct cInstEntry4Stack {
+    cInstEntry4Stack(const cString &name, tHardware4StackMethod function):name(name), function(function){}
+    cString name;
+    tHardware4StackMethod function;
+  };
+  static const cInstEntry4Stack s_f_array[] = {
+    //1 
+    cInstEntry4Stack("Nop-A",     &cHardware4Stack::Inst_Nop), 
+    //2
+    cInstEntry4Stack("Nop-B",     &cHardware4Stack::Inst_Nop), 
+    //3
+    cInstEntry4Stack("Nop-C",     &cHardware4Stack::Inst_Nop),   
+    //4 
+    cInstEntry4Stack("Nop-D",     &cHardware4Stack::Inst_Nop), 
+    //5
+    cInstEntry4Stack("Nop-X",     &cHardware4Stack::Inst_Nop),
+    //6 
+    cInstEntry4Stack("Val-Shift-R",   &cHardware4Stack::Inst_ShiftR),
+    //7
+    cInstEntry4Stack("Val-Shift-L",   &cHardware4Stack::Inst_ShiftL),
+    //8
+    cInstEntry4Stack("Val-Nand",      &cHardware4Stack::Inst_Val_Nand),
+    //9
+    cInstEntry4Stack("Val-Add",       &cHardware4Stack::Inst_Val_Add),
+    //10
+    cInstEntry4Stack("Val-Sub",       &cHardware4Stack::Inst_Val_Sub),
+    //11
+    cInstEntry4Stack("Val-Mult",      &cHardware4Stack::Inst_Val_Mult),
+    //12
+    cInstEntry4Stack("Val-Div",       &cHardware4Stack::Inst_Val_Div),
+    //13
+    cInstEntry4Stack("SetMemory",   &cHardware4Stack::Inst_SetMemory),
+    //14
+    cInstEntry4Stack("Divide",  &cHardware4Stack::Inst_Divide),
+    //15
+    cInstEntry4Stack("Inst-Read",    &cHardware4Stack::Inst_HeadRead),
+    //16
+    cInstEntry4Stack("Inst-Write",   &cHardware4Stack::Inst_HeadWrite),
+    //keeping this one for the transition period
+    //cInstEntry4Stack("Inst-Copy",    &cHardware4Stack::Inst_HeadCopy),
+    //17
+    cInstEntry4Stack("If-Equal",    &cHardware4Stack::Inst_IfEqual),
+    //18
+    cInstEntry4Stack("If-Not-Equal",  &cHardware4Stack::Inst_IfNotEqual),
+    //19
+    cInstEntry4Stack("If-Less",   &cHardware4Stack::Inst_IfLess),
+    //20
+    cInstEntry4Stack("If-Greater",    &cHardware4Stack::Inst_IfGreater),
+    //21
+    cInstEntry4Stack("Head-Push",    &cHardware4Stack::Inst_HeadPush),
+    //22
+    cInstEntry4Stack("Head-Pop",     &cHardware4Stack::Inst_HeadPop),
+    //23
+    cInstEntry4Stack("Head-Move",  &cHardware4Stack::Inst_HeadMove),
+    //24
+    cInstEntry4Stack("Search",  &cHardware4Stack::Inst_Search),
+    //25
+    cInstEntry4Stack("Push-Next",    &cHardware4Stack::Inst_PushNext),
+    //26
+    cInstEntry4Stack("Push-Prev",    &cHardware4Stack::Inst_PushPrevious),
+    //27
+    cInstEntry4Stack("Push-Comp",    &cHardware4Stack::Inst_PushComplement),
+    //28
+    cInstEntry4Stack("Val-Delete", &cHardware4Stack::Inst_ValDelete),
+    //29
+    cInstEntry4Stack("Val-Copy",  &cHardware4Stack::Inst_ValCopy),
+    //30
+    cInstEntry4Stack("ThreadFork",   &cHardware4Stack::Inst_ForkThread),
+    //31
+    //cInstEntry4Stack("if-label",  &cHardware4Stack::Inst_IfLabel),
+    //32
+    cInstEntry4Stack("Val-Inc",       &cHardware4Stack::Inst_Increment),
+    //33
+    cInstEntry4Stack("Val-Dec",       &cHardware4Stack::Inst_Decrement),
+    //34
+    cInstEntry4Stack("Val-Mod",       &cHardware4Stack::Inst_Mod),
+    //35
+    cInstEntry4Stack("ThreadKill",   &cHardware4Stack::Inst_KillThread),
+    //36
+    cInstEntry4Stack("IO", &cHardware4Stack::Inst_IO),
+    //37
+    cInstEntry4Stack("Inject", &cHardware4Stack::Inst_Inject)
+  };
+
+  const int n_size = sizeof(s_n_array)/sizeof(cNOPEntry4Stack);
+
+  cout << "Instruction Library has " << n_size << " instructions." << endl;
+
+  static cString n_names[n_size];
+  static int nop_mods[n_size];
+  for (int i = 0; i < n_size; i++){
+    n_names[i] = s_n_array[i].name;
+    nop_mods[i] = s_n_array[i].nop_mod;
+  }
+
+  const int f_size = sizeof(s_f_array)/sizeof(cInstEntry4Stack);
+  static cString f_names[f_size];
+  static tHardware4StackMethod functions[f_size];
+  for (int i = 0; i < f_size; i++){
+    f_names[i] = s_f_array[i].name;
+    functions[i] = s_f_array[i].function;
+  }
+
+  cInstLib4Stack *inst_lib = new cInstLib4Stack(
+    n_size,
+    f_size,
+    n_names,
+    f_names,
+    nop_mods,
+    functions
+  );
+
+  cout <<
+  "<cHardware4Stack::initInstLib> debug: important post-init values:" <<endl<<
+  " --- GetSize(): " << inst_lib->GetSize() <<endl<<
+  " --- GetNumNops(): " << inst_lib->GetNumNops() <<endl<<
+  " --- GetName(last): " <<
+  inst_lib->GetName(inst_lib->GetSize() - 1) <<endl<<
+  endl;
+
+  return inst_lib;
+}
+
+cHardware4Stack::cHardware4Stack(cOrganism * in_organism, cInstSet * in_inst_set)
+  : cHardwareBase(in_organism, in_inst_set)
+  , memory_array(NUM_MEMORY_SPACES)
+{
+  /* FIXME:  reorganize storage of m_functions.  -- kgn */
+  m_functions = s_inst_slib->GetFunctions();
+  /**/
+  inst_remainder = 0;
+ 
+  for(int x=1; x<=cConfig::GetMaxCPUThreads(); x++)
+    {
+      slice_array[x] = (x-1)*cConfig::GetThreadSlicingMethod()+1;
+    }
+
+  memory_array[0] = in_organism->GetGenome();  // Initialize memory...
+  memory_array[0].Resize(GetMemory(0).GetSize()+1);
+  memory_array[0][memory_array[0].GetSize()-1] = cInstruction();
+  Reset();                            // Setup the rest of the hardware...
+}
+
+
+cHardware4Stack::~cHardware4Stack()
+{
+}
+
+
+void cHardware4Stack::Recycle(cOrganism * new_organism, cInstSet * in_inst_set)
+{
+  cHardwareBase::Recycle(new_organism, in_inst_set);
+  memory_array[0] = new_organism->GetGenome();
+  memory_array[0].Resize(GetMemory(0).GetSize()+1);
+  memory_array[0][memory_array[0].GetSize()-1] = cInstruction();
+  Reset();
+}
+
+
+void cHardware4Stack::Reset()
+{
+  //global_stack.Clear();
+  //thread_time_used = 0;
+
+  // Setup the memory...
+  for (int i = 1; i < NUM_MEMORY_SPACES; i++) {
+      memory_array[i].Resize(1);
+      //GetMemory(i).Replace(0, 1, cGenome(ConvertToInstruction(i)));
+      GetMemory(i)=cGenome(ConvertToInstruction(i)); 
+  }
+
+  // We want to reset to have a single thread.
+  threads.Resize(1);
+
+  // Reset that single thread.
+  threads[0].Reset(this, 0);
+  thread_id_chart = 1; // Mark only the first thread as taken...
+  cur_thread = 0;
+
+  mal_active = false;
+
+  // Reset all stacks (local and global)
+  for(int i=0; i<NUM_STACKS; i++)
+    {
+      Stack(i).Clear();
+    }
+
+#ifdef INSTRUCTION_COSTS
+  // instruction cost arrays
+  const int num_inst_cost = GetNumInst();
+  inst_cost.Resize(num_inst_cost);
+  inst_ft_cost.Resize(num_inst_cost);
+
+  for (int i = 0; i < num_inst_cost; i++) {
+    inst_cost[i] = GetInstSet().GetCost(cInstruction(i));
+    inst_ft_cost[i] = GetInstSet().GetFTCost(cInstruction(i));
+  }
+#endif
+
+}
+
+// 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.
+
+void cHardware4Stack::SingleProcess(ostream * trace_fp)
+{
+  organism->GetPhenotype().IncTimeUsed();
+  //if(organism->GetCellID()==46 && IP().GetMemSpace()==2)
+  // int x=0;
+
+  //if (GetNumThreads() > 1) thread_time_used++;
+  //assert((GetHead(HEAD_WRITE).GetPosition() == Stack(STACK_BX).Top() ||
+  // Stack(STACK_BX).Top()==GetMemory(IP().GetMemSpace()).GetSize()-1 || 
+  // GetHead(HEAD_WRITE).GetPosition() == Stack(STACK_BX).Top()+1) &&
+  // (GetHead(HEAD_WRITE).GetMemSpace() == IP().GetMemSpace() ||
+  //  GetHead(HEAD_WRITE).GetMemSpace() == IP().GetMemSpace()+1));
+  // If we have threads turned on and we executed each thread in a single
+  // timestep, adjust the number of instructions executed accordingly.
+  //const int num_inst_exec = (cConfig::GetThreadSlicingMethod() == 1) ?
+  //  GetNumThreads() : 1;
+
+  const int num_inst_exec = int(slice_array[GetNumThreads()]+ inst_remainder);
+  inst_remainder = slice_array[GetNumThreads()] + inst_remainder - num_inst_exec;
+  
+  for (int i = 0; i < num_inst_exec; i++) {
+    // Setup the hardware for the next instruction to be executed.
+    NextThread();
+    AdvanceIP() = true;
+    IP().Adjust();
+
+#ifdef BREAKPOINTS
+    if (IP().FlagBreakpoint() == true) {
+      organism->DoBreakpoint();
+    }
+#endif
+    
+    // Print the status of this CPU at each step...
+    if (trace_fp != NULL) organism->PrintStatus(*trace_fp);
+    
+    // Find the instruction to be executed
+    const cInstruction & cur_inst = IP().GetInst();
+
+    // Test if costs have been paid and it is okay to execute this now...
+    const bool exec = SingleProcess_PayCosts(cur_inst);
+
+    // Now execute the instruction...
+    if (exec == true) {
+      SingleProcess_ExecuteInst(cur_inst);
+
+      // Some instruction (such as jump) may turn advance_ip off.  Ususally
+      // we now want to move to the next instruction in the memory.
+      if (AdvanceIP() == true) IP().Advance();
+    } // if exec
+    
+  } // Previous was executed once for each thread...
+
+  // Kill creatures who have reached their max num of instructions executed
+  const int max_executed = organism->GetMaxExecuted();
+  if ( max_executed > 0 &&
+       organism->GetPhenotype().GetTimeUsed() >= max_executed ) {
+    organism->Die();
+  }
+}
+
+// This method will test to see if all costs have been paid associated
+// with executing an instruction and only return true when that instruction
+// should proceed.
+bool cHardware4Stack::SingleProcess_PayCosts(const cInstruction & cur_inst)
+{
+#ifdef INSTRUCTION_COSTS
+  assert(cur_inst.GetOp() < inst_cost.GetSize());
+
+  // If first time cost hasn't been paid off...
+  if ( inst_ft_cost[cur_inst.GetOp()] > 0 ) {
+    inst_ft_cost[cur_inst.GetOp()]--;       // dec cost
+    return false;
+  }
+    
+  // Next, look at the per use cost
+  if ( GetInstSet().GetCost(cur_inst) > 0 ) {
+    if ( inst_cost[cur_inst.GetOp()] > 1 ){  // if isn't paid off (>1)
+      inst_cost[cur_inst.GetOp()]--;         // dec cost
+      return false;
+    } else {                                 // else, reset cost array
+      inst_cost[cur_inst.GetOp()] = GetInstSet().GetCost(cur_inst);
+    }
+  }
+    
+  // Prob of exec
+  if ( GetInstSet().GetProbFail(cur_inst) > 0.0 ){
+    return !( g_random.P(GetInstSet().GetProbFail(cur_inst)) );
+  }
+#endif
+  return true;
+}
+
+// This method will handle the actuall execution of an instruction
+// within single process, once that function has been finalized.
+bool cHardware4Stack::SingleProcess_ExecuteInst(const cInstruction & cur_inst) 
+{
+  // Get a pointer to the corrisponding method...
+  int inst_idx = GetInstSet().GetLibFunctionIndex(cur_inst);
+      
+  // Mark the instruction as executed
+  IP().FlagExecuted() = true;
+	
+#ifdef EXECUTION_ERRORS
+  // If there is an execution error, execute a random instruction.
+  if (organism->TestExeErr()) inst_idx = GetInstSet().GetRandFunctionIndex();
+#endif /* EXECUTION_ERRORS */
+	
+#ifdef INSTRUCTION_COUNT
+  // instruction execution count incremeneted
+  organism->GetPhenotype().IncCurInstCount(cur_inst.GetOp());
+#endif
+	
+  // And execute it.
+  const bool exec_success = (this->*(m_functions[inst_idx]))();
+	
+#ifdef INSTRUCTION_COUNT
+  // decremenet if the instruction was not executed successfully
+  if (exec_success == false) {
+    organism->GetPhenotype().DecCurInstCount(cur_inst.GetOp());
+  }
+#endif	
+
+  return exec_success;
+}
+
+
+
+void cHardware4Stack::LoadGenome(const cGenome & new_genome)
+{
+  GetMemory(0) = new_genome;
+}
+
+
+bool cHardware4Stack::OK()
+{
+  bool result = true;
+
+  for(int i = 0 ; i < NUM_MEMORY_SPACES; i++) {
+    if (!memory_array[i].OK()) result = false;
+  }
+
+  for (int i = 0; i < GetNumThreads(); i++) {
+    assert (threads[i].input_pointer < IO_SIZE);
+
+    for(int j=0; j<NUM_LOCAL_STACKS; j++)
+    if (threads[i].local_stacks[j].OK() == false) result = false;
+    if (threads[i].next_label.OK() == false) result = false;
+  }
+
+  return result;
+}
+
+void cHardware4Stack::PrintStatus(ostream & fp)
+{
+  fp << organism->GetPhenotype().GetTimeUsed() << " "
+     << "IP:(" << IP().GetMemSpace() << ", " << IP().GetPosition() << ")    "
+
+     << "AX:" << Stack(STACK_AX).Top() << " "
+     << setbase(16) << "[0x" << Stack(STACK_AX).Top() << "]  " << setbase(10)
+
+     << "BX:" << Stack(STACK_BX).Top() << " "
+     << setbase(16) << "[0x" << Stack(STACK_BX).Top() << "]  " << setbase(10)
+
+     << "CX:" << Stack(STACK_CX).Top() << " "
+     << setbase(16) << "[0x" << Stack(STACK_CX).Top() << "]  " << setbase(10)
+
+     << "DX:" << Stack(STACK_DX).Top() << " "
+     << setbase(16) << "[0x" << Stack(STACK_DX).Top() << "]  " << setbase(10)
+
+     << endl;
+
+  fp << "  R-Head:(" << GetHead(HEAD_READ).GetMemSpace() << ", " 
+     << GetHead(HEAD_READ).GetPosition() << ")  " 
+     << "W-Head:(" << GetHead(HEAD_WRITE).GetMemSpace()  << ", "
+     << GetHead(HEAD_WRITE).GetPosition() << ")  "
+     << "F-Head:(" << GetHead(HEAD_FLOW).GetMemSpace()   << ",  "
+     << GetHead(HEAD_FLOW).GetPosition() << ")  "
+     << "RL:" << GetReadLabel().AsString() << "   "
+     << "NEXT: >> " << inst_set->GetName(IP().GetInst())() << " <<"
+     << endl;
+
+  fp << "  Mem (" << GetMemory(0).GetSize() << "):"
+		  << "  " << GetMemory(0).AsString()
+		  << endl;
+  fp << "       " << GetMemory(1).GetSize() << "):"
+		  << "  " << GetMemory(1).AsString()
+		  << endl;
+  fp << "       " << GetMemory(2).GetSize() << "):"
+		  << "  " << GetMemory(2).AsString()
+		  << endl;
+  fp << "       " << GetMemory(3).GetSize() << "):"
+		  << "  " << GetMemory(3).AsString()
+		  << endl;
+  
+  
+  fp.flush();
+}
+
+
+void cHardware4Stack::DoInput(const int value)
+{
+  organism->DoInput(value, GetInputBuffer(), GetOutputBuffer());
+}
+
+void cHardware4Stack::DoOutput(const int value)
+{
+  organism->DoOutput(value, GetInputBuffer(), GetOutputBuffer());
+}
+
+
+
+
+/////////////////////////////////////////////////////////////////////////
+// Method: cHardware4Stack::FindLabel(direction)
+//
+// Search in 'direction' (+ or - 1) from the instruction pointer for the
+// compliment of the label in 'next_label' and return a pointer to the
+// results.  If direction is 0, search from the beginning of the genome.
+//
+/////////////////////////////////////////////////////////////////////////
+
+c4StackHead cHardware4Stack::FindLabel(int direction)
+{
+  c4StackHead & inst_ptr = IP();
+
+  // Start up a search head at the position of the instruction pointer.
+  c4StackHead search_head(inst_ptr);
+  cCodeLabel & search_label = GetLabel();
+
+  // Make sure the label is of size  > 0.
+
+  if (search_label.GetSize() == 0) {
+    return inst_ptr;
+  }
+
+  // Call special functions depending on if jump is forwards or backwards.
+  int found_pos = 0;
+  if( direction < 0 ) {
+    found_pos = FindLabel_Backward(search_label, inst_ptr.GetMemory(),
+			   inst_ptr.GetPosition() - search_label.GetSize());
+  }
+
+  // Jump forward.
+  else if (direction > 0) {
+    found_pos = FindLabel_Forward(search_label, inst_ptr.GetMemory(),
+			   inst_ptr.GetPosition());
+  }
+
+  // Jump forward from the very beginning.
+  else {
+    found_pos = FindLabel_Forward(search_label, inst_ptr.GetMemory(), 0);
+  }
+  
+  // Return the last line of the found label, if it was found.
+  if (found_pos > 0) search_head.Set(found_pos - 1, IP().GetMemSpace());
+  //*** I THINK THIS MIGHT HAVE BEEN WRONG...CHANGED >= to >.  -law ***//
+  
+  // Return the found position (still at start point if not found).
+  return search_head;
+}
+
+
+// Search forwards for search_label from _after_ position pos in the
+// memory.  Return the first line _after_ the the found label.  It is okay
+// to find search label's match inside another label.
+
+int cHardware4Stack::FindLabel_Forward(const cCodeLabel & search_label,
+				 const cGenome & search_genome, int pos)
+{
+  assert (pos < search_genome.GetSize() && pos >= 0);
+
+  int search_start = pos;
+  int label_size = search_label.GetSize();
+  bool found_label = false;
+
+  // Move off the template we are on.
+  pos += label_size;
+
+  // Search until we find the complement or exit the memory.
+  while (pos < search_genome.GetSize()) {
+
+    // If we are within a label, rewind to the beginning of it and see if
+    // it has the proper sub-label that we're looking for.
+
+    if (inst_set->IsNop(search_genome[pos])) {
+      // Find the start and end of the label we're in the middle of.
+
+      int start_pos = pos;
+      int end_pos = pos + 1;
+      while (start_pos > search_start &&
+	     inst_set->IsNop( search_genome[start_pos - 1] )) {
+	start_pos--;
+      }
+      while (end_pos < search_genome.GetSize() &&
+	     inst_set->IsNop( search_genome[end_pos] )) {
+	end_pos++;
+      }
+      int test_size = end_pos - start_pos;
+
+      // See if this label has the proper sub-label within it.
+      int max_offset = test_size - label_size + 1;
+      int offset = start_pos;
+      for (offset = start_pos; offset < start_pos + max_offset; offset++) {
+
+	// Test the number of matches for this offset.
+	int matches;
+	for (matches = 0; matches < label_size; matches++) {
+	  if (search_label[matches] !=
+	      inst_set->GetNopMod( search_genome[offset + matches] )) {
+	    break;
+	  }
+	}
+
+	// If we have found it, break out of this loop!
+	if (matches == label_size) {
+	  found_label = true;
+	  break;
+	}
+      }
+
+      // If we've found the complement label, set the position to the end of
+      // the label we found it in, and break out.
+
+      if (found_label == true) {
+	// pos = end_pos;
+	pos = label_size + offset;
+	break;
+      }
+
+      // We haven't found it; jump pos to just after the current label being
+      // checked.
+      pos = end_pos;
+    }
+
+    // Jump up a block to the next possible point to find a label,
+    pos += label_size;
+  }
+
+  // If the label was not found return a -1.
+  if (found_label == false) pos = -1;
+
+  return pos;
+}
+
+// Search backwards for search_label from _before_ position pos in the
+// memory.  Return the first line _after_ the the found label.  It is okay
+// to find search label's match inside another label.
+
+int cHardware4Stack::FindLabel_Backward(const cCodeLabel & search_label,
+				  const cGenome & search_genome, int pos)
+{
+  assert (pos < search_genome.GetSize());
+
+  int search_start = pos;
+  int label_size = search_label.GetSize();
+  bool found_label = false;
+
+  // Move off the template we are on.
+  pos -= label_size;
+
+  // Search until we find the complement or exit the memory.
+  while (pos >= 0) {
+    // If we are within a label, rewind to the beginning of it and see if
+    // it has the proper sub-label that we're looking for.
+
+    if (inst_set->IsNop( search_genome[pos] )) {
+      // Find the start and end of the label we're in the middle of.
+
+      int start_pos = pos;
+      int end_pos = pos + 1;
+      while (start_pos > 0 && inst_set->IsNop(search_genome[start_pos - 1])) {
+	start_pos--;
+      }
+      while (end_pos < search_start &&
+	     inst_set->IsNop(search_genome[end_pos])) {
+	end_pos++;
+      }
+      int test_size = end_pos - start_pos;
+
+      // See if this label has the proper sub-label within it.
+      int max_offset = test_size - label_size + 1;
+      for (int offset = start_pos; offset < start_pos + max_offset; offset++) {
+
+	// Test the number of matches for this offset.
+	int matches;
+	for (matches = 0; matches < label_size; matches++) {
+	  if (search_label[matches] !=
+	      inst_set->GetNopMod(search_genome[offset + matches])) {
+	    break;
+	  }
+	}
+
+	// If we have found it, break out of this loop!
+	if (matches == label_size) {
+	  found_label = true;
+	  break;
+	}
+      }
+
+      // If we've found the complement label, set the position to the end of
+      // the label we found it in, and break out.
+
+      if (found_label == true) {
+	pos = end_pos;
+	break;
+      }
+
+      // We haven't found it; jump pos to just before the current label
+      // being checked.
+      pos = start_pos - 1;
+    }
+
+    // Jump up a block to the next possible point to find a label,
+    pos -= label_size;
+  }
+
+  // If the label was not found return a -1.
+  if (found_label == false) pos = -1;
+
+  return pos;
+}
+
+// Search for 'in_label' anywhere in the hardware.
+c4StackHead cHardware4Stack::FindLabel(const cCodeLabel & in_label, int direction)
+{
+  assert (in_label.GetSize() > 0);
+
+  // IDEALY:
+  // Keep making jumps (in the proper direction) equal to the label
+  // length.  If we are inside of a label, check its size, and see if
+  // any of the sub-labels match properly.
+  // FOR NOW:
+  // Get something which works, no matter how inefficient!!!
+
+  c4StackHead temp_head(this);
+
+  while (temp_head.InMemory()) {
+    // IDEALY: Analyze the label we are in; see if the one we are looking
+    // for could be a sub-label of it.  Skip past it if not.
+
+    int i;
+    for (i = 0; i < in_label.GetSize(); i++) {
+      if (!inst_set->IsNop(temp_head.GetInst()) ||
+	  in_label[i] != inst_set->GetNopMod(temp_head.GetInst())) {
+	break;
+      }
+    }
+    if (i == GetLabel().GetSize()) {
+      temp_head.AbsJump(i - 1);
+      return temp_head;
+    }
+
+    temp_head.AbsJump(direction);     // IDEALY: MAKE LARGER JUMPS
+  }
+
+  temp_head.AbsSet(-1);
+  return temp_head;
+}
+
+// @CAO: direction is not currently used; should be used to indicate the
+// direction which the heads[HEAD_IP] should progress through a creature.
+c4StackHead cHardware4Stack::FindFullLabel(const cCodeLabel & in_label)
+{
+  // cout << "Running FindFullLabel with " << in_label.AsString() <<
+  // endl;
+
+  assert(in_label.GetSize() > 0); // Trying to find label of 0 size!
+
+  c4StackHead temp_head(this);
+
+  while (temp_head.InMemory()) {
+    // If we are not in a label, jump to the next checkpoint...
+    if (inst_set->IsNop(temp_head.GetInst())) {
+      temp_head.AbsJump(in_label.GetSize());
+      continue;
+    }
+
+    // Otherwise, rewind to the begining of this label...
+
+    while (!(temp_head.AtFront()) && inst_set->IsNop(temp_head.GetInst(-1)))
+      temp_head.AbsJump(-1);
+
+    // Calculate the size of the label being checked, and make sure they
+    // are equal.
+
+    int checked_size = 0;
+    while (inst_set->IsNop(temp_head.GetInst(checked_size))) {
+      checked_size++;
+    }
+    if (checked_size != in_label.GetSize()) {
+      temp_head.AbsJump(checked_size + 1);
+      continue;
+    }
+
+    // cout << "Testing label at line " << temp_head.GetPosition() <<
+    // endl;
+
+    // ...and do the comparison...
+
+    int j;
+    bool label_match = true;
+    for (j = 0; j < in_label.GetSize(); j++) {
+      if (!inst_set->IsNop(temp_head.GetInst(j)) ||
+	  in_label[j] != inst_set->GetNopMod(temp_head.GetInst(j))) {
+	temp_head.AbsJump(in_label.GetSize() + 1);
+	label_match = false;
+	break;
+      }
+    }
+
+    if (label_match) {
+      // If we have found the label, return the position after it.
+      temp_head.AbsJump(j - 1);
+      return temp_head;
+    }
+
+    // We have not found the label... increment i.
+
+    temp_head.AbsJump(in_label.GetSize() + 1);
+  }
+
+  // The label does not exist in this creature.
+
+  temp_head.AbsSet(-1);
+  return temp_head;
+}
+
+// This is the code run by the INFECTED organism.  Its function is to SPREAD infection.
+bool cHardware4Stack::InjectParasite(double mut_multiplier)
+{
+  const int end_pos = GetHead(HEAD_WRITE).GetPosition();
+  const int mem_space_used = GetHead(HEAD_WRITE).GetMemSpace();
+  
+  // Make sure the creature will still be above the minimum size,
+  // TEMPORARY!  INJECTED CODE CAN 
+  if (end_pos <= 0) {
+    Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: no code to inject");
+    return false; // (inject fails)
+  }
+  
+  if (end_pos < MIN_INJECT_SIZE) {
+    GetMemory(mem_space_used)=cGenome(ConvertToInstruction(mem_space_used)); 
+    Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: new size too small");
+    return false; // (inject fails)
+  }
+
+  GetMemory(mem_space_used).Resize(end_pos);
+
+  cCPUMemory injected_code = GetMemory(mem_space_used);
+
+  Inject_DoMutations(mut_multiplier, injected_code);
+
+  int inject_signal = false;
+
+  if(injected_code.GetSize()>0)
+    inject_signal = organism->InjectParasite(injected_code);
+  
+  //************* CALL GOES HERE ******************//
+  // spin around randomly (caution: possible organism dizziness)
+  //const int num_neighbors = organism->GetNeighborhoodSize();
+  //for(unsigned int i=0; i<g_random.GetUInt(num_neighbors); i++)
+  //  organism->Rotate(1);
+
+  // If we don't have a host, stop here.
+  //cOrganism * host_organism = organism->GetNeighbor();
+  
+ 
+  //if(host_organism!=NULL)
+  //  {
+  //    
+  //  }
+ 
+  //************** CALL ENDS HERE ******************//
+
+  //reset the memory space which was injected
+  GetMemory(mem_space_used)=cGenome(ConvertToInstruction(mem_space_used)); 
+
+  for(int x=0; x<NUM_HEADS; x++)
+    {
+      GetHead(x).Reset(IP().GetMemSpace(), this);
+    }
+
+  for(int x=0; x<NUM_LOCAL_STACKS; x++)
+    {
+      Stack(x).Clear();
+    }
+  
+  AdvanceIP() = false;
+  
+  return inject_signal;
+}
+
+//This is the code run by the TARGET of an injection.  This RECIEVES the infection.
+bool cHardware4Stack::InjectHost(const cCodeLabel & in_label, const cGenome & inject_code)
+{
+  // Make sure the genome will be below max size after injection.
+
+  // xxxTEMPORARYxxx - we should have this match injection templates.  For now it simply 
+  // makes sure the target_mem_space (hardcoded to 2) is empty. - law
+  int target_mem_space = 2; 
+  if(!(isEmpty(target_mem_space)))
+    return false;
+
+  assert(target_mem_space >=0 && target_mem_space < 4);
+  
+  if(ForkThread()) {
+    // Inject the new code
+    cCPUMemory oldcode = GetMemory(target_mem_space);
+    GetMemory(target_mem_space) = inject_code;
+    GetMemory(target_mem_space).Resize(inject_code.GetSize() + oldcode.GetSize());
+
+    // Copies previous instructions to the end of the injected code.
+    // Is there a faster way to do this?? -law
+    for(int x=0; x<oldcode.GetSize(); x++)
+      GetMemory(target_mem_space)[inject_code.GetSize()+x] = oldcode[x];
+  
+    // Set instruction flags on the injected code
+    for (int i = 0; i < inject_code.GetSize(); i++) {
+      memory_array[target_mem_space].FlagInjected(i) = true;
+    }
+    organism->GetPhenotype().IsModified() = true;
+    
+    // Adjust all of the heads to take into account the new mem size.
+    
+    cur_thread=GetNumThreads()-1;
+    
+    for(int i=0; i<cur_thread; i++) {
+      for(int j=0; j<NUM_HEADS; j++) {
+	if(threads[i].heads[j].GetMemSpace()==target_mem_space)
+	  threads[i].heads[j].Jump(inject_code.GetSize());
+      }
+    }
+    
+    for (int i=0; i < NUM_HEADS; i++) {    
+      GetHead(i).Reset(target_mem_space, this);
+    }
+    for (int i=0; i < NUM_LOCAL_STACKS; i++) {
+      Stack(i).Clear();
+    }
+  }
+
+  return true; // (inject succeeds!)
+}
+
+void cHardware4Stack::Mutate(int mut_point)
+{
+  // Test if trying to mutate outside of genome...
+  assert(mut_point >= 0 && mut_point < GetMemory(0).GetSize());
+
+  GetMemory(0)[mut_point] = GetRandomInst();
+  GetMemory(0).FlagMutated(mut_point) = true;
+  GetMemory(0).FlagPointMut(mut_point) = true;
+  //organism->GetPhenotype().IsMutated() = true;
+  organism->CPUStats().mut_stats.point_mut_count++;
+}
+
+int cHardware4Stack::PointMutate(const double mut_rate)
+{
+  const int num_muts =
+    g_random.GetRandBinomial(GetMemory(0).GetSize(), mut_rate);
+
+  for (int i = 0; i < num_muts; i++) {
+    const int pos = g_random.GetUInt(GetMemory(0).GetSize());
+    Mutate(pos);
+  }
+
+  return num_muts;
+}
+
+
+// Trigger mutations of a specific type.  Outside triggers cannot specify
+// a head since hardware types are not known.
+
+bool cHardware4Stack::TriggerMutations(int trigger)
+{
+  // Only update triggers should happen from the outside!
+  assert(trigger == MUTATION_TRIGGER_UPDATE);
+
+  // Assume instruction pointer is the intended target (if one is even
+  // needed!
+
+  return TriggerMutations(trigger, IP());
+}
+
+bool cHardware4Stack::TriggerMutations(int trigger, c4StackHead & cur_head)
+{
+  // Collect information about mutations from the organism.
+  cLocalMutations & mut_info = organism->GetLocalMutations();
+  const tList<cMutation> & mut_list =
+    mut_info.GetMutationLib().GetMutationList(trigger);
+
+  // If we have no mutations for this trigger, stop here.
+  if (mut_list.GetSize() == 0) return false;
+  bool has_mutation = false;
+
+  // Determine what memory this mutation will be affecting.
+  cCPUMemory & target_mem = (trigger == MUTATION_TRIGGER_DIVIDE) 
+    ? organism->ChildGenome() : GetMemory(0);
+
+  // Loop through all mutations associated with this trigger and test them.
+  tConstListIterator<cMutation> mut_it(mut_list);
+
+  while (mut_it.Next() != NULL) {
+    const cMutation * cur_mut = mut_it.Get();
+    const int mut_id = cur_mut->GetID();
+    const int scope = cur_mut->GetScope();
+    const double rate = mut_info.GetRate(mut_id);
+    switch (scope) {
+    case MUTATION_SCOPE_GENOME:
+      if (TriggerMutations_ScopeGenome(cur_mut, target_mem, cur_head, rate)) {
+	has_mutation = true;
+	mut_info.IncCount(mut_id);
+      }
+      break;
+    case MUTATION_SCOPE_LOCAL:
+    case MUTATION_SCOPE_PROP:
+      if (TriggerMutations_ScopeLocal(cur_mut, target_mem, cur_head, rate)) {
+	has_mutation = true;
+	mut_info.IncCount(mut_id);
+      }
+      break;
+    case MUTATION_SCOPE_GLOBAL:
+    case MUTATION_SCOPE_SPREAD:
+      int num_muts =
+	TriggerMutations_ScopeGlobal(cur_mut, target_mem, cur_head, rate);
+      if (num_muts > 0) {
+	has_mutation = true;
+	mut_info.IncCount(mut_id, num_muts);
+      }
+      break;
+    }
+  }
+
+  return has_mutation;
+}
+
+bool cHardware4Stack::TriggerMutations_ScopeGenome(const cMutation * cur_mut,
+          cCPUMemory & target_memory, c4StackHead & cur_head, const double rate)
+{
+  // The rate we have stored indicates the probability that a single
+  // mutation will occur anywhere in the genome.
+  
+  if (g_random.P(rate) == true) {
+    // We must create a temporary head and use it to randomly determine the
+    // position in the genome to be mutated.
+    c4StackHead tmp_head(cur_head);
+    tmp_head.AbsSet(g_random.GetUInt(target_memory.GetSize()));
+    TriggerMutations_Body(cur_mut->GetType(), target_memory, tmp_head);
+    return true;
+  }
+  return false;
+}
+
+bool cHardware4Stack::TriggerMutations_ScopeLocal(const cMutation * cur_mut,
+          cCPUMemory & target_memory, c4StackHead & cur_head, const double rate)
+{
+  // The rate we have stored is the probability for a mutation at this single
+  // position in the genome.
+
+  if (g_random.P(rate) == true) {
+    TriggerMutations_Body(cur_mut->GetType(), target_memory, cur_head);
+    return true;
+  }
+  return false;
+}
+
+int cHardware4Stack::TriggerMutations_ScopeGlobal(const cMutation * cur_mut,
+          cCPUMemory & target_memory, c4StackHead & cur_head, const double rate)
+{
+  // The probability we have stored is per-site, so we can pull a random
+  // number from a binomial distribution to determine the number of mutations
+  // that should occur.
+
+  const int num_mut =
+    g_random.GetRandBinomial(target_memory.GetSize(), rate);
+
+  if (num_mut > 0) {
+    for (int i = 0; i < num_mut; i++) {
+      c4StackHead tmp_head(cur_head);
+      tmp_head.AbsSet(g_random.GetUInt(target_memory.GetSize()));
+      TriggerMutations_Body(cur_mut->GetType(), target_memory, tmp_head);
+    }
+  }
+
+  return num_mut;
+}
+
+void cHardware4Stack::TriggerMutations_Body(int type, cCPUMemory & target_memory,
+					 c4StackHead & cur_head)
+{
+  const int pos = cur_head.GetPosition();
+
+  switch (type) {
+  case MUTATION_TYPE_POINT:
+    target_memory[pos] = GetRandomInst();
+    target_memory.FlagMutated(pos) = true;
+    break;
+  case MUTATION_TYPE_INSERT:
+  case MUTATION_TYPE_DELETE:
+  case MUTATION_TYPE_HEAD_INC:
+  case MUTATION_TYPE_HEAD_DEC:
+  case MUTATION_TYPE_TEMP:
+  case MUTATION_TYPE_KILL:
+  default:
+    cout << "Error: Mutation type not implemented!" << endl;
+    break;
+  };
+}
+
+void cHardware4Stack::ReadInst(const int in_inst)
+{
+  if (inst_set->IsNop( cInstruction(in_inst) )) {
+    GetReadLabel().AddNop(in_inst);
+  } else {
+    GetReadLabel().Clear();
+  }
+}
+
+
+void cHardware4Stack::AdjustHeads()
+{
+  for (int i = 0; i < GetNumThreads(); i++) {
+    for (int j = 0; j < NUM_HEADS; j++) {
+      threads[i].heads[j].Adjust();
+    }
+  }
+}
+
+
+
+// This function looks at the current position in the info of a creature,
+// and sets the next_label to be the sequence of nops which follows.  The
+// instruction pointer is left on the last line of the label found.
+
+void cHardware4Stack::ReadLabel(int max_size)
+{
+  int count = 0;
+  c4StackHead * inst_ptr = &( IP() );
+
+  GetLabel().Clear();
+
+  while (inst_set->IsNop(inst_ptr->GetNextInst()) &&
+	 (count < max_size)) {
+    count++;
+    inst_ptr->Advance();
+    GetLabel().AddNop(inst_set->GetNopMod(inst_ptr->GetInst()));
+
+    // If this is the first line of the template, mark it executed.
+    if (GetLabel().GetSize() <=	cConfig::GetMaxLabelExeSize()) {
+      inst_ptr->FlagExecuted() = true;
+    }
+  }
+}
+
+
+bool cHardware4Stack::ForkThread()
+{
+  const int num_threads = GetNumThreads();
+  if (num_threads == cConfig::GetMaxCPUThreads()) return false;
+
+  // Make room for the new thread.
+  threads.Resize(num_threads + 1);
+
+  //IP().Advance();
+
+  // Initialize the new thread to the same values as the current one.
+  threads[num_threads] = threads[cur_thread]; 
+
+  // Find the first free bit in thread_id_chart to determine the new
+  // thread id.
+  int new_id = 0;
+  while ( (thread_id_chart >> new_id) & 1 == 1) new_id++;
+  threads[num_threads].SetID(new_id);
+  thread_id_chart |= (1 << new_id);
+
+  return true;
+}
+
+
+int cHardware4Stack::TestParasite() const
+{
+  return IP().TestParasite();
+}
+
+
+bool cHardware4Stack::KillThread()
+{
+  // Make sure that there is always at least one thread...
+  if (GetNumThreads() == 1) return false;
+
+  // Note the current thread and set the current back one.
+  const int kill_thread = cur_thread;
+  PrevThread();
+  
+  // Turn off this bit in the thread_id_chart...
+  thread_id_chart ^= 1 << threads[kill_thread].GetID();
+
+  // Copy the last thread into the kill position
+  const int last_thread = GetNumThreads() - 1;
+  if (last_thread != kill_thread) {
+    threads[kill_thread] = threads[last_thread];
+  }
+
+  // Kill the thread!
+  threads.Resize(GetNumThreads() - 1);
+
+  if (cur_thread > kill_thread) cur_thread--;
+
+  return true;
+}
+
+
+void cHardware4Stack::SaveState(ostream & fp)
+{
+  // note, memory & child_memory handled by cpu (@CAO Not any more!)
+  assert(fp.good());
+
+  fp<<"cHardware4Stack"<<endl;
+
+  // global_stack (in inverse order so load can just push)
+  for(int i=NUM_LOCAL_STACKS; i<NUM_STACKS; i++)
+    Stack(i).SaveState(fp);
+
+  //fp << thread_time_used  << endl;
+  fp << GetNumThreads()   << endl;
+  fp << cur_thread        << endl;
+
+  // Threads
+  for( int i = 0; i < GetNumThreads(); i++ ) {
+    threads[i].SaveState(fp);
+  }
+}
+
+
+void cHardware4Stack::LoadState(istream & fp)
+{
+  // note, memory & child_memory handled by cpu (@CAO Not any more!)
+  assert(fp.good());
+
+  cString foo;
+  fp>>foo;
+  assert( foo == "cHardware4Stack" );
+
+  // global_stack
+  for(int i=NUM_LOCAL_STACKS; i<NUM_STACKS; i++)
+    Stack(i).LoadState(fp);
+
+  int num_threads;
+  //fp >> thread_time_used;
+  fp >> num_threads;
+  fp >> cur_thread;
+
+  // Threads
+  for( int i = 0; i < num_threads; i++ ){
+    threads[i].LoadState(fp);
+  }
+}
+
+
+////////////////////////////
+//  Instruction Helpers...
+////////////////////////////
+
+inline int cHardware4Stack::FindModifiedStack(int default_stack)
+{
+  assert(default_stack < NUM_STACKS);  // Stack ID too high.
+
+  if (GetInstSet().IsNop(IP().GetNextInst())) {
+    IP().Advance();
+    default_stack = GetInstSet().GetNopMod(IP().GetInst());
+    IP().FlagExecuted() = true;
+  }
+  return default_stack;
+}
+
+inline int cHardware4Stack::FindModifiedHead(int default_head)
+{
+  assert(default_head < NUM_HEADS); // Head ID too high.
+
+  if (GetInstSet().IsNop(IP().GetNextInst())) {
+    IP().Advance();
+    default_head = GetInstSet().GetNopMod(IP().GetInst());
+    IP().FlagExecuted() = true;
+  }
+  return default_head;
+}
+
+inline int cHardware4Stack::FindComplementStack(int base_stack)
+{
+  const int comp_stack = base_stack + 2;
+  return comp_stack%NUM_STACKS;
+}
+
+inline void cHardware4Stack::Fault(int fault_loc, int fault_type, cString fault_desc)
+{
+  organism->Fault(fault_loc, fault_type, fault_desc);
+}
+
+bool cHardware4Stack::Divide_CheckViable(const int parent_size,
+				      const int child_size, const int mem_space)
+{
+  // Make sure the organism is okay with dividing now...
+  if (organism->Divide_CheckViable() == false) return false; // (divide fails)
+
+  // Make sure that neither parent nor child will be below the minimum size.
+
+  const int genome_size = organism->GetGenome().GetSize();
+  const double size_range = cConfig::GetChildSizeRange();
+  const int min_size = Max(MIN_CREATURE_SIZE, (int) (genome_size/size_range));
+  const int max_size = Min(MAX_CREATURE_SIZE, (int) (genome_size*size_range));
+  
+  if (child_size < min_size || child_size > max_size) {
+    Fault(FAULT_LOC_DIVIDE, FAULT_TYPE_ERROR,
+	  cStringUtil::Stringf("Invalid offspring length (%d)", child_size));
+    return false; // (divide fails)
+  }
+
+  // Count the number of lines executed in the parent, and make sure the
+  // specified fraction has been reached.
+
+  int executed_size = 0;
+  for (int i = 0; i < parent_size; i++) {
+    if (GetMemory(0).FlagExecuted(i)) executed_size++;
+  }
+
+  const int min_exe_lines = (int) (parent_size * cConfig::GetMinExeLines());
+  if (executed_size < min_exe_lines) {
+    Fault(FAULT_LOC_DIVIDE, FAULT_TYPE_ERROR,
+	  cStringUtil::Stringf("Too few executed lines (%d < %d)",
+			       executed_size, min_exe_lines));
+    return false; // (divide fails)
+  }
+	
+  // Count the number of lines which were copied into the child, and make
+  // sure the specified fraction has been reached.
+
+  int copied_size = 0;
+  for (int i = 0; i < GetMemory(mem_space).GetSize(); i++) {
+    if (GetMemory(mem_space).FlagCopied(i)) copied_size++;
+   }
+
+  const int min_copied =  (int) (child_size * cConfig::GetMinCopiedLines());
+  if (copied_size < min_copied) {
+    Fault(FAULT_LOC_DIVIDE, FAULT_TYPE_ERROR,
+	  cStringUtil::Stringf("Too few copied commands (%d < %d)",
+			       copied_size, min_copied));
+    return false; // (divide fails)
+  }
+
+  // Save the information we collected here...
+  organism->GetPhenotype().SetLinesExecuted(executed_size);
+  organism->GetPhenotype().SetLinesCopied(copied_size);
+
+  return true; // (divide succeeds!)
+}
+
+void cHardware4Stack::Divide_DoMutations(double mut_multiplier)
+{
+  sCPUStats & cpu_stats = organism->CPUStats();
+  cCPUMemory & child_genome = organism->ChildGenome();
+  
+  organism->GetPhenotype().SetDivType(mut_multiplier);
+
+  // Divide Mutations
+  if (organism->TestDivideMut()) {
+    const UINT mut_line = g_random.GetUInt(child_genome.GetSize());
+    child_genome[mut_line] = GetRandomInst();
+    cpu_stats.mut_stats.divide_mut_count++;
+  }
+
+  // Divide Insertions
+  if (organism->TestDivideIns() && child_genome.GetSize() < MAX_CREATURE_SIZE){
+    const UINT mut_line = g_random.GetUInt(child_genome.GetSize() + 1);
+    child_genome.Insert(mut_line, GetRandomInst());
+    cpu_stats.mut_stats.divide_insert_mut_count++;
+  }
+
+  // Divide Deletions
+  if (organism->TestDivideDel() && child_genome.GetSize() > MIN_CREATURE_SIZE){
+    const UINT mut_line = g_random.GetUInt(child_genome.GetSize());
+    // if( child_genome.FlagCopied(mut_line) == true) copied_size_change--;
+    child_genome.Remove(mut_line);
+    cpu_stats.mut_stats.divide_delete_mut_count++;
+  }
+
+  // Divide Mutations (per site)
+  if(organism->GetDivMutProb() > 0){
+    int num_mut = g_random.GetRandBinomial(child_genome.GetSize(), 
+				   	   organism->GetDivMutProb() / mut_multiplier);
+    // If we have lines to mutate...
+    if( num_mut > 0 ){
+      for (int i = 0; i < num_mut; i++) {
+	int site = g_random.GetUInt(child_genome.GetSize());
+	child_genome[site]=GetRandomInst();
+	cpu_stats.mut_stats.div_mut_count++;
+      }
+    }
+  }
+
+
+  // Insert Mutations (per site)
+  if(organism->GetInsMutProb() > 0){
+    int num_mut = g_random.GetRandBinomial(child_genome.GetSize(),
+					   organism->GetInsMutProb());
+    // If would make creature to big, insert up to MAX_CREATURE_SIZE
+    if( num_mut + child_genome.GetSize() > MAX_CREATURE_SIZE ){
+      num_mut = MAX_CREATURE_SIZE - child_genome.GetSize();
+    }
+    // If we have lines to insert...
+    if( num_mut > 0 ){
+      // Build a list of the sites where mutations occured
+      static int mut_sites[MAX_CREATURE_SIZE];
+      for (int i = 0; i < num_mut; i++) {
+	mut_sites[i] = g_random.GetUInt(child_genome.GetSize() + 1);
+      }
+      // Sort the list
+      qsort( (void*)mut_sites, num_mut, sizeof(int), &IntCompareFunction );
+      // Actually do the mutations (in reverse sort order)
+      for(int i = num_mut-1; i >= 0; i--) {
+	child_genome.Insert(mut_sites[i], GetRandomInst());
+	cpu_stats.mut_stats.insert_mut_count++;
+      }
+    }
+  }
+
+
+  // Delete Mutations (per site)
+  if( organism->GetDelMutProb() > 0 ){
+    int num_mut = g_random.GetRandBinomial(child_genome.GetSize(),
+					   organism->GetDelMutProb());
+    // If would make creature too small, delete down to MIN_CREATURE_SIZE
+    if (child_genome.GetSize() - num_mut < MIN_CREATURE_SIZE) {
+      num_mut = child_genome.GetSize() - MIN_CREATURE_SIZE;
+    }
+
+    // If we have lines to delete...
+    for (int i = 0; i < num_mut; i++) {
+      int site = g_random.GetUInt(child_genome.GetSize());
+      // if (child_genome.FlagCopied(site) == true) copied_size_change--;
+      child_genome.Remove(site);
+      cpu_stats.mut_stats.delete_mut_count++;
+    }
+  }
+
+  // Mutations in the parent's genome
+  if (organism->GetParentMutProb() > 0) {
+    for (int i = 0; i < GetMemory(0).GetSize(); i++) {
+      if (organism->TestParentMut()) {
+	GetMemory(0)[i] = GetRandomInst();
+	cpu_stats.mut_stats.parent_mut_line_count++;
+      }
+    }
+  }
+
+
+  // Count up mutated lines
+  for(int i = 0; i < GetMemory(0).GetSize(); i++){
+    if (GetMemory(0).FlagPointMut(i) == true) {
+      cpu_stats.mut_stats.point_mut_line_count++;
+    }
+  }
+  for(int i = 0; i < child_genome.GetSize(); i++){
+    if( child_genome.FlagCopyMut(i) == true) {
+      cpu_stats.mut_stats.copy_mut_line_count++;
+    }
+  }
+}
+
+void cHardware4Stack::Inject_DoMutations(double mut_multiplier, cCPUMemory & injected_code)
+{
+  //sCPUStats & cpu_stats = organism->CPUStats();
+  //cCPUMemory & child_genome = organism->ChildGenome();
+  
+  organism->GetPhenotype().SetDivType(mut_multiplier);
+
+  // Divide Mutations
+  if (organism->TestDivideMut()) {
+    const UINT mut_line = g_random.GetUInt(injected_code.GetSize());
+    injected_code[mut_line] = GetRandomInst();
+    //cpu_stats.mut_stats.divide_mut_count++;
+  }
+
+  // Divide Insertions
+  if (organism->TestDivideIns() && injected_code.GetSize() < MAX_CREATURE_SIZE){
+    const UINT mut_line = g_random.GetUInt(injected_code.GetSize() + 1);
+    injected_code.Insert(mut_line, GetRandomInst());
+    //cpu_stats.mut_stats.divide_insert_mut_count++;
+  }
+
+  // Divide Deletions
+  if (organism->TestDivideDel() && injected_code.GetSize() > MIN_CREATURE_SIZE){
+    const UINT mut_line = g_random.GetUInt(injected_code.GetSize());
+    // if( injected_code.FlagCopied(mut_line) == true) copied_size_change--;
+    injected_code.Remove(mut_line);
+    //cpu_stats.mut_stats.divide_delete_mut_count++;
+  }
+
+  // Divide Mutations (per site)
+  if(organism->GetDivMutProb() > 0){
+    int num_mut = g_random.GetRandBinomial(injected_code.GetSize(), 
+				   	   organism->GetDivMutProb() / mut_multiplier);
+    // If we have lines to mutate...
+    if( num_mut > 0 ){
+      for (int i = 0; i < num_mut; i++) {
+	int site = g_random.GetUInt(injected_code.GetSize());
+	injected_code[site]=GetRandomInst();
+	//cpu_stats.mut_stats.div_mut_count++;
+      }
+    }
+  }
+
+
+  // Insert Mutations (per site)
+  if(organism->GetInsMutProb() > 0){
+    int num_mut = g_random.GetRandBinomial(injected_code.GetSize(),
+					   organism->GetInsMutProb());
+    // If would make creature to big, insert up to MAX_CREATURE_SIZE
+    if( num_mut + injected_code.GetSize() > MAX_CREATURE_SIZE ){
+      num_mut = MAX_CREATURE_SIZE - injected_code.GetSize();
+    }
+    // If we have lines to insert...
+    if( num_mut > 0 ){
+      // Build a list of the sites where mutations occured
+      static int mut_sites[MAX_CREATURE_SIZE];
+      for (int i = 0; i < num_mut; i++) {
+	mut_sites[i] = g_random.GetUInt(injected_code.GetSize() + 1);
+      }
+      // Sort the list
+      qsort( (void*)mut_sites, num_mut, sizeof(int), &IntCompareFunction );
+      // Actually do the mutations (in reverse sort order)
+      for(int i = num_mut-1; i >= 0; i--) {
+	injected_code.Insert(mut_sites[i], GetRandomInst());
+	//cpu_stats.mut_stats.insert_mut_count++;
+      }
+    }
+  }
+
+
+  // Delete Mutations (per site)
+  if( organism->GetDelMutProb() > 0 ){
+    int num_mut = g_random.GetRandBinomial(injected_code.GetSize(),
+					   organism->GetDelMutProb());
+    // If would make creature too small, delete down to MIN_CREATURE_SIZE
+    if (injected_code.GetSize() - num_mut < MIN_CREATURE_SIZE) {
+      num_mut = injected_code.GetSize() - MIN_CREATURE_SIZE;
+    }
+
+    // If we have lines to delete...
+    for (int i = 0; i < num_mut; i++) {
+      int site = g_random.GetUInt(injected_code.GetSize());
+      // if (injected_code.FlagCopied(site) == true) copied_size_change--;
+      injected_code.Remove(site);
+      //cpu_stats.mut_stats.delete_mut_count++;
+    }
+  }
+
+  // Mutations in the parent's genome
+  if (organism->GetParentMutProb() > 0) {
+    for (int i = 0; i < GetMemory(0).GetSize(); i++) {
+      if (organism->TestParentMut()) {
+	GetMemory(0)[i] = GetRandomInst();
+	//cpu_stats.mut_stats.parent_mut_line_count++;
+      }
+    }
+  }
+
+  /*
+  // Count up mutated lines
+  for(int i = 0; i < GetMemory(0).GetSize(); i++){
+    if (GetMemory(0).FlagPointMut(i) == true) {
+      cpu_stats.mut_stats.point_mut_line_count++;
+    }
+  }
+  for(int i = 0; i < injected_code.GetSize(); i++){
+    if( injected_code.FlagCopyMut(i) == true) {
+      cpu_stats.mut_stats.copy_mut_line_count++;
+    }
+    }*/
+}
+
+
+// test whether the offspring creature contains an advantageous mutation.
+void cHardware4Stack::Divide_TestFitnessMeasures()
+{
+  cPhenotype & phenotype = organism->GetPhenotype();
+  phenotype.CopyTrue() = ( organism->ChildGenome() == organism->GetGenome() );
+  phenotype.ChildFertile() = true;
+
+  // Only continue if we're supposed to do a fitness test on divide...
+  if (organism->GetTestOnDivide() == false) return;
+
+  // If this was a perfect copy, then we don't need to worry about any other
+  // tests...  Theoretically, we need to worry about the parent changing,
+  // but as long as the child is always compared to the original genotype,
+  // this won't be an issue.
+  if (phenotype.CopyTrue() == true) return;
+
+  const double parent_fitness = organism->GetTestFitness();
+  const double neut_min = parent_fitness * FITNESS_NEUTRAL_MIN;
+  const double neut_max = parent_fitness * FITNESS_NEUTRAL_MAX;
+  
+  cCPUTestInfo test_info;
+  test_info.UseRandomInputs();
+  cTestCPU::TestGenome(test_info, organism->ChildGenome());
+  const double child_fitness = test_info.GetGenotypeFitness();
+  
+  bool revert = false;
+  bool sterilize = false;
+  
+  // If implicit mutations are turned off, make sure this won't spawn one.
+  if (organism->GetFailImplicit() == true) {
+    if (test_info.GetMaxDepth() > 0) sterilize = true;
+  }
+  
+  if (child_fitness == 0.0) {
+    // Fatal mutation... test for reversion.
+    if (g_random.P(organism->GetRevertFatal())) revert = true;
+    if (g_random.P(organism->GetSterilizeFatal())) sterilize = true;
+  } else if (child_fitness < neut_min) {
+    if (g_random.P(organism->GetRevertNeg())) revert = true;
+    if (g_random.P(organism->GetSterilizeNeg())) sterilize = true;
+  } else if (child_fitness <= neut_max) {
+    if (g_random.P(organism->GetRevertNeut())) revert = true;
+    if (g_random.P(organism->GetSterilizeNeut())) sterilize = true;
+  } else {
+    if (g_random.P(organism->GetRevertPos())) revert = true;
+    if (g_random.P(organism->GetSterilizePos())) sterilize = true;
+  }
+  
+  // Ideally, we won't have reversions and sterilizations turned on at the
+  // same time, but if we do, give revert the priority.
+  if (revert == true) {
+    organism->ChildGenome() = organism->GetGenome();
+  }
+
+  if (sterilize == true) {
+    organism->GetPhenotype().ChildFertile() = false;
+  }
+}
+
+
+bool cHardware4Stack::Divide_Main(int mem_space_used, double mut_multiplier)
+{
+  int write_head_pos = GetHead(HEAD_WRITE).GetPosition();
+  
+  // We're going to disallow division calls from memory spaces other than zero 
+  // for right now -law
+  if(IP().GetMemSpace()!=0)
+    return false;
+
+  // Make sure this divide will produce a viable offspring.
+  if(!Divide_CheckViable(GetMemory(IP().GetMemSpace()).GetSize(), 
+	 		 write_head_pos, mem_space_used)) 
+    return false;
+  
+  // Since the divide will now succeed, set up the information to be sent
+  // to the new organism
+  cGenome & child_genome = organism->ChildGenome();
+  GetMemory(mem_space_used).Resize(write_head_pos);
+  child_genome = GetMemory(mem_space_used);
+
+  // Handle Divide Mutations...
+  Divide_DoMutations(mut_multiplier);
+
+  // Many tests will require us to run the offspring through a test CPU;
+  // this is, for example, to see if mutations need to be reverted or if
+  // lineages need to be updated.
+  Divide_TestFitnessMeasures();
+
+#ifdef INSTRUCTION_COSTS
+  // reset first time instruction costs
+  for (int i = 0; i < inst_ft_cost.GetSize(); i++) {
+    inst_ft_cost[i] = GetInstSet().GetFTCost(cInstruction(i));
+  }
+#endif
+
+  bool parent_alive = organism->ActivateDivide();
+
+  //reset the memory of the memory space that has been divided off
+  GetMemory(mem_space_used)=cGenome(ConvertToInstruction(mem_space_used)); 
+
+  // 3 Division Methods:
+  // 1) DIVIDE_METHOD_OFFSPRING - Create a child, leave parent state untouched.
+  // 2) DIVIDE_METHOD_SPLIT - Create a child, completely reset state of parent.
+  // 3) DIVIDE_METHOD_BIRTH - Create a child, reset state of parent's current thread.
+  if(parent_alive && !(cConfig::GetDivideMethod() == DIVIDE_METHOD_OFFSPRING))
+    {
+      
+      if(cConfig::GetDivideMethod() == DIVIDE_METHOD_SPLIT)
+	{
+	  //this will wipe out all parasites on a divide.
+	  Reset();
+	  
+	}
+      else if(cConfig::GetDivideMethod() == DIVIDE_METHOD_BIRTH)
+	{
+	  //if this isn't the only thread, get rid of it!
+	  // ***this can cause a concurrency problem if we have 
+	  // multiprocessor support for single organisms...don't 
+	  // think that's happening anytime soon though -law ***
+	  if(!organism->GetPhenotype().IsModified() && GetNumThreads()>1 || 
+	     GetNumThreads()>2)
+	    {
+	      KillThread();
+	    }
+
+	  //this will reset the current thread's heads and stacks.  It will 
+	  //not touch any other threads or memory spaces (ie: parasites)
+	  else
+	    {
+	      for(int x=0; x<NUM_HEADS; x++)
+		{
+		  GetHead(x).Reset(0, this);
+		}
+	      for(int x=0; x<NUM_LOCAL_STACKS; x++)
+		{
+		  Stack(x).Clear();
+		}	  
+	    }
+	}
+      AdvanceIP()=false;
+    }
+     
+  return true;
+}
+
+cString cHardware4Stack::ConvertToInstruction(int mem_space_used)
+{
+  char c = mem_space_used + 97;
+  cString ret;
+  ret += c;
+  return ret;
+}
+
+cString cHardware4Stack::GetActiveStackID(int stackID) const
+{
+  if(stackID==STACK_AX)
+    return "AX";
+  else if(stackID==STACK_BX)
+    return "BX";
+  else if(stackID==STACK_CX)
+    return "CX";
+  else if(stackID==STACK_DX)
+    return "DX";
+  else
+    return "";
+}
+  
+
+//////////////////////////
+// And the instructions...
+//////////////////////////
+
+//6
+bool cHardware4Stack::Inst_ShiftR()
+{
+  const int stack_used = FindModifiedStack(STACK_BX);
+  int value = Stack(stack_used).Pop();
+  value >>= 1;
+  Stack(stack_used).Push(value);
+  return true;
+}
+
+//7
+bool cHardware4Stack::Inst_ShiftL()
+{
+  const int stack_used = FindModifiedStack(STACK_BX);
+  int value = Stack(stack_used).Pop();
+  value <<= 1;
+  Stack(stack_used).Push(value);
+  return true;
+}
+
+//8
+bool cHardware4Stack::Inst_Val_Nand()
+{
+  const int stack_used = FindModifiedStack(STACK_BX);
+  Stack(stack_used).Push(~(Stack(STACK_BX).Top() & Stack(STACK_CX).Top()));
+  return true;
+}
+
+//9
+bool cHardware4Stack::Inst_Val_Add()
+{
+  const int stack_used = FindModifiedStack(STACK_BX);
+  Stack(stack_used).Push(Stack(STACK_BX).Top() + Stack(STACK_CX).Top());
+  return true;
+}
+
+//10
+bool cHardware4Stack::Inst_Val_Sub()
+{
+  const int stack_used = FindModifiedStack(STACK_BX);
+  Stack(stack_used).Push(Stack(STACK_BX).Top() - Stack(STACK_CX).Top());
+  return true;
+}
+
+//11
+bool cHardware4Stack::Inst_Val_Mult()
+{
+  const int stack_used = FindModifiedStack(STACK_BX);
+  Stack(stack_used).Push(Stack(STACK_BX).Top() * Stack(STACK_CX).Top());
+  return true;
+}
+
+//12
+bool cHardware4Stack::Inst_Val_Div()
+{
+  const int stack_used = FindModifiedStack(STACK_BX);
+  if (Stack(STACK_CX).Top() != 0) {
+    if (0-INT_MAX > Stack(STACK_BX).Top() && Stack(STACK_CX).Top() == -1)
+      Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "div: Float exception");
+    else
+      Stack(stack_used).Push(Stack(STACK_BX).Top() / Stack(STACK_CX).Top());
+  } else {
+    Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "div: dividing by 0");
+    return false;
+  }
+  return true;
+}
+
+//13 
+bool cHardware4Stack::Inst_SetMemory()   // Allocate maximal more
+{
+  int mem_space_used = FindModifiedStack(-1);
+  
+  if(mem_space_used==-1) {
+    mem_space_used = FindFirstEmpty();
+    if(mem_space_used==-1)
+      return false;
+  }
+  
+  GetHead(HEAD_FLOW).Set(0, mem_space_used);
+  return true;
+  
+  //const int cur_size = GetMemory(0).GetSize();
+  //const int alloc_size = Min((int) (cConfig::GetChildSizeRange() * cur_size),
+  //			     MAX_CREATURE_SIZE - cur_size);
+  //if( Allocate_Main(alloc_size) ) {
+  //  Stack(STACK_AX).Push(cur_size);
+  //  return true;
+  //} else return false;
+}
+
+//14
+bool cHardware4Stack::Inst_Divide()
+{
+  int mem_space_used = GetHead(HEAD_WRITE).GetMemSpace();
+  int mut_multiplier = 1;
+
+  return Divide_Main(mem_space_used, mut_multiplier);
+}
+
+bool cHardware4Stack::Inst_HeadDivideMut(double mut_multiplier)
+{
+  // Unused for the moment...
+  return true;
+  //AdjustHeads();
+  //const int divide_pos = GetHead(HEAD_READ).GetPosition();
+  //int child_end =  GetHead(HEAD_WRITE).GetPosition();
+  //if (child_end == 0) child_end = GetMemory(0).GetSize();
+  //const int extra_lines = GetMemory(0).GetSize() - child_end;
+  //bool ret_val = Divide_Main(divide_pos, extra_lines, mut_multiplier);
+  //// Re-adjust heads.
+  //AdjustHeads();
+  //return ret_val; 
+}
+
+//15
+bool cHardware4Stack::Inst_HeadRead()
+{
+  const int head_id = FindModifiedHead(HEAD_READ);
+  GetHead(head_id).Adjust();
+  sCPUStats & cpu_stats = organism->CPUStats();
+
+  // Mutations only occur on the read, for the moment.
+  int read_inst = 0;
+  if (organism->TestCopyMut()) {
+    read_inst = GetRandomInst().GetOp();
+    cpu_stats.mut_stats.copy_mut_count++;  // @CAO, hope this is good!
+  } else {
+    read_inst = GetHead(head_id).GetInst().GetOp();
+  }
+  Stack(STACK_AX).Push(read_inst);
+  ReadInst(read_inst);
+
+  cpu_stats.mut_stats.copies_exec++;  // @CAO, this too..
+  GetHead(head_id).Advance();
+  return true;
+}
+
+//16
+bool cHardware4Stack::Inst_HeadWrite()
+{
+  const int head_id = FindModifiedHead(HEAD_WRITE);
+  c4StackHead & active_head = GetHead(head_id);
+  int mem_space_used = active_head.GetMemSpace();
+  
+  //commented out for right now...
+  if(active_head.GetPosition()>=GetMemory(mem_space_used).GetSize()-1)
+   {
+     GetMemory(mem_space_used).Resize(GetMemory(mem_space_used).GetSize()+1);
+     GetMemory(mem_space_used).Copy(GetMemory(mem_space_used).GetSize()-1, GetMemory(mem_space_used).GetSize()-2);
+   }
+
+  active_head.Adjust();
+
+  int value = Stack(STACK_AX).Pop();
+  if (value < 0 || value >= GetNumInst()) value = 0;
+
+  active_head.SetInst(cInstruction(value));
+  active_head.FlagCopied() = true;
+
+  // Advance the head after write...
+  active_head++;
+  return true;
+}
+
+//??
+bool cHardware4Stack::Inst_HeadCopy()
+{
+  // For the moment, this cannot be nop-modified.
+  c4StackHead & read_head = GetHead(HEAD_READ);
+  c4StackHead & write_head = GetHead(HEAD_WRITE);
+  sCPUStats & cpu_stats = organism->CPUStats();
+
+  read_head.Adjust();
+  write_head.Adjust();
+
+  // TriggerMutations(MUTATION_TRIGGER_READ, read_head);
+  
+  // Do mutations.
+  cInstruction read_inst = read_head.GetInst();
+  if (organism->TestCopyMut()) {
+    read_inst = GetRandomInst();
+    cpu_stats.mut_stats.copy_mut_count++; 
+    write_head.FlagMutated() = true;
+    write_head.FlagCopyMut() = true;
+    //organism->GetPhenotype().IsMutated() = true;
+  }
+  ReadInst(read_inst.GetOp());
+
+  cpu_stats.mut_stats.copies_exec++;
+
+  write_head.SetInst(read_inst);
+  write_head.FlagCopied() = true;  // Set the copied flag...
+
+  // TriggerMutations(MUTATION_TRIGGER_WRITE, write_head);
+
+  read_head.Advance();
+  write_head.Advance();
+  return true;
+}
+
+//17
+bool cHardware4Stack::Inst_IfEqual()      // Execute next if bx == ?cx?
+{
+  const int stack_used = FindModifiedStack(STACK_AX);
+  const int stack_used2 = (stack_used+1)%NUM_STACKS;
+  if (Stack(stack_used).Top() != Stack(stack_used2).Top())  IP().Advance();
+  return true;
+}
+
+//18
+bool cHardware4Stack::Inst_IfNotEqual()     // Execute next if bx != ?cx?
+{
+  const int stack_used = FindModifiedStack(STACK_AX);
+  const int stack_used2 = (stack_used+1)%NUM_STACKS;
+  if (Stack(stack_used).Top() == Stack(stack_used2).Top())  IP().Advance();
+  return true;
+}
+
+//19
+bool cHardware4Stack::Inst_IfLess()       // Execute next if ?bx? < ?cx?
+{
+  const int stack_used = FindModifiedStack(STACK_AX);
+  const int stack_used2 = (stack_used+1)%NUM_STACKS;
+  if (Stack(stack_used).Top() >=  Stack(stack_used2).Top())  IP().Advance();
+  return true;
+}
+
+//20
+bool cHardware4Stack::Inst_IfGreater()       // Execute next if bx > ?cx?
+{
+  const int stack_used = FindModifiedStack(STACK_AX);
+  const int stack_used2 = (stack_used+1)%NUM_STACKS;
+  if (Stack(stack_used).Top() <= Stack(stack_used2).Top())  IP().Advance();
+  return true;
+}
+
+//21
+bool cHardware4Stack::Inst_HeadPush()
+{
+  const int head_used = FindModifiedHead(HEAD_IP);
+  Stack(STACK_BX).Push(GetHead(head_used).GetPosition());
+  //if (head_used == HEAD_IP) {
+  //  GetHead(head_used).Set(GetHead(HEAD_FLOW));
+  //  AdvanceIP() = false;
+  //}
+  return true;
+}
+
+//22
+bool cHardware4Stack::Inst_HeadPop()
+{
+  const int head_used = FindModifiedHead(HEAD_IP);
+  GetHead(head_used).Set(Stack(STACK_BX).Pop(), 
+			 GetHead(head_used).GetMemSpace(), this);
+  return true;
+}
+
+//23 
+bool cHardware4Stack::Inst_HeadMove()
+{
+  const int head_used = FindModifiedHead(HEAD_IP);
+  if(head_used != HEAD_FLOW)
+    {
+      GetHead(head_used).Set(GetHead(HEAD_FLOW));
+      if (head_used == HEAD_IP) AdvanceIP() = false;
+    }
+  else
+    {
+      threads[cur_thread].heads[HEAD_FLOW]++;
+    }
+  return true;
+}
+
+//24
+bool cHardware4Stack::Inst_Search()
+{
+  ReadLabel();
+  GetLabel().Rotate(2, NUM_NOPS_4STACK);
+  c4StackHead found_pos = FindLabel(0);
+  if(found_pos.GetPosition()-IP().GetPosition()==0)
+    {
+      GetHead(HEAD_FLOW).Set(IP().GetPosition()+1, IP().GetMemSpace(), this);
+      // pushing zero into STACK_AX on a missed search makes it difficult to create
+      // a self-replicating organism.  -law
+      //Stack(STACK_AX).Push(0);
+      Stack(STACK_BX).Push(0);
+    }
+  else
+    {
+      int search_size = found_pos.GetPosition() - IP().GetPosition() + GetLabel().GetSize() + 1;
+      Stack(STACK_BX).Push(search_size);
+      Stack(STACK_AX).Push(GetLabel().GetSize());
+      GetHead(HEAD_FLOW).Set(found_pos);
+    }  
+  
+  return true; 
+}
+
+//25
+bool cHardware4Stack::Inst_PushNext() 
+{
+  int stack_used = FindModifiedStack(STACK_AX);
+  int successor = (stack_used+1)%NUM_STACKS;
+  Stack(successor).Push(Stack(stack_used).Pop());
+  return true;
+}
+
+//26
+bool cHardware4Stack::Inst_PushPrevious() 
+{
+  int stack_used = FindModifiedStack(STACK_BX);
+  int predecessor = (stack_used+NUM_STACKS-1)%NUM_STACKS;
+  Stack(predecessor).Push(Stack(stack_used).Pop());
+  return true;
+}
+
+//27
+bool cHardware4Stack::Inst_PushComplement() 
+{
+  int stack_used = FindModifiedStack(STACK_BX);
+  int complement = FindComplementStack(stack_used);
+  Stack(complement).Push(Stack(stack_used).Pop());
+  return true;
+}
+
+//28
+bool cHardware4Stack::Inst_ValDelete()
+{
+  int stack_used = FindModifiedStack(STACK_BX);
+  Stack(stack_used).Pop();
+  return true;
+}
+
+//29
+bool cHardware4Stack::Inst_ValCopy()
+{
+  const int stack_used = FindModifiedStack(STACK_BX);
+  Stack(stack_used).Push(Stack(stack_used).Top());
+  return true;
+}
+
+//30
+bool cHardware4Stack::Inst_ForkThread()
+{
+  if (!ForkThread()) 
+    Fault(FAULT_LOC_THREAD_FORK, FAULT_TYPE_FORK_TH);
+  else
+    IP().Advance();
+  return true;
+}
+
+//31
+bool cHardware4Stack::Inst_IfLabel()
+{
+  ReadLabel();
+  GetLabel().Rotate(2, NUM_NOPS_4STACK);
+  if (GetLabel() != GetReadLabel())  IP().Advance();
+  return true;
+}
+
+//32
+bool cHardware4Stack::Inst_Increment()
+{
+  const int stack_used = FindModifiedStack(STACK_BX);
+  int value = Stack(stack_used).Pop();
+  Stack(stack_used).Push(++value);
+  return true;
+}
+
+//33
+bool cHardware4Stack::Inst_Decrement()
+{
+  const int stack_used = FindModifiedStack(STACK_BX);
+  int value = Stack(stack_used).Pop();
+  Stack(stack_used).Push(--value);
+  return true;
+}
+
+//34
+bool cHardware4Stack::Inst_Mod()
+{
+  const int stack_used = FindModifiedStack(STACK_BX);
+  if (Stack(STACK_CX).Top() != 0) {
+    if(Stack(STACK_CX).Top() == -1)
+      Stack(stack_used).Push(0);
+    else
+      Stack(stack_used).Push(Stack(STACK_BX).Top() % Stack(STACK_CX).Top());
+  } else {
+    Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "mod: modding by 0");
+  return false;
+  }
+  return true;
+}
+
+//35
+bool cHardware4Stack::Inst_KillThread()
+{
+  if (!KillThread()) Fault(FAULT_LOC_THREAD_KILL, FAULT_TYPE_KILL_TH);
+  else AdvanceIP() = false;
+  return true;
+}
+
+//36
+bool cHardware4Stack::Inst_IO()
+{
+  const int stack_used = FindModifiedStack(STACK_BX);
+
+  // Do the "put" component
+  const int value_out = Stack(stack_used).Top();
+  DoOutput(value_out);  // Check for tasks compleated.
+
+  // Do the "get" component
+  const int value_in = organism->GetInputAt(threads[GetCurThread()].input_pointer);
+  Stack(stack_used).Push(value_in);
+  DoInput(value_in);
+  return true;
+}
+
+int cHardware4Stack::FindFirstEmpty()
+{
+  bool OK=true;
+  const int current_mem_space = IP().GetMemSpace();
+
+  for(int x=1; x<NUM_MEMORY_SPACES; x++)
+    {
+      OK=true;
+      
+      int index = (current_mem_space+x) % NUM_MEMORY_SPACES;
+
+      for(int y=0; y<GetMemory(index).GetSize() && OK; y++)
+	{
+	  if(GetMemory(index)[y].GetOp() >= NUM_NOPS_4STACK)
+	    OK=false; 
+	}
+      for(int y=0; y<GetNumThreads() && OK; y++)
+	{
+	  for(int z=0; z<NUM_HEADS; z++)
+	    {
+	      if(threads[y].heads[z].GetMemSpace() == index)
+		OK=false;
+	    }
+	}
+      if(OK)
+	return index;
+    }
+  return -1;
+}
+
+bool cHardware4Stack::isEmpty(int mem_space_used)
+{
+  for(int x=0; x<GetMemory(mem_space_used).GetSize(); x++)
+    {
+      if(GetMemory(mem_space_used)[x].GetOp() >= NUM_NOPS_4STACK)
+	return false;
+    }
+  return true;
+}
+
+// The inject instruction can be used instead of a divide command, paired
+// with an allocate.  Note that for an inject to work, one needs to have a
+// broad range for sizes allowed to be allocated.
+//
+// This command will cut out from read-head to write-head.
+// It will then look at the template that follows the command and inject it
+// into the complement template found in a neighboring organism.
+
+bool cHardware4Stack::Inst_Inject()
+{
+  double mut_multiplier = 1;
+
+  return InjectParasite(mut_multiplier);
+}
+
+
+
+/*
+bool cHardware4Stack::Inst_InjectRand()
+{
+  // Rotate to a random facing and then run the normal inject instruction
+  const int num_neighbors = organism->GetNeighborhoodSize();
+  organism->Rotate(g_random.GetUInt(num_neighbors));
+  Inst_Inject();
+  return true;
+}
+
+*/
Index: avida/current/source/cpu/hardware_4stack.hh
diff -u /dev/null avida/current/source/cpu/hardware_4stack.hh:1.11
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/cpu/hardware_4stack.hh	Tue Nov 25 09:37:54 2003
@@ -0,0 +1,519 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef HARDWARE_4STACK_HH
+#define HARDWARE_4STACK_HH
+
+#include <iomanip>
+
+#ifndef CPU_MEMORY_HH
+#include "cpu_memory.hh"
+#endif
+#ifndef CPU_STACK_HH
+#include "cpu_stack.hh"
+#endif
+#ifndef DEFS_HH
+#include "defs.hh"
+#endif
+#ifndef FOURSTACK_HEAD_HH
+#include "4stack_head.hh"
+#endif
+#ifndef HARDWARE_BASE_HH
+#include "hardware_base.hh"
+#endif
+#ifndef HARDWARE_4STACK_CONSTANTS_HH
+#include "hardware_4stack_constants.hh"
+#endif
+#ifndef HARDWARE_4STACK_THREAD_HH
+#include "hardware_4stack_thread.hh"
+#endif
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+#ifndef TARRAY_HH
+#include "tArray.hh"
+#endif
+
+class cInstSet;
+class cInstLibBase;
+class cOrganism;
+class cMutation;
+class cInjectGenotype;
+
+#ifdef SINGLE_IO_BUFFER   // For Single IOBuffer vs IOBuffer for each Thread
+# define IO_THREAD 0
+#else
+# define IO_THREAD cur_thread
+#endif
+
+/**
+ * Each organism may have a cHardware4Stack structure which keeps track of the
+ * current status of all the components of the simulated hardware.
+ *
+ * @see cHardware4Stack_Thread, cCPUStack, cCPUMemory, cInstSet
+ **/
+
+class cCodeLabel;
+class cCPUMemory;
+class cCPUStack; // aggregate
+class c4StackHead; // access
+class cGenome;
+class cHardware4Stack_Thread; // access
+class cInjectGenotype;
+class cInstLib4Stack; // access
+class cInstruction;
+class cInstSet;
+class cOrganism;
+class cString; // aggregate
+template <class T> class tArray; // aggregate
+
+class cHardware4Stack : public cHardwareBase {
+public:
+  typedef bool (cHardware4Stack::*tHardware4StackMethod)();
+private:
+  static cInstLib4Stack *s_inst_slib;
+  static cInstLib4Stack *initInstLib(void);
+  tHardware4StackMethod *m_functions;
+private:
+  tArray<cCPUMemory> memory_array;          // Memory...
+  //cCPUStack global_stack;     // A stack that all threads share.
+  cCPUStack global_stacks[NUM_GLOBAL_STACKS];
+  //int thread_time_used;
+
+  tArray<cHardware4Stack_Thread> threads;
+  int thread_id_chart;
+  int cur_thread;
+
+  // Flags...
+  bool mal_active;         // Has an allocate occured since last dividehe?
+  //bool advance_ip;         // Should the IP advance after this instruction?
+
+  // Instruction costs...
+#ifdef INSTRUCTION_COSTS
+  tArray<int> inst_cost;
+  tArray<int> inst_ft_cost;
+#endif
+
+  // Thread slicing...
+
+    // Keeps track of the base thread slicing number for each possible number of threads
+  float slice_array[10]; //***HACK!  How do I do this right? -law
+                         //this wouldn't compile -> [cConfig::GetMaxCPUThreads()+1]***; 
+
+  // Keeps track of fractional instructions that carry over into next update
+  float inst_remainder; 
+
+public:
+  cHardware4Stack(cOrganism * in_organism, cInstSet * in_inst_set);
+  ~cHardware4Stack();
+  void Recycle(cOrganism * new_organism, cInstSet * in_inst_set);
+  static cInstLibBase *GetInstLib();
+  static cString GetDefaultInstFilename() { return "inst_lib.4stack"; }
+  static void WriteDefaultInstSet() { ; }
+
+  void Reset();
+  void SingleProcess(std::ostream * trace_fp=NULL);
+  bool SingleProcess_PayCosts(const cInstruction & cur_inst);
+  bool SingleProcess_ExecuteInst(const cInstruction & cur_inst);
+  void LoadGenome(const cGenome & new_genome);
+
+  // --------  Helper methods  --------
+  bool OK();
+  void PrintStatus(std::ostream & fp);
+
+
+  // --------  Flag Accessors --------
+  bool GetMalActive() const   { return mal_active; }
+
+  // --------  Stack Manipulation...  --------
+  inline void StackFlip();
+  inline int GetStack(int depth=0, int stack_id=-1, int in_thread=-1) const;
+  inline void StackClear();
+  inline void SwitchStack();
+  cString GetActiveStackID(int stackID) const;
+  //retrieves appropriate stack
+  inline cCPUStack & Stack(int stack_id); 
+  inline const cCPUStack & Stack(int stack_id) const;
+  inline cCPUStack & Stack(int stack_id, int in_thread);
+  inline const cCPUStack & Stack(int stack_id, int in_thread) const;
+
+  // --------  Tasks & IO  --------
+  tBuffer<int> & GetInputBuffer() { return threads[cur_thread].input_buf; }
+  tBuffer<int> & GetOutputBuffer() { return threads[cur_thread].output_buf; }
+  void DoInput(const int value);
+  void DoOutput(const int value);
+
+  // --------  Head Manipulation (including IP)  --------
+  inline void SetActiveHead(const int new_head)
+  { threads[cur_thread].cur_head = (UCHAR) new_head; }
+
+  int GetCurHead() const { return threads[cur_thread].cur_head; }
+  
+  const c4StackHead & GetHead(int head_id) const
+  { return threads[cur_thread].heads[head_id]; }
+  c4StackHead & GetHead(int head_id) 
+  { return threads[cur_thread].heads[head_id];}
+  
+  const c4StackHead & GetHead(int head_id, int thread) const
+  { return threads[thread].heads[head_id]; }
+  c4StackHead & GetHead(int head_id, int thread) 
+  { return threads[thread].heads[head_id];}
+
+  const c4StackHead & GetActiveHead() const { return GetHead(GetCurHead()); }
+  c4StackHead & GetActiveHead() { return GetHead(GetCurHead()); }
+
+  void AdjustHeads();
+
+  inline const c4StackHead & IP() const
+    { return threads[cur_thread].heads[HEAD_IP]; }
+  inline c4StackHead & IP() { return threads[cur_thread].heads[HEAD_IP]; }
+
+  inline const c4StackHead & IP(int thread) const
+  { return threads[thread].heads[HEAD_IP]; }
+  inline c4StackHead & IP(int thread) 
+  { return threads[thread].heads[HEAD_IP]; }
+
+
+  inline const bool & AdvanceIP() const
+    { return threads[cur_thread].advance_ip; }
+  inline bool & AdvanceIP() { return threads[cur_thread].advance_ip; }
+
+  // --------  Label Manipulation  -------
+  void ReadLabel(int max_size=MAX_LABEL_SIZE);
+  const cCodeLabel & GetLabel() const 
+    { return threads[cur_thread].next_label; }
+  cCodeLabel & GetLabel() { return threads[cur_thread].next_label; }
+  const cCodeLabel & GetReadLabel() const
+    { return threads[cur_thread].read_label; }
+  cCodeLabel & GetReadLabel() { return threads[cur_thread].read_label; }
+
+
+  // --------  Register Manipulation  --------
+  //int Register(int reg_id) const { return threads[cur_thread].reg[reg_id]; }
+  //int & Register(int reg_id) { return threads[cur_thread].reg[reg_id]; }
+
+  // --------  Memory Manipulation  --------}
+  inline cCPUMemory & GetMemory();
+  inline cCPUMemory & GetMemory(int mem_space);
+  inline const cCPUMemory & GetMemory(int mem_space) const;
+  inline const cCPUMemory & GetMemory() const;
+
+  // --------  Thread Manipulation  --------
+  bool ForkThread(); // Adds a new thread based off of cur_thread.
+  bool KillThread(); // Kill the current thread!
+  inline void PrevThread(); // Shift the current thread in use.
+  inline void NextThread();
+  inline void SetThread(int value);
+  inline cInjectGenotype * GetCurThreadOwner(); 
+  inline cInjectGenotype * GetThreadOwner(int in_thread);
+  inline void SetThreadOwner(cInjectGenotype * in_genotype);
+
+  // --------  Tests  --------
+
+  int TestParasite() const;
+
+  // --------  Accessors  --------
+  //int GetThreadTimeUsed() const { return thread_time_used; }
+  int GetNumThreads() const     { return threads.GetSize(); }
+  int GetCurThread() const      { return cur_thread; }
+  int GetCurThreadID() const    { return threads[cur_thread].GetID(); }
+
+  int GetThreadDist() const {
+    if (GetNumThreads() == 1) return 0;
+    return threads[0].heads[HEAD_IP].GetPosition() -
+      threads[1].heads[HEAD_IP].GetPosition();
+  }
+
+  // Complex label manipulation...
+  c4StackHead 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);
+  c4StackHead FindLabel(const cCodeLabel & in_label, int direction);
+  c4StackHead FindFullLabel(const cCodeLabel & in_label);
+
+  int GetType() const { return HARDWARE_TYPE_CPU_4STACK; }
+  bool InjectParasite(double mut_multiplier);
+  bool InjectHost(const cCodeLabel & in_label, const cGenome & injection);
+  int InjectThread(const cCodeLabel &, const cGenome &) { return -1; }
+  void Mutate(const int mut_point);
+  int PointMutate(const double mut_rate);
+  int FindFirstEmpty();
+  bool isEmpty(int mem_space_used);
+
+  bool TriggerMutations(int trigger);
+  bool TriggerMutations(int trigger, c4StackHead & cur_head);
+  bool TriggerMutations_ScopeGenome(const cMutation * cur_mut,
+        cCPUMemory & target_memory, c4StackHead & cur_head, const double rate);
+  bool TriggerMutations_ScopeLocal(const cMutation * cur_mut,
+        cCPUMemory & target_memory, c4StackHead & cur_head, const double rate);
+  int TriggerMutations_ScopeGlobal(const cMutation * cur_mut,
+        cCPUMemory & target_memory, c4StackHead & cur_head, const double rate);
+  void TriggerMutations_Body(int type, cCPUMemory & target_memory,
+			     c4StackHead & cur_head);
+
+  void ReadInst(const int in_inst);
+
+  void SaveState(std::ostream & fp);
+  void LoadState(std::istream & fp);
+
+  void InitInstSet(const cString & filename, cInstSet & inst_set);
+  cString ConvertToInstruction(int mem_space_used);
+
+
+private:
+ 
+ /////////---------- Instruction Helpers ------------//////////
+
+  int FindModifiedStack(int default_stack);
+  int FindModifiedHead(int default_head);
+  int FindComplementStack(int base_stack);
+
+  void Fault(int fault_loc, int fault_type, cString fault_desc=""); 
+  bool Allocate_Necro(const int new_size);
+  bool Allocate_Random(const int old_size, const int new_size);
+  bool Allocate_Default(const int new_size);
+  bool Allocate_Main(const int allocated_size);
+
+  bool Divide_Main(const int mem_space_used, double mut_multiplier=1);
+  bool Divide_CheckViable(const int parent_size, const int child_size, const int mem_space);
+  void Divide_DoMutations(double mut_multiplier=1);
+  void Inject_DoMutations(double mut_multiplier, cCPUMemory & injected_code);
+  void Divide_TestFitnessMeasures();
+
+  bool HeadCopy_ErrorCorrect(double reduction);
+  bool Inst_HeadDivideMut(double mut_multiplier=1);
+
+public:
+  /////////---------- Instruction Library ------------//////////
+
+  //6
+  bool Inst_ShiftR();
+  //7
+  bool Inst_ShiftL();
+  //8
+  bool Inst_Val_Nand();
+  //9
+  bool Inst_Val_Add();
+  //10
+  bool Inst_Val_Sub();
+  //11
+  bool Inst_Val_Mult();
+  //12
+  bool Inst_Val_Div();
+  //13
+  bool Inst_SetMemory();
+  //14
+  bool Inst_Divide();
+  //15
+  bool Inst_HeadRead();
+  //16
+  bool Inst_HeadWrite();
+  //??
+  bool Inst_HeadCopy();
+  //17
+  bool Inst_IfEqual();
+  //18
+  bool Inst_IfNotEqual();
+  //19
+  bool Inst_IfLess();
+  //20
+  bool Inst_IfGreater();
+  //21
+  bool Inst_HeadPush();
+  //22
+  bool Inst_HeadPop();
+  //23
+  bool Inst_HeadMove();
+  //24
+  bool Inst_Search();
+  //25
+  bool Inst_PushNext();
+  //26
+  bool Inst_PushPrevious();
+  //27
+  bool Inst_PushComplement();
+  //28
+  bool Inst_ValDelete();
+  //29
+  bool Inst_ValCopy();
+  //30
+  bool Inst_ForkThread();
+  //31
+  bool Inst_IfLabel();
+  //32
+  bool Inst_Increment();
+  //33
+  bool Inst_Decrement();
+  //34
+  bool Inst_Mod();
+  //35 
+  bool Inst_KillThread();
+  //36
+  bool Inst_IO();
+  //37
+  bool Inst_Inject();
+  
+  /*
+  bool Inst_InjectRand();
+  bool Inst_InjectThread();
+  bool Inst_Repro();
+  */
+ 
+};
+
+
+//////////////////
+//  cHardware4Stack
+//////////////////
+
+//Not used, but here to satisfy the requirements of HardwareBase
+inline const cCPUMemory & cHardware4Stack::GetMemory() const
+{
+  return memory_array[0];
+}
+
+//Not used, but here to satisfy the requirements of HardwareBase 
+inline cCPUMemory & cHardware4Stack::GetMemory()
+{
+  return memory_array[0];
+}
+
+inline const cCPUMemory & cHardware4Stack::GetMemory(int mem_space) const
+{
+  if(mem_space >= NUM_MEMORY_SPACES)
+    mem_space %= NUM_MEMORY_SPACES;
+  return memory_array[mem_space];
+}
+
+inline cCPUMemory & cHardware4Stack::GetMemory(int mem_space)
+{
+ if(mem_space >= NUM_MEMORY_SPACES)
+    mem_space %= NUM_MEMORY_SPACES;
+  return memory_array[mem_space];
+}
+
+inline void cHardware4Stack::NextThread()
+{
+  cur_thread++;
+  if (cur_thread >= GetNumThreads()) cur_thread = 0;
+}
+
+inline void cHardware4Stack::PrevThread()
+{
+  if (cur_thread == 0) cur_thread = GetNumThreads() - 1;
+  else cur_thread--;
+}
+
+inline void cHardware4Stack::SetThread(int value)
+{
+  if (value>=0 && value < GetNumThreads())
+    cur_thread=value;
+}
+
+inline cInjectGenotype * cHardware4Stack::GetCurThreadOwner() 
+{ 
+  return threads[cur_thread].owner; 
+}
+
+inline cInjectGenotype * cHardware4Stack::GetThreadOwner(int thread) 
+{ 
+  return threads[thread].owner; 
+}
+
+inline void cHardware4Stack::SetThreadOwner(cInjectGenotype * in_genotype)
+{ 
+  threads[cur_thread].owner = in_genotype; 
+}
+
+/*inline void cHardware4Stack::StackFlip()
+{
+  if (threads[cur_thread].cur_stack == 0) {
+    threads[cur_thread].stack.Flip();
+  } else {
+    global_stack.Flip();
+  }
+}*/
+
+inline int cHardware4Stack::GetStack(int depth, int stack_id, int in_thread) const
+{
+  if(stack_id<0 || stack_id>NUM_STACKS) stack_id=0;
+  
+  if(in_thread==-1)
+    in_thread=cur_thread;
+  
+  return Stack(stack_id, in_thread).Get(depth);
+}
+
+//inline void cHardware4Stack::StackClear()
+//{
+  
+  //if (threads[cur_thread].cur_stack == 0) {
+  //  threads[cur_thread].stack.Clear();
+  //} else {
+  //  global_stack.Clear();
+  //}
+//}
+
+//inline void cHardware4Stack::SwitchStack()
+//{
+//  threads[cur_thread].cur_stack++;
+//  if (threads[cur_thread].cur_stack > 1) threads[cur_thread].cur_stack = 0;
+//}
+
+inline cCPUStack& cHardware4Stack::Stack(int stack_id)
+{
+  if(stack_id >= NUM_STACKS)
+    {
+      stack_id=0;
+    }
+  if(stack_id < NUM_LOCAL_STACKS)
+    return threads[cur_thread].local_stacks[stack_id];
+  else
+    return global_stacks[stack_id % NUM_LOCAL_STACKS];
+}
+
+inline const cCPUStack& cHardware4Stack::Stack(int stack_id) const 
+{
+  if(stack_id >= NUM_STACKS)
+    {
+      stack_id=0;
+    }
+  if(stack_id < NUM_LOCAL_STACKS)
+    return threads[cur_thread].local_stacks[stack_id];
+  else
+    return global_stacks[stack_id % NUM_LOCAL_STACKS];
+}
+
+inline cCPUStack& cHardware4Stack::Stack(int stack_id, int in_thread) 
+{
+  if(stack_id >= NUM_STACKS)
+      stack_id=0;
+  if(in_thread >= threads.GetSize())
+      in_thread=cur_thread;
+
+  if(stack_id < NUM_LOCAL_STACKS)
+    return threads[in_thread].local_stacks[stack_id];
+  else
+    return global_stacks[stack_id % NUM_LOCAL_STACKS];
+}
+
+inline const cCPUStack& cHardware4Stack::Stack(int stack_id, int in_thread) const 
+{
+  if(stack_id >= NUM_STACKS)
+      stack_id=0;
+  if(in_thread >= threads.GetSize())
+      in_thread=cur_thread;
+
+  if(stack_id < NUM_LOCAL_STACKS)
+    return threads[in_thread].local_stacks[stack_id];
+  else
+    return global_stacks[stack_id % NUM_LOCAL_STACKS];
+}
+
+#endif
Index: avida/current/source/cpu/hardware_base.cc
diff -u /dev/null avida/current/source/cpu/hardware_base.cc:1.14
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/cpu/hardware_base.cc	Tue Nov 25 09:37:55 2003
@@ -0,0 +1,64 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef HARDWARE_BASE_HH
+#include "hardware_base.hh"
+#endif
+
+#ifndef INST_SET_HH
+#include "inst_set.hh"
+#endif
+
+using namespace std;
+
+int cHardwareBase::instance_count(0);
+
+cHardwareBase::cHardwareBase(cOrganism * in_organism, cInstSet * in_inst_set)
+  : organism(in_organism)
+  , inst_set(in_inst_set)
+  , viewer_lock(-1)
+{
+  assert(inst_set->OK());
+  assert(organism != NULL);
+
+  instance_count++;
+}
+
+cHardwareBase::~cHardwareBase()
+{
+  instance_count--;
+}
+
+void cHardwareBase::Recycle(cOrganism * new_organism, cInstSet * in_inst_set)
+{
+  assert(inst_set->OK());
+  assert(new_organism != NULL);
+
+  organism    = new_organism;
+  inst_set    = in_inst_set;
+  viewer_lock = -1;
+}
+
+bool cHardwareBase::Inst_Nop()          // Do Nothing.
+{
+  return true;
+}
+
+
+int cHardwareBase::GetNumInst()
+{
+  assert(inst_set != NULL);
+  return inst_set->GetSize();
+}
+
+
+cInstruction cHardwareBase::GetRandomInst()
+{
+  assert(inst_set != NULL);
+  return inst_set->GetRandomInst();
+}
+
Index: avida/current/source/cpu/hardware_base.hh
diff -u /dev/null avida/current/source/cpu/hardware_base.hh:1.22
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/cpu/hardware_base.hh	Tue Nov 25 09:37:55 2003
@@ -0,0 +1,83 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef HARDWARE_BASE_HH
+#define HARDWARE_BASE_HH
+
+#include <iostream>
+
+#ifndef INSTRUCTION_HH
+#include "instruction.hh"
+#endif
+
+class cCodeLabel;
+class cCPUMemory;
+class cGenome;
+class cInstruction; // aggregate
+class cInstSet;
+class cOrganism;
+
+class cHardwareBase {
+protected:
+  cOrganism * organism;       // Organism using this hardware.
+  cInstSet * inst_set;        // Instruction set being used.
+  int viewer_lock;            // Used if the viewer should only lock onto
+                              //  one aspect of the hardware.
+
+  static int instance_count;
+public:
+  cHardwareBase(cOrganism * in_organism, cInstSet * in_inst_set);
+  virtual ~cHardwareBase();
+  virtual void Recycle(cOrganism * new_organism, cInstSet * in_inst_set);
+
+  // --------  Organism ---------
+  cOrganism * GetOrganism() { return organism; }
+
+  // --------  Instruction Library  --------
+  const cInstSet & GetInstSet() { return *inst_set; }
+  int GetNumInst();
+  cInstruction GetRandomInst();
+  virtual void SetInstSet(cInstSet & in_inst_set) { inst_set = &in_inst_set; }
+
+  // --------  No-Operation Instruction --------
+  bool Inst_Nop();  // A no-operation instruction that does nothing! 
+
+  // --------  Interaction with Viewer --------
+  int & ViewerLock() { return viewer_lock; }
+
+  // --------  Core Functionality  --------
+  virtual void Reset() = 0;
+  virtual void SingleProcess(std::ostream * trace_fp=NULL) = 0;
+  virtual void LoadGenome(const cGenome & new_genome) = 0;
+  virtual bool OK() = 0;
+
+  // --------  Other Virtual Tools --------
+  virtual int GetType() const = 0;
+  virtual bool InjectHost(const cCodeLabel & in_label,
+		      const cGenome & injection) = 0;
+  virtual int InjectThread(const cCodeLabel & in_label,
+			   const cGenome & injection) = 0;
+
+  // --------  Input and Output --------
+  virtual void PrintStatus(std::ostream & fp) = 0;
+  virtual void SaveState(std::ostream & fp) = 0;
+  virtual void LoadState(std::istream & fp) = 0;
+
+
+  // --------  Mutations (Must be Virtual)  --------
+  virtual int PointMutate(const double mut_rate) = 0;
+  virtual bool TriggerMutations(int trigger) = 0;
+
+  // --------  @CAO Should be rethought?  --------
+  virtual cCPUMemory & GetMemory() = 0;
+  virtual cCPUMemory & GetMemory(int) = 0;
+
+  // --------  DEBUG ---------
+  static int GetInstanceCount() { return instance_count; }
+};
+
+#endif
Index: avida/current/source/cpu/hardware_cpu.cc
diff -u /dev/null avida/current/source/cpu/hardware_cpu.cc:1.62
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/cpu/hardware_cpu.cc	Tue Nov 25 09:37:55 2003
@@ -0,0 +1,3244 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef HARDWARE_CPU_HH
+#include "hardware_cpu.hh"
+#endif
+
+#ifndef CONFIG_HH
+#include "config.hh"
+#endif
+#ifndef CPU_TEST_INFO_HH
+#include "cpu_test_info.hh"
+#endif
+#ifndef FUNCTIONS_HH
+#include "functions.hh"
+#endif
+#ifndef GENOME_UTIL_HH
+#include "genome_util.hh"
+#endif
+#ifndef GENOTYPE_HH
+#include "genotype.hh"
+#endif
+#ifndef INST_LIB_BASE_HH
+#include "inst_lib_base.hh"
+#endif
+#ifndef INST_SET_HH
+#include "inst_set.hh"
+#endif
+#ifndef MUTATION_HH
+#include "mutation.hh"
+#endif
+#ifndef MUTATION_LIB_HH
+#include "mutation_lib.hh"
+#endif
+#ifndef MUTATION_MACROS_HH
+#include "mutation_macros.hh"
+#endif
+#ifndef ORGANISM_HH
+#include "organism.hh"
+#endif
+#ifndef PHENOTYPE_HH
+#include "phenotype.hh"
+#endif
+#ifndef STRING_UTIL_HH
+#include "string_util.hh"
+#endif
+#ifndef TEST_CPU_HH
+#include "test_cpu.hh"
+#endif
+
+#include <limits.h>
+#include <fstream>
+
+using namespace std;
+
+
+
+
+///////////////
+//  cInstLibCPU
+///////////////
+
+class cInstLibCPU : public cInstLibBase {
+  const size_t m_nopmods_array_size;
+  const size_t m_function_array_size;
+  cString *m_nopmod_names;
+  cString *m_function_names;
+  const int *m_nopmods;
+  cHardwareCPU::tHardwareCPUMethod *m_functions;
+  static const cInstruction inst_error;
+  static const cInstruction inst_default;
+public:
+  cInstLibCPU(
+    size_t nopmod_array_size,
+    size_t function_array_size,
+    cString *nopmod_names,
+    cString *function_names,
+    const int *nopmods,
+    cHardwareCPU::tHardwareCPUMethod *functions
+  ):m_nopmods_array_size(nopmod_array_size),
+    m_function_array_size(function_array_size),
+    m_nopmod_names(nopmod_names),
+    m_function_names(function_names),
+    m_nopmods(nopmods),
+    m_functions(functions)
+  {}
+  cHardwareCPU::tHardwareCPUMethod *GetFunctions(void){ return m_functions; } 
+  const cString &GetName(const unsigned int id) {
+    assert(id < m_function_array_size);
+    return m_function_names[id];
+  }
+  const cString &GetNopName(const unsigned int id) {
+    assert(id < m_nopmods_array_size);
+    return m_nopmod_names[id];
+  }
+  int GetNopMod(const unsigned int id){
+    assert(id < m_nopmods_array_size);
+    return m_nopmods[id];
+  }
+  int GetNopMod(const cInstruction & inst){
+    return GetNopMod(inst.GetOp());
+  }
+  int GetSize(){ return m_function_array_size; }
+  int GetNumNops(){ return m_nopmods_array_size; }
+  cInstruction GetInst(const cString & in_name){
+    for (unsigned int i = 0; i < m_function_array_size; i++) {
+      if (m_function_names[i] == in_name) return cInstruction(i);
+    }
+    return cInstLibCPU::GetInstError();
+  }
+  const cInstruction & GetInstDefault(){ return inst_default; }
+  const cInstruction & GetInstError(){ return inst_error; }
+};
+
+///////////////
+//  cHardwareCPU
+///////////////
+
+const cInstruction cInstLibCPU::inst_error(255);
+const cInstruction cInstLibCPU::inst_default(0);
+cInstLibBase *cHardwareCPU::GetInstLib(){ return s_inst_slib; }
+
+cInstLibCPU *cHardwareCPU::s_inst_slib = cHardwareCPU::initInstLib();
+cInstLibCPU *cHardwareCPU::initInstLib(void){
+  struct cNOPEntryCPU {
+    cString name;
+    int nop_mod;
+    cNOPEntryCPU(const cString &name, int nop_mod)
+      : name(name), nop_mod(nop_mod) {}
+  };
+  static const cNOPEntryCPU s_n_array[] = {
+    cNOPEntryCPU("nop-A", REG_AX),
+    cNOPEntryCPU("nop-B", REG_BX),
+    cNOPEntryCPU("nop-C", REG_CX)
+  };
+
+  struct cInstEntryCPU { 
+    const cString name;
+    const tHardwareCPUMethod function;
+    const bool is_default;
+    const cString desc;
+
+    cInstEntryCPU(const cString & _name, tHardwareCPUMethod _fun,
+		  bool _def=false, const cString & _desc="")
+      : name(_name), function(_fun), is_default(_def), desc(_desc) {}
+  };
+  static const cInstEntryCPU s_f_array[] = {
+    /*
+    Note: all entries of cNOPEntryCPU s_n_array must have corresponding
+    in the same order in cInstEntryCPU s_f_array, and these entries must
+    be the first elements of s_f_array.
+    */
+    cInstEntryCPU("nop-A",     &cHardwareCPU::Inst_Nop, true,
+		  "No-operation instruction; modifies other instructions"),
+    cInstEntryCPU("nop-B",     &cHardwareCPU::Inst_Nop, true,
+		  "No-operation instruction; modifies other instructions"),
+    cInstEntryCPU("nop-C",     &cHardwareCPU::Inst_Nop, true,
+		  "No-operation instruction; modifies other instructions"),
+
+    cInstEntryCPU("NULL",      &cHardwareCPU::Inst_Nop, false,
+		  "True no-operation instruction: does nothing"),
+    cInstEntryCPU("nop-X",     &cHardwareCPU::Inst_Nop, false,
+		  "True no-operation instruction: does nothing"),
+    cInstEntryCPU("if-equ-0",  &cHardwareCPU::Inst_If0, false,
+		  "Execute next instruction if ?BX?==0, else skip it"),
+    cInstEntryCPU("if-not-0",  &cHardwareCPU::Inst_IfNot0, false,
+		  "Execute next instruction if ?BX?!=0, else skip it"),
+    cInstEntryCPU("if-n-equ",  &cHardwareCPU::Inst_IfNEqu, true,
+		  "Execute next instruction if ?BX?!=?CX?, else skip it"),
+    cInstEntryCPU("if-equ",    &cHardwareCPU::Inst_IfEqu, false,
+		  "Execute next instruction if ?BX?==?CX?, else skip it"),
+    cInstEntryCPU("if-grt-0",  &cHardwareCPU::Inst_IfGr0),
+    cInstEntryCPU("if-grt",    &cHardwareCPU::Inst_IfGr),
+    cInstEntryCPU("if->=-0",   &cHardwareCPU::Inst_IfGrEqu0),
+    cInstEntryCPU("if->=",     &cHardwareCPU::Inst_IfGrEqu),
+    cInstEntryCPU("if-les-0",  &cHardwareCPU::Inst_IfLess0),
+    cInstEntryCPU("if-less",   &cHardwareCPU::Inst_IfLess, true,
+		  "Execute next instruction if ?BX? < ?CX?, else skip it"),
+    cInstEntryCPU("if-<=-0",   &cHardwareCPU::Inst_IfLsEqu0),
+    cInstEntryCPU("if-<=",     &cHardwareCPU::Inst_IfLsEqu),
+    cInstEntryCPU("if-A!=B",   &cHardwareCPU::Inst_IfANotEqB),
+    cInstEntryCPU("if-B!=C",   &cHardwareCPU::Inst_IfBNotEqC),
+    cInstEntryCPU("if-A!=C",   &cHardwareCPU::Inst_IfANotEqC),
+    cInstEntryCPU("if-bit-1",  &cHardwareCPU::Inst_IfBit1),
+
+    cInstEntryCPU("jump-f",    &cHardwareCPU::Inst_JumpF),
+    cInstEntryCPU("jump-b",    &cHardwareCPU::Inst_JumpB),
+    cInstEntryCPU("jump-p",    &cHardwareCPU::Inst_JumpP),
+    cInstEntryCPU("jump-slf",  &cHardwareCPU::Inst_JumpSelf),
+    cInstEntryCPU("call",      &cHardwareCPU::Inst_Call),
+    cInstEntryCPU("return",    &cHardwareCPU::Inst_Return),
+
+    cInstEntryCPU("pop",       &cHardwareCPU::Inst_Pop, true,
+		  "Remove top number from stack and place into ?BX?"),
+    cInstEntryCPU("push",      &cHardwareCPU::Inst_Push, true,
+		  "Copy number from ?BX? and place it into the stack"),
+    cInstEntryCPU("swap-stk",  &cHardwareCPU::Inst_SwitchStack, true,
+		  "Toggle which stack is currently being used"),
+    cInstEntryCPU("flip-stk",  &cHardwareCPU::Inst_FlipStack),
+    cInstEntryCPU("swap",      &cHardwareCPU::Inst_Swap, true,
+		  "Swap the contents of ?BX? with ?CX?"),
+    cInstEntryCPU("swap-AB",   &cHardwareCPU::Inst_SwapAB),
+    cInstEntryCPU("swap-BC",   &cHardwareCPU::Inst_SwapBC),
+    cInstEntryCPU("swap-AC",   &cHardwareCPU::Inst_SwapAC),
+    cInstEntryCPU("copy-reg",  &cHardwareCPU::Inst_CopyReg),
+    cInstEntryCPU("set_A=B",   &cHardwareCPU::Inst_CopyRegAB),
+    cInstEntryCPU("set_A=C",   &cHardwareCPU::Inst_CopyRegAC),
+    cInstEntryCPU("set_B=A",   &cHardwareCPU::Inst_CopyRegBA),
+    cInstEntryCPU("set_B=C",   &cHardwareCPU::Inst_CopyRegBC),
+    cInstEntryCPU("set_C=A",   &cHardwareCPU::Inst_CopyRegCA),
+    cInstEntryCPU("set_C=B",   &cHardwareCPU::Inst_CopyRegCB),
+    cInstEntryCPU("reset",     &cHardwareCPU::Inst_Reset),
+
+    cInstEntryCPU("pop-A",     &cHardwareCPU::Inst_PopA),
+    cInstEntryCPU("pop-B",     &cHardwareCPU::Inst_PopB),
+    cInstEntryCPU("pop-C",     &cHardwareCPU::Inst_PopC),
+    cInstEntryCPU("push-A",    &cHardwareCPU::Inst_PushA),
+    cInstEntryCPU("push-B",    &cHardwareCPU::Inst_PushB),
+    cInstEntryCPU("push-C",    &cHardwareCPU::Inst_PushC),
+
+    cInstEntryCPU("shift-r",   &cHardwareCPU::Inst_ShiftR, true,
+		  "Shift bits in ?BX? right by one (divide by two)"),
+    cInstEntryCPU("shift-l",   &cHardwareCPU::Inst_ShiftL, true,
+		  "Shift bits in ?BX? left by one (multiply by two)"),
+    cInstEntryCPU("bit-1",     &cHardwareCPU::Inst_Bit1),
+    cInstEntryCPU("set-num",   &cHardwareCPU::Inst_SetNum),
+    cInstEntryCPU("inc",       &cHardwareCPU::Inst_Inc, true,
+		  "Increment ?BX? by one"),
+    cInstEntryCPU("dec",       &cHardwareCPU::Inst_Dec, true,
+		  "Decrement ?BX? by one"),
+    cInstEntryCPU("zero",      &cHardwareCPU::Inst_Zero, false,
+		  "Set ?BX? to zero"),
+    cInstEntryCPU("neg",       &cHardwareCPU::Inst_Neg),
+    cInstEntryCPU("square",    &cHardwareCPU::Inst_Square),
+    cInstEntryCPU("sqrt",      &cHardwareCPU::Inst_Sqrt),
+    cInstEntryCPU("not",       &cHardwareCPU::Inst_Not),
+    cInstEntryCPU("minus-17",  &cHardwareCPU::Inst_Minus17),
+    
+    cInstEntryCPU("add",       &cHardwareCPU::Inst_Add, true,
+		  "Add BX to CX and place the result in ?BX?"),
+    cInstEntryCPU("sub",       &cHardwareCPU::Inst_Sub, true,
+		  "Subtract CX from BX and place the result in ?BX?"),
+    cInstEntryCPU("mult",      &cHardwareCPU::Inst_Mult, false,
+		  "Multiple BX by CX and place the result in ?BX?"),
+    cInstEntryCPU("div",       &cHardwareCPU::Inst_Div, false,
+		  "Divide BX by CX and place the result in ?BX?"),
+    cInstEntryCPU("mod",       &cHardwareCPU::Inst_Mod),
+    cInstEntryCPU("nand",      &cHardwareCPU::Inst_Nand, true,
+		  "Nand BX by CX and place the result in ?BX?"),
+    cInstEntryCPU("nor",       &cHardwareCPU::Inst_Nor),
+    cInstEntryCPU("and",       &cHardwareCPU::Inst_And),
+    cInstEntryCPU("order",     &cHardwareCPU::Inst_Order),
+    cInstEntryCPU("xor",       &cHardwareCPU::Inst_Xor),
+    
+    cInstEntryCPU("copy",      &cHardwareCPU::Inst_Copy),
+    cInstEntryCPU("read",      &cHardwareCPU::Inst_ReadInst),
+    cInstEntryCPU("write",     &cHardwareCPU::Inst_WriteInst),
+    cInstEntryCPU("stk-read",  &cHardwareCPU::Inst_StackReadInst),
+    cInstEntryCPU("stk-writ",  &cHardwareCPU::Inst_StackWriteInst),
+    
+    cInstEntryCPU("compare",   &cHardwareCPU::Inst_Compare),
+    cInstEntryCPU("if-n-cpy",  &cHardwareCPU::Inst_IfNCpy),
+    cInstEntryCPU("allocate",  &cHardwareCPU::Inst_Allocate),
+    cInstEntryCPU("divide",    &cHardwareCPU::Inst_Divide),
+    cInstEntryCPU("c-alloc",   &cHardwareCPU::Inst_CAlloc),
+    cInstEntryCPU("c-divide",  &cHardwareCPU::Inst_CDivide),
+    cInstEntryCPU("inject",    &cHardwareCPU::Inst_Inject),
+    cInstEntryCPU("inject-r",  &cHardwareCPU::Inst_InjectRand),
+    cInstEntryCPU("get",       &cHardwareCPU::Inst_TaskGet),
+    cInstEntryCPU("stk-get",   &cHardwareCPU::Inst_TaskStackGet),
+    cInstEntryCPU("stk-load",  &cHardwareCPU::Inst_TaskStackLoad),
+    cInstEntryCPU("put",       &cHardwareCPU::Inst_TaskPut),
+    cInstEntryCPU("IO",        &cHardwareCPU::Inst_TaskIO, true,
+		  "Output ?BX?, and input new number back into ?BX?"),
+    cInstEntryCPU("search-f",  &cHardwareCPU::Inst_SearchF),
+    cInstEntryCPU("search-b",  &cHardwareCPU::Inst_SearchB),
+    cInstEntryCPU("mem-size",  &cHardwareCPU::Inst_MemSize),
+
+    cInstEntryCPU("rotate-l",  &cHardwareCPU::Inst_RotateL),
+    cInstEntryCPU("rotate-r",  &cHardwareCPU::Inst_RotateR),
+
+    cInstEntryCPU("set-cmut",  &cHardwareCPU::Inst_SetCopyMut),
+    cInstEntryCPU("mod-cmut",  &cHardwareCPU::Inst_ModCopyMut),
+
+    // Threading instructions
+    cInstEntryCPU("fork-th",   &cHardwareCPU::Inst_ForkThread),
+    cInstEntryCPU("kill-th",   &cHardwareCPU::Inst_KillThread),
+    cInstEntryCPU("id-th",     &cHardwareCPU::Inst_ThreadID),
+
+    // Head-based instructions
+    cInstEntryCPU("h-alloc",   &cHardwareCPU::Inst_MaxAlloc, true,
+		  "Allocate maximum allowed space"),
+    cInstEntryCPU("h-divide",  &cHardwareCPU::Inst_HeadDivide, true,
+		  "Divide code between read and write heads."),
+    cInstEntryCPU("h-read",    &cHardwareCPU::Inst_HeadRead),
+    cInstEntryCPU("h-write",   &cHardwareCPU::Inst_HeadWrite),
+    cInstEntryCPU("h-copy",    &cHardwareCPU::Inst_HeadCopy, true,
+		  "Copy from read-head to write-head; advance both"),
+    cInstEntryCPU("h-search",  &cHardwareCPU::Inst_HeadSearch, true,
+		  "Find complement template and make with flow head"),
+    cInstEntryCPU("h-push",    &cHardwareCPU::Inst_HeadPush),
+    cInstEntryCPU("h-pop",     &cHardwareCPU::Inst_HeadPop),
+    cInstEntryCPU("set-head",  &cHardwareCPU::Inst_SetHead),
+    cInstEntryCPU("adv-head",  &cHardwareCPU::Inst_AdvanceHead),
+    cInstEntryCPU("mov-head",  &cHardwareCPU::Inst_MoveHead, true,
+		  "Move head ?IP? to the flow head"),
+    cInstEntryCPU("jmp-head",  &cHardwareCPU::Inst_JumpHead, true,
+		  "Move head ?IP? by amount in CX register; CX = old pos."),
+    cInstEntryCPU("get-head",  &cHardwareCPU::Inst_GetHead, true,
+		  "Copy the position of the ?IP? head into CX"),
+    cInstEntryCPU("if-label",  &cHardwareCPU::Inst_IfLabel, true,
+		  "Execute next if we copied complement of attached label"),
+    cInstEntryCPU("set-flow",  &cHardwareCPU::Inst_SetFlow, true,
+		  "Set flow-head to position in ?CX?"),
+
+    cInstEntryCPU("h-copy2",    &cHardwareCPU::Inst_HeadCopy2),
+    cInstEntryCPU("h-copy3",    &cHardwareCPU::Inst_HeadCopy3),
+    cInstEntryCPU("h-copy4",    &cHardwareCPU::Inst_HeadCopy4),
+    cInstEntryCPU("h-copy5",    &cHardwareCPU::Inst_HeadCopy5),
+    cInstEntryCPU("h-copy6",    &cHardwareCPU::Inst_HeadCopy6),
+    cInstEntryCPU("h-copy7",    &cHardwareCPU::Inst_HeadCopy7),
+    cInstEntryCPU("h-copy8",    &cHardwareCPU::Inst_HeadCopy8),
+    cInstEntryCPU("h-copy9",    &cHardwareCPU::Inst_HeadCopy9),
+    cInstEntryCPU("h-copy10",   &cHardwareCPU::Inst_HeadCopy10),
+
+    cInstEntryCPU("divide-sex",    &cHardwareCPU::Inst_HeadDivideSex),
+    cInstEntryCPU("divide-asex",   &cHardwareCPU::Inst_HeadDivideAsex),
+
+    cInstEntryCPU("div-sex",    &cHardwareCPU::Inst_HeadDivideSex),
+    cInstEntryCPU("div-asex",   &cHardwareCPU::Inst_HeadDivideAsex),
+    cInstEntryCPU("div-asex-w",   &cHardwareCPU::Inst_HeadDivideAsexWait),
+
+    cInstEntryCPU("h-divide1",      &cHardwareCPU::Inst_HeadDivide1),
+    cInstEntryCPU("h-divide2",      &cHardwareCPU::Inst_HeadDivide2),
+    cInstEntryCPU("h-divide3",      &cHardwareCPU::Inst_HeadDivide3),
+    cInstEntryCPU("h-divide4",      &cHardwareCPU::Inst_HeadDivide4),
+    cInstEntryCPU("h-divide5",      &cHardwareCPU::Inst_HeadDivide5),
+    cInstEntryCPU("h-divide6",      &cHardwareCPU::Inst_HeadDivide6),
+    cInstEntryCPU("h-divide7",      &cHardwareCPU::Inst_HeadDivide7),
+    cInstEntryCPU("h-divide8",      &cHardwareCPU::Inst_HeadDivide8),
+    cInstEntryCPU("h-divide9",      &cHardwareCPU::Inst_HeadDivide9),
+    cInstEntryCPU("h-divide10",     &cHardwareCPU::Inst_HeadDivide10),
+    cInstEntryCPU("h-divide16",     &cHardwareCPU::Inst_HeadDivide16),
+    cInstEntryCPU("h-divide32",     &cHardwareCPU::Inst_HeadDivide32),
+    cInstEntryCPU("h-divide50",     &cHardwareCPU::Inst_HeadDivide50),
+    cInstEntryCPU("h-divide100",    &cHardwareCPU::Inst_HeadDivide100),
+    cInstEntryCPU("h-divide500",    &cHardwareCPU::Inst_HeadDivide500),
+    cInstEntryCPU("h-divide1000",   &cHardwareCPU::Inst_HeadDivide1000),
+    cInstEntryCPU("h-divide5000",   &cHardwareCPU::Inst_HeadDivide5000),
+    cInstEntryCPU("h-divide10000",  &cHardwareCPU::Inst_HeadDivide10000),
+    cInstEntryCPU("h-divide50000",  &cHardwareCPU::Inst_HeadDivide50000),
+    cInstEntryCPU("h-divide0.5",    &cHardwareCPU::Inst_HeadDivide0_5),
+    cInstEntryCPU("h-divide0.1",    &cHardwareCPU::Inst_HeadDivide0_1),
+    cInstEntryCPU("h-divide0.05",   &cHardwareCPU::Inst_HeadDivide0_05),
+    cInstEntryCPU("h-divide0.01",   &cHardwareCPU::Inst_HeadDivide0_01),
+    cInstEntryCPU("h-divide0.001",  &cHardwareCPU::Inst_HeadDivide0_001),
+
+    // High-level instructions
+    cInstEntryCPU("repro",      &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-A",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-B",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-C",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-D",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-E",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-F",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-G",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-H",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-I",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-J",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-K",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-L",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-M",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-N",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-O",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-P",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-Q",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-R",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-S",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-T",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-U",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-V",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-W",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-X",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-Y",    &cHardwareCPU::Inst_Repro),
+    cInstEntryCPU("repro-Z",    &cHardwareCPU::Inst_Repro),
+
+	// Jeff and Sherri
+	cInstEntryCPU("kazi",		&cHardwareCPU::Inst_Kazi),
+
+    // Placebo instructions
+    // nop-x (included with nops)
+    cInstEntryCPU("skip",      &cHardwareCPU::Inst_Skip)
+  };
+
+  const int n_size = sizeof(s_n_array)/sizeof(cNOPEntryCPU);
+
+  cout << "<cHardwareCPU::initInstLib> Instruction Library has "
+  << n_size << " instructions." << endl;
+
+
+  static cString n_names[n_size];
+  static int nop_mods[n_size];
+  for (int i = 0; i < n_size; i++){
+    n_names[i] = s_n_array[i].name;
+    nop_mods[i] = s_n_array[i].nop_mod;
+  }
+
+  const int f_size = sizeof(s_f_array)/sizeof(cInstEntryCPU);
+  static cString f_names[f_size];
+  static tHardwareCPUMethod functions[f_size];
+  for (int i = 0; i < f_size; i++){
+    f_names[i] = s_f_array[i].name;
+    functions[i] = s_f_array[i].function;
+  }
+
+  cInstLibCPU *inst_lib = new cInstLibCPU(
+    n_size,
+    f_size,
+    n_names,
+    f_names,
+    nop_mods,
+    functions
+  );
+
+  cout <<
+  "<cHardwareCPU::initInstLib> debug: important post-init values:" <<endl<<
+  " --- GetSize(): " << inst_lib->GetSize() <<endl<<
+  " --- GetNumNops(): " << inst_lib->GetNumNops() <<endl<<
+  " --- GetName(last): " <<
+  inst_lib->GetName(inst_lib->GetSize() - 1) <<endl<<
+  endl;
+
+  return inst_lib;
+}
+
+cHardwareCPU::cHardwareCPU(cOrganism * in_organism, cInstSet * in_inst_set)
+  : cHardwareBase(in_organism, in_inst_set)
+{
+  /* FIXME:  reorganize storage of m_functions.  -- kgn */
+  m_functions = s_inst_slib->GetFunctions();
+  /**/
+  memory = in_organism->GetGenome();  // Initialize memory...
+  Reset();                            // Setup the rest of the hardware...
+}
+
+
+cHardwareCPU::~cHardwareCPU()
+{
+}
+
+
+void cHardwareCPU::Recycle(cOrganism * new_organism, cInstSet * in_inst_set)
+{
+  cHardwareBase::Recycle(new_organism, in_inst_set);
+  memory = new_organism->GetGenome();
+  Reset();
+}
+
+
+void cHardwareCPU::Reset()
+{
+  global_stack.Clear();
+  thread_time_used = 0;
+
+  // We want to reset to have a single thread.
+  threads.Resize(1);
+
+  // Reset that single thread.
+  threads[0].Reset(this, 0);
+  thread_id_chart = 1; // Mark only the first thread as taken...
+  cur_thread = 0;
+
+  mal_active = false;
+
+#ifdef INSTRUCTION_COSTS
+  // instruction cost arrays
+  const int num_inst_cost = GetNumInst();
+  inst_cost.Resize(num_inst_cost);
+  inst_ft_cost.Resize(num_inst_cost);
+
+  for (int i = 0; i < num_inst_cost; i++) {
+    inst_cost[i] = GetInstSet().GetCost(cInstruction(i));
+    inst_ft_cost[i] = GetInstSet().GetFTCost(cInstruction(i));
+  }
+#endif
+
+}
+
+
+// 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.
+
+void cHardwareCPU::SingleProcess(ostream * trace_fp)
+{
+  organism->GetPhenotype().IncTimeUsed();
+  if (GetNumThreads() > 1) thread_time_used++;
+
+  // If we have threads turned on and we executed each thread in a single
+  // timestep, adjust the number of instructions executed accordingly.
+  const int num_inst_exec = (cConfig::GetThreadSlicingMethod() == 1) ?
+    GetNumThreads() : 1;
+  
+  for (int i = 0; i < num_inst_exec; i++) {
+    // Setup the hardware for the next instruction to be executed.
+    NextThread();
+    advance_ip = true;
+    IP().Adjust();
+
+#ifdef BREAKPOINTS
+    if (IP().FlagBreakpoint() == true) {
+      organism->DoBreakpoint();
+    }
+#endif
+    
+    // Print the status of this CPU at each step...
+    if (trace_fp != NULL) organism->PrintStatus(*trace_fp);
+    
+    // Find the instruction to be executed
+    const cInstruction & cur_inst = IP().GetInst();
+
+    // Test if costs have been paid and it is okay to execute this now...
+    const bool exec = SingleProcess_PayCosts(cur_inst);
+
+    // Now execute the instruction...
+    if (exec == true) {
+      SingleProcess_ExecuteInst(cur_inst);
+
+      // Some instruction (such as jump) may turn advance_ip off.  Ususally
+      // we now want to move to the next instruction in the memory.
+      if (advance_ip == true) IP().Advance();
+    } // if exec
+    
+  } // Previous was executed once for each thread...
+
+  // Kill creatures who have reached their max num of instructions executed
+  const int max_executed = organism->GetMaxExecuted();
+  if ( max_executed > 0 &&
+       organism->GetPhenotype().GetTimeUsed() >= max_executed ) {
+    organism->Die();
+  }
+}
+
+
+// This method will test to see if all costs have been paid associated
+// with executing an instruction and only return true when that instruction
+// should proceed.
+bool cHardwareCPU::SingleProcess_PayCosts(const cInstruction & cur_inst)
+{
+#ifdef INSTRUCTION_COSTS
+  assert(cur_inst.GetOp() < inst_cost.GetSize());
+
+  // If first time cost hasn't been paid off...
+  if ( inst_ft_cost[cur_inst.GetOp()] > 0 ) {
+    inst_ft_cost[cur_inst.GetOp()]--;       // dec cost
+    return false;
+  }
+    
+  // Next, look at the per use cost
+  if ( GetInstSet().GetCost(cur_inst) > 0 ) {
+    if ( inst_cost[cur_inst.GetOp()] > 1 ){  // if isn't paid off (>1)
+      inst_cost[cur_inst.GetOp()]--;         // dec cost
+      return false;
+    } else {                                 // else, reset cost array
+      inst_cost[cur_inst.GetOp()] = GetInstSet().GetCost(cur_inst);
+    }
+  }
+    
+  // Prob of exec
+  if ( GetInstSet().GetProbFail(cur_inst) > 0.0 ){
+    return !( g_random.P(GetInstSet().GetProbFail(cur_inst)) );
+  }
+#endif
+  return true;
+}
+
+// This method will handle the actuall execution of an instruction
+// within single process, once that function has been finalized.
+bool cHardwareCPU::SingleProcess_ExecuteInst(const cInstruction & cur_inst) 
+{
+  // Get a pointer to the corrisponding method...
+  int inst_idx = GetInstSet().GetLibFunctionIndex(cur_inst);
+      
+  // Mark the instruction as executed
+  IP().FlagExecuted() = true;
+	
+#ifdef EXECUTION_ERRORS
+  // If there is an execution error, execute a random instruction.
+  if (organism->TestExeErr()) inst_idx = GetInstSet().GetRandFunctionIndex();
+#endif /* EXECUTION_ERRORS */
+	
+#ifdef INSTRUCTION_COUNT
+  // instruction execution count incremeneted
+  organism->GetPhenotype().IncCurInstCount(cur_inst.GetOp());
+#endif
+	
+  // And execute it.
+  const bool exec_success
+  //= (this->*(s_inst_slib->GetFunctions()[inst_idx]))();
+  = (this->*(m_functions[inst_idx]))();
+	
+#ifdef INSTRUCTION_COUNT
+  // decremenet if the instruction was not executed successfully
+  if (exec_success == false) {
+    organism->GetPhenotype().DecCurInstCount(cur_inst.GetOp());
+  }
+#endif	
+
+  return exec_success;
+}
+
+
+
+void cHardwareCPU::LoadGenome(const cGenome & new_genome)
+{
+  GetMemory() = new_genome;
+}
+
+
+bool cHardwareCPU::OK()
+{
+  bool result = true;
+
+  if (!memory.OK()) result = false;
+
+  for (int i = 0; i < GetNumThreads(); i++) {
+    assert (threads[i].input_pointer < IO_SIZE);
+
+    if (threads[i].stack.OK() == false) result = false;
+    if (threads[i].next_label.OK() == false) result = false;
+  }
+
+  return result;
+}
+
+void cHardwareCPU::PrintStatus(ostream & fp)
+{
+  fp << organism->GetPhenotype().GetTimeUsed() << " "
+     << "IP:" << IP().GetPosition() << "    "
+
+     << "AX:" << Register(REG_AX) << " "
+     << setbase(16) << "[0x" << Register(REG_AX) << "]  " << setbase(10)
+
+     << "BX:" << Register(REG_BX) << " "
+     << setbase(16) << "[0x" << Register(REG_BX) << "]  " << setbase(10)
+
+     << "CX:" << Register(REG_CX) << " "
+     << setbase(16) << "[0x" << Register(REG_CX) << "]" << setbase(10)
+
+     << endl;
+
+  fp << "  R-Head:" << GetHead(HEAD_READ).GetPosition() << " "
+     << "W-Head:" << GetHead(HEAD_WRITE).GetPosition()  << " "
+     << "F-Head:" << GetHead(HEAD_FLOW).GetPosition()   << "  "
+     << "RL:" << GetReadLabel().AsString() << "   "
+     << "NEXT: >> " << inst_set->GetName(IP().GetInst())() << " <<"
+     << endl;
+
+  fp << "  Mem (" << GetMemory().GetSize() << "):"
+		  << "  " << GetMemory().AsString()
+		  << endl;
+  fp.flush();
+}
+
+
+void cHardwareCPU::DoInput(const int value)
+{
+  organism->DoInput(value, GetInputBuffer(), GetOutputBuffer());
+}
+
+void cHardwareCPU::DoOutput(const int value)
+{
+  organism->DoOutput(value, GetInputBuffer(), GetOutputBuffer());
+}
+
+
+
+
+/////////////////////////////////////////////////////////////////////////
+// Method: cHardwareCPU::FindLabel(direction)
+//
+// Search in 'direction' (+ or - 1) from the instruction pointer for the
+// compliment of the label in 'next_label' and return a pointer to the
+// results.  If direction is 0, search from the beginning of the genome.
+//
+/////////////////////////////////////////////////////////////////////////
+
+cCPUHead cHardwareCPU::FindLabel(int direction)
+{
+  cCPUHead & inst_ptr = IP();
+
+  // Start up a search head at the position of the instruction pointer.
+  cCPUHead search_head(inst_ptr);
+  cCodeLabel & search_label = GetLabel();
+
+  // Make sure the label is of size > 0.
+
+  if (search_label.GetSize() == 0) {
+    return inst_ptr;
+  }
+
+  // Call special functions depending on if jump is forwards or backwards.
+  int found_pos = 0;
+  if( direction < 0 ) {
+    found_pos = FindLabel_Backward(search_label, inst_ptr.GetMemory(),
+			   inst_ptr.GetPosition() - search_label.GetSize());
+  }
+
+  // Jump forward.
+  else if (direction > 0) {
+    found_pos = FindLabel_Forward(search_label, inst_ptr.GetMemory(),
+			   inst_ptr.GetPosition());
+  }
+
+  // Jump forward from the very beginning.
+  else {
+    found_pos = FindLabel_Forward(search_label, inst_ptr.GetMemory(), 0);
+  }
+  
+  // Return the last line of the found label, if it was found.
+  if (found_pos >= 0) search_head.Set(found_pos - 1);
+
+  // Return the found position (still at start point if not found).
+  return search_head;
+}
+
+
+// Search forwards for search_label from _after_ position pos in the
+// memory.  Return the first line _after_ the the found label.  It is okay
+// to find search label's match inside another label.
+
+int cHardwareCPU::FindLabel_Forward(const cCodeLabel & search_label,
+				 const cGenome & search_genome, int pos)
+{
+  assert (pos < search_genome.GetSize() && pos >= 0);
+
+  int search_start = pos;
+  int label_size = search_label.GetSize();
+  bool found_label = false;
+
+  // Move off the template we are on.
+  pos += label_size;
+
+  // Search until we find the complement or exit the memory.
+  while (pos < search_genome.GetSize()) {
+
+    // If we are within a label, rewind to the beginning of it and see if
+    // it has the proper sub-label that we're looking for.
+
+    if (inst_set->IsNop(search_genome[pos])) {
+      // Find the start and end of the label we're in the middle of.
+
+      int start_pos = pos;
+      int end_pos = pos + 1;
+      while (start_pos > search_start &&
+	     inst_set->IsNop( search_genome[start_pos - 1] )) {
+	start_pos--;
+      }
+      while (end_pos < search_genome.GetSize() &&
+	     inst_set->IsNop( search_genome[end_pos] )) {
+	end_pos++;
+      }
+      int test_size = end_pos - start_pos;
+
+      // See if this label has the proper sub-label within it.
+      int max_offset = test_size - label_size + 1;
+      int offset = start_pos;
+      for (offset = start_pos; offset < start_pos + max_offset; offset++) {
+
+	// Test the number of matches for this offset.
+	int matches;
+	for (matches = 0; matches < label_size; matches++) {
+	  if (search_label[matches] !=
+	      inst_set->GetNopMod( search_genome[offset + matches] )) {
+	    break;
+	  }
+	}
+
+	// If we have found it, break out of this loop!
+	if (matches == label_size) {
+	  found_label = true;
+	  break;
+	}
+      }
+
+      // If we've found the complement label, set the position to the end of
+      // the label we found it in, and break out.
+
+      if (found_label == true) {
+	// pos = end_pos;
+	pos = label_size + offset;
+	break;
+      }
+
+      // We haven't found it; jump pos to just after the current label being
+      // checked.
+      pos = end_pos;
+    }
+
+    // Jump up a block to the next possible point to find a label,
+    pos += label_size;
+  }
+
+  // If the label was not found return a -1.
+  if (found_label == false) pos = -1;
+
+  return pos;
+}
+
+// Search backwards for search_label from _before_ position pos in the
+// memory.  Return the first line _after_ the the found label.  It is okay
+// to find search label's match inside another label.
+
+int cHardwareCPU::FindLabel_Backward(const cCodeLabel & search_label,
+				  const cGenome & search_genome, int pos)
+{
+  assert (pos < search_genome.GetSize());
+
+  int search_start = pos;
+  int label_size = search_label.GetSize();
+  bool found_label = false;
+
+  // Move off the template we are on.
+  pos -= label_size;
+
+  // Search until we find the complement or exit the memory.
+  while (pos >= 0) {
+    // If we are within a label, rewind to the beginning of it and see if
+    // it has the proper sub-label that we're looking for.
+
+    if (inst_set->IsNop( search_genome[pos] )) {
+      // Find the start and end of the label we're in the middle of.
+
+      int start_pos = pos;
+      int end_pos = pos + 1;
+      while (start_pos > 0 && inst_set->IsNop(search_genome[start_pos - 1])) {
+	start_pos--;
+      }
+      while (end_pos < search_start &&
+	     inst_set->IsNop(search_genome[end_pos])) {
+	end_pos++;
+      }
+      int test_size = end_pos - start_pos;
+
+      // See if this label has the proper sub-label within it.
+      int max_offset = test_size - label_size + 1;
+      for (int offset = start_pos; offset < start_pos + max_offset; offset++) {
+
+	// Test the number of matches for this offset.
+	int matches;
+	for (matches = 0; matches < label_size; matches++) {
+	  if (search_label[matches] !=
+	      inst_set->GetNopMod(search_genome[offset + matches])) {
+	    break;
+	  }
+	}
+
+	// If we have found it, break out of this loop!
+	if (matches == label_size) {
+	  found_label = true;
+	  break;
+	}
+      }
+
+      // If we've found the complement label, set the position to the end of
+      // the label we found it in, and break out.
+
+      if (found_label == true) {
+	pos = end_pos;
+	break;
+      }
+
+      // We haven't found it; jump pos to just before the current label
+      // being checked.
+      pos = start_pos - 1;
+    }
+
+    // Jump up a block to the next possible point to find a label,
+    pos -= label_size;
+  }
+
+  // If the label was not found return a -1.
+  if (found_label == false) pos = -1;
+
+  return pos;
+}
+
+// Search for 'in_label' anywhere in the hardware.
+cCPUHead cHardwareCPU::FindLabel(const cCodeLabel & in_label, int direction)
+{
+  assert (in_label.GetSize() > 0);
+
+  // IDEALY:
+  // Keep making jumps (in the proper direction) equal to the label
+  // length.  If we are inside of a label, check its size, and see if
+  // any of the sub-labels match properly.
+  // FOR NOW:
+  // Get something which works, no matter how inefficient!!!
+
+  cCPUHead temp_head(this);
+
+  while (temp_head.InMemory()) {
+    // IDEALY: Analyze the label we are in; see if the one we are looking
+    // for could be a sub-label of it.  Skip past it if not.
+
+    int i;
+    for (i = 0; i < in_label.GetSize(); i++) {
+      if (!inst_set->IsNop(temp_head.GetInst()) ||
+	  in_label[i] != inst_set->GetNopMod(temp_head.GetInst())) {
+	break;
+      }
+    }
+    if (i == GetLabel().GetSize()) {
+      temp_head.AbsJump(i - 1);
+      return temp_head;
+    }
+
+    temp_head.AbsJump(direction);     // IDEALY: MAKE LARGER JUMPS
+  }
+
+  temp_head.AbsSet(-1);
+  return temp_head;
+}
+
+// @CAO: direction is not currently used; should be used to indicate the
+// direction which the heads[HEAD_IP] should progress through a creature.
+cCPUHead cHardwareCPU::FindFullLabel(const cCodeLabel & in_label)
+{
+  // cout << "Running FindFullLabel with " << in_label.AsString() <<
+  // endl;
+
+  assert(in_label.GetSize() > 0); // Trying to find label of 0 size!
+
+  cCPUHead temp_head(this);
+
+  while (temp_head.InMemory()) {
+    // If we are not in a label, jump to the next checkpoint...
+    if (inst_set->IsNop(temp_head.GetInst())) {
+      temp_head.AbsJump(in_label.GetSize());
+      continue;
+    }
+
+    // Otherwise, rewind to the begining of this label...
+
+    while (!(temp_head.AtFront()) && inst_set->IsNop(temp_head.GetInst(-1)))
+      temp_head.AbsJump(-1);
+
+    // Calculate the size of the label being checked, and make sure they
+    // are equal.
+
+    int checked_size = 0;
+    while (inst_set->IsNop(temp_head.GetInst(checked_size))) {
+      checked_size++;
+    }
+    if (checked_size != in_label.GetSize()) {
+      temp_head.AbsJump(checked_size + 1);
+      continue;
+    }
+
+    // cout << "Testing label at line " << temp_head.GetPosition() <<
+    // endl;
+
+    // ...and do the comparison...
+
+    int j;
+    bool label_match = true;
+    for (j = 0; j < in_label.GetSize(); j++) {
+      if (!inst_set->IsNop(temp_head.GetInst(j)) ||
+	  in_label[j] != inst_set->GetNopMod(temp_head.GetInst(j))) {
+	temp_head.AbsJump(in_label.GetSize() + 1);
+	label_match = false;
+	break;
+      }
+    }
+
+    if (label_match) {
+      // If we have found the label, return the position after it.
+      temp_head.AbsJump(j - 1);
+      return temp_head;
+    }
+
+    // We have not found the label... increment i.
+
+    temp_head.AbsJump(in_label.GetSize() + 1);
+  }
+
+  // The label does not exist in this creature.
+
+  temp_head.AbsSet(-1);
+  return temp_head;
+}
+
+
+bool cHardwareCPU::InjectHost(const cCodeLabel & in_label, const cGenome & injection)
+{
+  // Make sure the genome will be below max size after injection.
+
+  const int new_size = injection.GetSize() + GetMemory().GetSize();
+  if (new_size > MAX_CREATURE_SIZE) return false; // (inject fails)
+
+  const int inject_line = FindFullLabel(in_label).GetPosition();
+
+  // Abort if no compliment is found.
+  if (inject_line == -1) return false; // (inject fails)
+
+  // Inject the code!
+  InjectCode(injection, inject_line+1);
+
+  return true; // (inject succeeds!)
+}
+
+int cHardwareCPU::InjectThread(const cCodeLabel & in_label, const cGenome & injection)
+{
+  // Make sure the genome will be below max size after injection.
+
+  const int new_size = injection.GetSize() + GetMemory().GetSize();
+  if (new_size > MAX_CREATURE_SIZE) return 1; // (inject fails)
+
+  const int inject_line = FindFullLabel(in_label).GetPosition();
+
+  // Abort if no compliment is found.
+  if (inject_line == -1) return 2; // (inject fails)
+
+  // Inject the code!
+  InjectCodeThread(injection, inject_line+1);
+
+  return 0; // (inject succeeds!)
+}
+
+void cHardwareCPU::InjectCode(const cGenome & inject_code, const int line_num)
+{
+  assert(line_num >= 0);
+  assert(line_num <= memory.GetSize());
+  assert(memory.GetSize() + inject_code.GetSize() < MAX_CREATURE_SIZE);
+
+  // Inject the new code.
+  const int inject_size = inject_code.GetSize();
+  memory.Insert(line_num, inject_code);
+  
+  // Set instruction flags on the injected code
+  for (int i = line_num; i < line_num + inject_size; i++) {
+    memory.FlagInjected(i) = true;
+  }
+  organism->GetPhenotype().IsModified() = true;
+
+  // Adjust all of the heads to take into account the new mem size.
+
+  for (int i=0; i < NUM_HEADS; i++) {    
+    if (!GetHead(i).TestParasite() &&
+	GetHead(i).GetPosition() > line_num)
+      GetHead(i).Jump(inject_size);
+  }
+}
+
+void cHardwareCPU::InjectCodeThread(const cGenome & inject_code, const int line_num)
+{
+  assert(line_num >= 0);
+  assert(line_num <= memory.GetSize());
+  assert(memory.GetSize() + inject_code.GetSize() < MAX_CREATURE_SIZE);
+  
+  if(ForkThread())
+    {
+      // Inject the new code.
+      const int inject_size = inject_code.GetSize();
+      memory.Insert(line_num, inject_code);
+      
+      // Set instruction flags on the injected code
+      for (int i = line_num; i < line_num + inject_size; i++) {
+	memory.FlagInjected(i) = true;
+      }
+      organism->GetPhenotype().IsModified() = true;
+      organism->GetPhenotype().IsMultiThread() = true;
+      
+      // Adjust all of the heads to take into account the new mem size.
+      
+      int currthread = GetCurThread();
+      SetThread(0);
+      for (int i=0; i<GetNumThreads()-2; i++)
+	{
+	  for (int j=0; j < NUM_HEADS; j++) 
+	    {    
+	      if (!GetHead(i).TestParasite() && GetHead(i).GetPosition() > line_num)
+		GetHead(i).Jump(inject_size);
+	    }
+	  NextThread();
+	}
+      SetThread(currthread);
+          
+    }
+  else
+    {
+      //Some kind of error message should go here...but what?
+    }
+
+}
+
+void cHardwareCPU::Mutate(int mut_point)
+{
+  // Test if trying to mutate outside of genome...
+  assert(mut_point >= 0 && mut_point < GetMemory().GetSize());
+
+  GetMemory()[mut_point] = GetRandomInst();
+  GetMemory().FlagMutated(mut_point) = true;
+  GetMemory().FlagPointMut(mut_point) = true;
+  //organism->GetPhenotype().IsMutated() = true;
+  organism->CPUStats().mut_stats.point_mut_count++;
+}
+
+int cHardwareCPU::PointMutate(const double mut_rate)
+{
+  const int num_muts =
+    g_random.GetRandBinomial(GetMemory().GetSize(), mut_rate);
+
+  for (int i = 0; i < num_muts; i++) {
+    const int pos = g_random.GetUInt(GetMemory().GetSize());
+    Mutate(pos);
+  }
+
+  return num_muts;
+}
+
+
+// Trigger mutations of a specific type.  Outside triggers cannot specify
+// a head since hardware types are not known.
+
+bool cHardwareCPU::TriggerMutations(int trigger)
+{
+  // Only update triggers should happen from the outside!
+  assert(trigger == MUTATION_TRIGGER_UPDATE);
+
+  // Assume instruction pointer is the intended target (if one is even
+  // needed!
+
+  return TriggerMutations(trigger, IP());
+}
+
+bool cHardwareCPU::TriggerMutations(int trigger, cCPUHead & cur_head)
+{
+  // Collect information about mutations from the organism.
+  cLocalMutations & mut_info = organism->GetLocalMutations();
+  const tList<cMutation> & mut_list =
+    mut_info.GetMutationLib().GetMutationList(trigger);
+
+  // If we have no mutations for this trigger, stop here.
+  if (mut_list.GetSize() == 0) return false;
+  bool has_mutation = false;
+
+  // Determine what memory this mutation will be affecting.
+  cCPUMemory & target_mem = (trigger == MUTATION_TRIGGER_DIVIDE) 
+    ? organism->ChildGenome() : GetMemory();
+
+  // Loop through all mutations associated with this trigger and test them.
+  tConstListIterator<cMutation> mut_it(mut_list);
+
+  while (mut_it.Next() != NULL) {
+    const cMutation * cur_mut = mut_it.Get();
+    const int mut_id = cur_mut->GetID();
+    const int scope = cur_mut->GetScope();
+    const double rate = mut_info.GetRate(mut_id);
+    switch (scope) {
+    case MUTATION_SCOPE_GENOME:
+      if (TriggerMutations_ScopeGenome(cur_mut, target_mem, cur_head, rate)) {
+	has_mutation = true;
+	mut_info.IncCount(mut_id);
+      }
+      break;
+    case MUTATION_SCOPE_LOCAL:
+    case MUTATION_SCOPE_PROP:
+      if (TriggerMutations_ScopeLocal(cur_mut, target_mem, cur_head, rate)) {
+	has_mutation = true;
+	mut_info.IncCount(mut_id);
+      }
+      break;
+    case MUTATION_SCOPE_GLOBAL:
+    case MUTATION_SCOPE_SPREAD:
+      int num_muts =
+	TriggerMutations_ScopeGlobal(cur_mut, target_mem, cur_head, rate);
+      if (num_muts > 0) {
+	has_mutation = true;
+	mut_info.IncCount(mut_id, num_muts);
+      }
+      break;
+    }
+  }
+
+  return has_mutation;
+}
+
+bool cHardwareCPU::TriggerMutations_ScopeGenome(const cMutation * cur_mut,
+          cCPUMemory & target_memory, cCPUHead & cur_head, const double rate)
+{
+  // The rate we have stored indicates the probability that a single
+  // mutation will occur anywhere in the genome.
+  
+  if (g_random.P(rate) == true) {
+    // We must create a temporary head and use it to randomly determine the
+    // position in the genome to be mutated.
+    cCPUHead tmp_head(cur_head);
+    tmp_head.AbsSet(g_random.GetUInt(target_memory.GetSize()));
+    TriggerMutations_Body(cur_mut->GetType(), target_memory, tmp_head);
+    return true;
+  }
+  return false;
+}
+
+bool cHardwareCPU::TriggerMutations_ScopeLocal(const cMutation * cur_mut,
+          cCPUMemory & target_memory, cCPUHead & cur_head, const double rate)
+{
+  // The rate we have stored is the probability for a mutation at this single
+  // position in the genome.
+
+  if (g_random.P(rate) == true) {
+    TriggerMutations_Body(cur_mut->GetType(), target_memory, cur_head);
+    return true;
+  }
+  return false;
+}
+
+int cHardwareCPU::TriggerMutations_ScopeGlobal(const cMutation * cur_mut,
+          cCPUMemory & target_memory, cCPUHead & cur_head, const double rate)
+{
+  // The probability we have stored is per-site, so we can pull a random
+  // number from a binomial distribution to determine the number of mutations
+  // that should occur.
+
+  const int num_mut =
+    g_random.GetRandBinomial(target_memory.GetSize(), rate);
+
+  if (num_mut > 0) {
+    for (int i = 0; i < num_mut; i++) {
+      cCPUHead tmp_head(cur_head);
+      tmp_head.AbsSet(g_random.GetUInt(target_memory.GetSize()));
+      TriggerMutations_Body(cur_mut->GetType(), target_memory, tmp_head);
+    }
+  }
+
+  return num_mut;
+}
+
+void cHardwareCPU::TriggerMutations_Body(int type, cCPUMemory & target_memory,
+					 cCPUHead & cur_head)
+{
+  const int pos = cur_head.GetPosition();
+
+  switch (type) {
+  case MUTATION_TYPE_POINT:
+    target_memory[pos] = GetRandomInst();
+    target_memory.FlagMutated(pos) = true;
+    break;
+  case MUTATION_TYPE_INSERT:
+  case MUTATION_TYPE_DELETE:
+  case MUTATION_TYPE_HEAD_INC:
+  case MUTATION_TYPE_HEAD_DEC:
+  case MUTATION_TYPE_TEMP:
+  case MUTATION_TYPE_KILL:
+  default:
+    cout << "Error: Mutation type not implemented!" << endl;
+    break;
+  };
+}
+
+void cHardwareCPU::ReadInst(const int in_inst)
+{
+  if (inst_set->IsNop( cInstruction(in_inst) )) {
+    GetReadLabel().AddNop(in_inst);
+  } else {
+    GetReadLabel().Clear();
+  }
+}
+
+
+void cHardwareCPU::AdjustHeads()
+{
+  for (int i = 0; i < GetNumThreads(); i++) {
+    for (int j = 0; j < NUM_HEADS; j++) {
+      threads[i].heads[j].Adjust();
+    }
+  }
+}
+
+
+
+// This function looks at the current position in the info of a creature,
+// and sets the next_label to be the sequence of nops which follows.  The
+// instruction pointer is left on the last line of the label found.
+
+void cHardwareCPU::ReadLabel(int max_size)
+{
+  int count = 0;
+  cCPUHead * inst_ptr = &( IP() );
+
+  GetLabel().Clear();
+
+  while (inst_set->IsNop(inst_ptr->GetNextInst()) &&
+	 (count < max_size)) {
+    count++;
+    inst_ptr->Advance();
+    GetLabel().AddNop(inst_set->GetNopMod(inst_ptr->GetInst()));
+
+    // If this is the first line of the template, mark it executed.
+    if (GetLabel().GetSize() <=	cConfig::GetMaxLabelExeSize()) {
+      inst_ptr->FlagExecuted() = true;
+    }
+  }
+}
+
+
+bool cHardwareCPU::ForkThread()
+{
+  const int num_threads = GetNumThreads();
+  if (num_threads == cConfig::GetMaxCPUThreads()) return false;
+
+  // Make room for the new thread.
+  threads.Resize(num_threads + 1);
+
+  // Initialize the new thread to the same values as the current one.
+  threads[num_threads] = threads[cur_thread];
+
+  // Find the first free bit in thread_id_chart to determine the new
+  // thread id.
+  int new_id = 0;
+  while ( (thread_id_chart >> new_id) & 1 == 1) new_id++;
+  threads[num_threads].SetID(new_id);
+  thread_id_chart |= (1 << new_id);
+
+  return true;
+}
+
+
+int cHardwareCPU::TestParasite() const
+{
+  return IP().TestParasite();
+}
+
+
+bool cHardwareCPU::KillThread()
+{
+  // Make sure that there is always at least one thread...
+  if (GetNumThreads() == 1) return false;
+
+  // Note the current thread and set the current back one.
+  const int kill_thread = cur_thread;
+  PrevThread();
+  
+  // Turn off this bit in the thread_id_chart...
+  thread_id_chart ^= 1 << threads[kill_thread].GetID();
+
+  // Copy the last thread into the kill position
+  const int last_thread = GetNumThreads() - 1;
+  if (last_thread != kill_thread) {
+    threads[kill_thread] = threads[last_thread];
+  }
+
+  // Kill the thread!
+  threads.Resize(GetNumThreads() - 1);
+
+  if (cur_thread > kill_thread) cur_thread--;
+
+  return true;
+}
+
+
+void cHardwareCPU::SaveState(ostream & fp)
+{
+  // note, memory & child_memory handled by cpu (@CAO Not any more!)
+  assert(fp.good());
+
+  fp<<"cHardwareCPU"<<endl;
+
+  // global_stack (in inverse order so load can just push)
+  global_stack.SaveState(fp);
+
+  fp << thread_time_used  << endl;
+  fp << GetNumThreads()   << endl;
+  fp << cur_thread        << endl;
+
+  // Threads
+  for( int i = 0; i < GetNumThreads(); i++ ) {
+    threads[i].SaveState(fp);
+  }
+}
+
+
+void cHardwareCPU::LoadState(istream & fp)
+{
+  // note, memory & child_memory handled by cpu (@CAO Not any more!)
+  assert(fp.good());
+
+  cString foo;
+  fp>>foo;
+  assert( foo == "cHardwareCPU" );
+
+  // global_stack
+  global_stack.LoadState(fp);
+
+  int num_threads;
+  fp >> thread_time_used;
+  fp >> num_threads;
+  fp >> cur_thread;
+
+  // Threads
+  for( int i = 0; i < num_threads; i++ ){
+    threads[i].LoadState(fp);
+  }
+}
+
+
+////////////////////////////
+//  Instruction Helpers...
+////////////////////////////
+
+inline int cHardwareCPU::FindModifiedRegister(int default_register)
+{
+  assert(default_register < NUM_REGISTERS);  // Reg ID too high.
+
+  if (GetInstSet().IsNop(IP().GetNextInst())) {
+    IP().Advance();
+    default_register = GetInstSet().GetNopMod(IP().GetInst());
+    IP().FlagExecuted() = true;
+  }
+  return default_register;
+}
+
+
+inline int cHardwareCPU::FindModifiedHead(int default_head)
+{
+  assert(default_head < NUM_HEADS); // Head ID too high.
+
+  if (GetInstSet().IsNop(IP().GetNextInst())) {
+    IP().Advance();
+    default_head = GetInstSet().GetNopMod(IP().GetInst());
+    IP().FlagExecuted() = true;
+  }
+  return default_head;
+}
+
+
+inline int cHardwareCPU::FindComplementRegister(int base_reg)
+{
+  const int comp_reg = base_reg + 1;
+  return (comp_reg  == NUM_REGISTERS) ? 0 : comp_reg;
+}
+
+
+inline void cHardwareCPU::Fault(int fault_loc, int fault_type, cString fault_desc)
+{
+  organism->Fault(fault_loc, fault_type, fault_desc);
+}
+
+
+bool cHardwareCPU::Allocate_Necro(const int new_size)
+{
+  GetMemory().ResizeOld(new_size);
+  return true;
+}
+
+bool cHardwareCPU::Allocate_Random(const int old_size, const int new_size)
+{
+  GetMemory().Resize(new_size);
+
+  for (int i = old_size; i < new_size; i++) {
+    GetMemory()[i] = GetInstSet().GetRandomInst();
+  }
+  return true;
+}
+
+bool cHardwareCPU::Allocate_Default(const int new_size)
+{
+  GetMemory().Resize(new_size);
+
+  // New space already defaults to default instruction...
+
+  return true;
+}
+
+bool cHardwareCPU::Allocate_Main(const int allocated_size)
+{
+  // must do divide before second allocate & must allocate positive amount...
+  if (cConfig::GetRequireAllocate() && mal_active == true) {
+    Fault(FAULT_LOC_ALLOC, FAULT_TYPE_ERROR, "Allocate already active");
+    return false;
+  }
+  if (allocated_size < 1) {
+    Fault(FAULT_LOC_ALLOC, FAULT_TYPE_ERROR,
+	  cStringUtil::Stringf("Allocate of %d too small", allocated_size));
+    return false;
+  }
+
+  const int old_size = GetMemory().GetSize();
+  const int new_size = old_size + allocated_size;
+
+  // Make sure that the new size is in range.
+  if (new_size > MAX_CREATURE_SIZE  ||  new_size < MIN_CREATURE_SIZE) {
+    Fault(FAULT_LOC_ALLOC, FAULT_TYPE_ERROR,
+	  cStringUtil::Stringf("Invalid post-allocate size (%d)",
+			       new_size));
+    return false;
+  }
+
+  const int max_alloc_size = (int) (old_size * cConfig::GetChildSizeRange());
+  if (allocated_size > max_alloc_size) {
+    Fault(FAULT_LOC_ALLOC, FAULT_TYPE_ERROR,
+	  cStringUtil::Stringf("Allocate too large (%d > %d)",
+			       allocated_size, max_alloc_size));
+    return false;
+  }
+
+  const int max_old_size =
+    (int) (allocated_size * cConfig::GetChildSizeRange());
+  if (old_size > max_old_size) {
+    Fault(FAULT_LOC_ALLOC, FAULT_TYPE_ERROR,
+	  cStringUtil::Stringf("Allocate too small (%d > %d)",
+			       old_size, max_old_size));
+    return false;
+  }
+
+  switch (cConfig::GetAllocMethod()) {
+  case ALLOC_METHOD_NECRO:
+    // Only break if this succeeds -- otherwise just do random.
+    if (Allocate_Necro(new_size) == true) break;
+  case ALLOC_METHOD_RANDOM:
+    Allocate_Random(old_size, new_size);
+    break;
+  case ALLOC_METHOD_DEFAULT:
+    Allocate_Default(new_size);
+    break;
+  }
+
+  mal_active = true;
+
+  return true;
+}
+
+
+bool cHardwareCPU::Divide_CheckViable(const int child_size,
+				      const int parent_size)
+{
+  // Make sure the organism is okay with dividing now...
+  if (organism->Divide_CheckViable() == false) return false; // (divide fails)
+
+  // If required, make sure an allocate has occured.
+  if (cConfig::GetRequireAllocate() && mal_active == false) {
+    Fault(FAULT_LOC_DIVIDE, FAULT_TYPE_ERROR, "Must allocate before divide");
+    return false; //  (divide fails)
+  }
+
+  // Make sure that neither parent nor child will be below the minimum size.
+
+  const int genome_size = organism->GetGenome().GetSize();
+  const double size_range = cConfig::GetChildSizeRange();
+  const int min_size = Max(MIN_CREATURE_SIZE, (int) (genome_size/size_range));
+  const int max_size = Min(MAX_CREATURE_SIZE, (int) (genome_size*size_range));
+  
+  if (child_size < min_size || child_size > max_size) {
+    Fault(FAULT_LOC_DIVIDE, FAULT_TYPE_ERROR,
+	  cStringUtil::Stringf("Invalid offspring length (%d)", child_size));
+    return false; // (divide fails)
+  }
+  if (parent_size < min_size || parent_size > max_size) {
+    Fault(FAULT_LOC_DIVIDE, FAULT_TYPE_ERROR,
+	  cStringUtil::Stringf("Invalid post-divide length (%d)",parent_size));
+    return false; // (divide fails)
+  }
+
+  // Count the number of lines executed in the parent, and make sure the
+  // specified fraction has been reached.
+
+  int executed_size = 0;
+  for (int i = 0; i < parent_size; i++) {
+    if (GetMemory().FlagExecuted(i)) executed_size++;
+  }
+
+  const int min_exe_lines = (int) (parent_size * cConfig::GetMinExeLines());
+  if (executed_size < min_exe_lines) {
+    Fault(FAULT_LOC_DIVIDE, FAULT_TYPE_ERROR,
+	  cStringUtil::Stringf("Too few executed lines (%d < %d)",
+			       executed_size, min_exe_lines));
+    return false; // (divide fails)
+  }
+	
+  // Count the number of lines which were copied into the child, and make
+  // sure the specified fraction has been reached.
+
+  int copied_size = 0;
+  for (int i = parent_size; i < parent_size + child_size; i++) {
+    if (GetMemory().FlagCopied(i)) copied_size++;
+  }
+
+  const int min_copied =  (int) (child_size * cConfig::GetMinCopiedLines());
+  if (copied_size < min_copied) {
+    Fault(FAULT_LOC_DIVIDE, FAULT_TYPE_ERROR,
+	  cStringUtil::Stringf("Too few copied commands (%d < %d)",
+			       copied_size, min_copied));
+    return false; // (divide fails)
+  }
+
+  // Save the information we collected here...
+  cPhenotype & phenotype = organism->GetPhenotype();
+  phenotype.SetLinesExecuted(executed_size);
+  phenotype.SetLinesCopied(copied_size);
+
+  // Determine the fitness of this organism as compared to its parent...
+  if (cConfig::GetTestSterilize() == true &&
+      phenotype.IsInjected() == false) {
+    const int merit_base =
+      cPhenotype::CalcSizeMerit(genome_size, copied_size, executed_size);
+    const double cur_fitness =
+      merit_base * phenotype.GetCurBonus() / phenotype.GetTimeUsed();
+    const double fitness_ratio = cur_fitness / phenotype.GetLastFitness();
+
+
+    //  const double neut_min = parent_fitness * FITNESS_NEUTRAL_MIN;
+    //  const double neut_max = parent_fitness * FITNESS_NEUTRAL_MAX;
+  
+    bool sterilize = false;
+  
+    if (fitness_ratio < FITNESS_NEUTRAL_MIN) {
+      if (g_random.P(organism->GetSterilizeNeg())) sterilize = true;
+    } else if (fitness_ratio <= FITNESS_NEUTRAL_MAX) {
+      if (g_random.P(organism->GetSterilizeNeut())) sterilize = true;
+    } else {
+      if (g_random.P(organism->GetSterilizePos())) sterilize = true;
+    }
+  
+//     cout << "[ min(" << genome_size
+// 	 << "," << copied_size
+// 	 << "," << executed_size
+// 	 << ") * " << phenotype.GetCurBonus()
+// 	 << " / " << phenotype.GetTimeUsed()
+// 	 << "] / " << phenotype.GetLastFitness()
+// 	 << " == " << fitness_ratio;
+
+    if (sterilize == true) {
+      //Don't let this organism have this or any more children!
+      phenotype.IsFertile() = false;
+      return false;
+    }    
+  }
+
+  return true; // (divide succeeds!)
+}
+
+
+void cHardwareCPU::Divide_DoMutations(double mut_multiplier)
+{
+  sCPUStats & cpu_stats = organism->CPUStats();
+  cCPUMemory & child_genome = organism->ChildGenome();
+  
+  organism->GetPhenotype().SetDivType(mut_multiplier);
+
+  // Divide Mutations
+  if (organism->TestDivideMut()) {
+    const UINT mut_line = g_random.GetUInt(child_genome.GetSize());
+    child_genome[mut_line] = GetRandomInst();
+    cpu_stats.mut_stats.divide_mut_count++;
+  }
+
+  // Divide Insertions
+  if (organism->TestDivideIns() && child_genome.GetSize() < MAX_CREATURE_SIZE){
+    const UINT mut_line = g_random.GetUInt(child_genome.GetSize() + 1);
+    child_genome.Insert(mut_line, GetRandomInst());
+    cpu_stats.mut_stats.divide_insert_mut_count++;
+  }
+
+  // Divide Deletions
+  if (organism->TestDivideDel() && child_genome.GetSize() > MIN_CREATURE_SIZE){
+    const UINT mut_line = g_random.GetUInt(child_genome.GetSize());
+    // if( child_genome.FlagCopied(mut_line) == true) copied_size_change--;
+    child_genome.Remove(mut_line);
+    cpu_stats.mut_stats.divide_delete_mut_count++;
+  }
+
+  // Divide Mutations (per site)
+  if(organism->GetDivMutProb() > 0){
+    int num_mut = g_random.GetRandBinomial(child_genome.GetSize(), 
+				   	   organism->GetDivMutProb() / mut_multiplier);
+    // If we have lines to mutate...
+    if( num_mut > 0 ){
+      for (int i = 0; i < num_mut; i++) {
+	int site = g_random.GetUInt(child_genome.GetSize());
+	child_genome[site]=GetRandomInst();
+	cpu_stats.mut_stats.div_mut_count++;
+      }
+    }
+  }
+
+
+  // Insert Mutations (per site)
+  if(organism->GetInsMutProb() > 0){
+    int num_mut = g_random.GetRandBinomial(child_genome.GetSize(),
+					   organism->GetInsMutProb());
+    // If would make creature to big, insert up to MAX_CREATURE_SIZE
+    if( num_mut + child_genome.GetSize() > MAX_CREATURE_SIZE ){
+      num_mut = MAX_CREATURE_SIZE - child_genome.GetSize();
+    }
+    // If we have lines to insert...
+    if( num_mut > 0 ){
+      // Build a list of the sites where mutations occured
+      static int mut_sites[MAX_CREATURE_SIZE];
+      for (int i = 0; i < num_mut; i++) {
+	mut_sites[i] = g_random.GetUInt(child_genome.GetSize() + 1);
+      }
+      // Sort the list
+      qsort( (void*)mut_sites, num_mut, sizeof(int), &IntCompareFunction );
+      // Actually do the mutations (in reverse sort order)
+      for(int i = num_mut-1; i >= 0; i--) {
+	child_genome.Insert(mut_sites[i], GetRandomInst());
+	cpu_stats.mut_stats.insert_mut_count++;
+      }
+    }
+  }
+
+
+  // Delete Mutations (per site)
+  if( organism->GetDelMutProb() > 0 ){
+    int num_mut = g_random.GetRandBinomial(child_genome.GetSize(),
+					   organism->GetDelMutProb());
+    // If would make creature too small, delete down to MIN_CREATURE_SIZE
+    if (child_genome.GetSize() - num_mut < MIN_CREATURE_SIZE) {
+      num_mut = child_genome.GetSize() - MIN_CREATURE_SIZE;
+    }
+
+    // If we have lines to delete...
+    for (int i = 0; i < num_mut; i++) {
+      int site = g_random.GetUInt(child_genome.GetSize());
+      // if (child_genome.FlagCopied(site) == true) copied_size_change--;
+      child_genome.Remove(site);
+      cpu_stats.mut_stats.delete_mut_count++;
+    }
+  }
+
+  // Mutations in the parent's genome
+  if (organism->GetParentMutProb() > 0) {
+    for (int i = 0; i < GetMemory().GetSize(); i++) {
+      if (organism->TestParentMut()) {
+	GetMemory()[i] = GetRandomInst();
+	cpu_stats.mut_stats.parent_mut_line_count++;
+      }
+    }
+  }
+
+
+  // Count up mutated lines
+  for(int i = 0; i < GetMemory().GetSize(); i++){
+    if (GetMemory().FlagPointMut(i) == true) {
+      cpu_stats.mut_stats.point_mut_line_count++;
+    }
+  }
+  for(int i = 0; i < child_genome.GetSize(); i++){
+    if( child_genome.FlagCopyMut(i) == true) {
+      cpu_stats.mut_stats.copy_mut_line_count++;
+    }
+  }
+}
+
+
+// test whether the offspring creature contains an advantageous mutation.
+void cHardwareCPU::Divide_TestFitnessMeasures()
+{
+  cPhenotype & phenotype = organism->GetPhenotype();
+  phenotype.CopyTrue() = ( organism->ChildGenome() == organism->GetGenome() );
+  phenotype.ChildFertile() = true;
+
+  // Only continue if we're supposed to do a fitness test on divide...
+  if (organism->GetTestOnDivide() == false) return;
+
+  // If this was a perfect copy, then we don't need to worry about any other
+  // tests...  Theoretically, we need to worry about the parent changing,
+  // but as long as the child is always compared to the original genotype,
+  // this won't be an issue.
+  if (phenotype.CopyTrue() == true) return;
+
+  const double parent_fitness = organism->GetTestFitness();
+  const double neut_min = parent_fitness * FITNESS_NEUTRAL_MIN;
+  const double neut_max = parent_fitness * FITNESS_NEUTRAL_MAX;
+  
+  cCPUTestInfo test_info;
+  test_info.UseRandomInputs();
+  cTestCPU::TestGenome(test_info, organism->ChildGenome());
+  const double child_fitness = test_info.GetGenotypeFitness();
+  
+  bool revert = false;
+  bool sterilize = false;
+  
+  // If implicit mutations are turned off, make sure this won't spawn one.
+  if (organism->GetFailImplicit() == true) {
+    if (test_info.GetMaxDepth() > 0) sterilize = true;
+  }
+  
+  if (child_fitness == 0.0) {
+    // Fatal mutation... test for reversion.
+    if (g_random.P(organism->GetRevertFatal())) revert = true;
+    if (g_random.P(organism->GetSterilizeFatal())) sterilize = true;
+  } else if (child_fitness < neut_min) {
+    if (g_random.P(organism->GetRevertNeg())) revert = true;
+    if (g_random.P(organism->GetSterilizeNeg())) sterilize = true;
+  } else if (child_fitness <= neut_max) {
+    if (g_random.P(organism->GetRevertNeut())) revert = true;
+    if (g_random.P(organism->GetSterilizeNeut())) sterilize = true;
+  } else {
+    if (g_random.P(organism->GetRevertPos())) revert = true;
+    if (g_random.P(organism->GetSterilizePos())) sterilize = true;
+  }
+  
+  // Ideally, we won't have reversions and sterilizations turned on at the
+  // same time, but if we do, give revert the priority.
+  if (revert == true) {
+    organism->ChildGenome() = organism->GetGenome();
+  }
+
+  if (sterilize == true) {
+    organism->GetPhenotype().ChildFertile() = false;
+  }
+}
+
+
+bool cHardwareCPU::Divide_Main(const int div_point, const int extra_lines, double mut_multiplier)
+{
+  const int child_size = GetMemory().GetSize() - div_point - extra_lines;
+
+  // Make sure this divide will produce a viable offspring.
+  const bool viable = Divide_CheckViable(child_size, div_point);
+  if (viable == false) return false;
+
+  // Since the divide will now succeed, set up the information to be sent
+  // to the new organism
+  cGenome & child_genome = organism->ChildGenome();
+  child_genome = cGenomeUtil::Crop(memory, div_point, div_point+child_size);
+
+  // Cut off everything in this memory past the divide point.
+  GetMemory().Resize(div_point);
+
+  // Handle Divide Mutations...
+  Divide_DoMutations(mut_multiplier);
+
+  // Many tests will require us to run the offspring through a test CPU;
+  // this is, for example, to see if mutations need to be reverted or if
+  // lineages need to be updated.
+  Divide_TestFitnessMeasures();
+
+#ifdef INSTRUCTION_COSTS
+  // reset first time instruction costs
+  for (int i = 0; i < inst_ft_cost.GetSize(); i++) {
+    inst_ft_cost[i] = GetInstSet().GetFTCost(cInstruction(i));
+  }
+#endif
+
+  mal_active = false;
+  if (cConfig::GetDivideMethod() == DIVIDE_METHOD_SPLIT) {
+    advance_ip = false;
+  }
+
+  // Activate the child, and do more work if the parent lives through the
+  // birth.
+  bool parent_alive = organism->ActivateDivide();
+  if (parent_alive) {
+    if (cConfig::GetDivideMethod() == DIVIDE_METHOD_SPLIT) Reset();
+  }
+
+  return true;
+}
+
+
+//////////////////////////
+// And the instructions...
+//////////////////////////
+
+bool cHardwareCPU::Inst_If0()          // Execute next if ?bx? ==0.
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  if (Register(reg_used) != 0)  IP().Advance();
+  return true; 
+}
+
+bool cHardwareCPU::Inst_IfNot0()       // Execute next if ?bx? != 0.
+{ 
+  const int reg_used = FindModifiedRegister(REG_BX);
+  if (Register(reg_used) == 0)  IP().Advance();
+  return true;
+}
+
+bool cHardwareCPU::Inst_IfEqu()      // Execute next if bx == ?cx?
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  const int reg_used2 = FindComplementRegister(reg_used);
+  if (Register(reg_used) != Register(reg_used2))  IP().Advance();
+  return true;
+}
+
+bool cHardwareCPU::Inst_IfNEqu()     // Execute next if bx != ?cx?
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  const int reg_used2 = FindComplementRegister(reg_used);
+  if (Register(reg_used) == Register(reg_used2))  IP().Advance();
+  return true;
+}
+
+bool cHardwareCPU::Inst_IfGr0()       // Execute next if ?bx? ! < 0.
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  if (Register(reg_used) <= 0)  IP().Advance();
+  return true;
+}
+
+bool cHardwareCPU::Inst_IfGr()       // Execute next if bx > ?cx?
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  const int reg_used2 = FindComplementRegister(reg_used);
+  if (Register(reg_used) <= Register(reg_used2))  IP().Advance();
+  return true;
+}
+
+bool cHardwareCPU::Inst_IfGrEqu0()       // Execute next if ?bx? != 0.
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  if (Register(reg_used) < 0)  IP().Advance();
+  return true;
+}
+
+bool cHardwareCPU::Inst_IfGrEqu()       // Execute next if bx > ?cx?
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  const int reg_used2 = FindComplementRegister(reg_used);
+  if (Register(reg_used) < Register(reg_used2)) IP().Advance();
+  return true;
+}
+
+bool cHardwareCPU::Inst_IfLess0()       // Execute next if ?bx? != 0.
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  if (Register(reg_used) >= 0)  IP().Advance();
+  return true;
+}
+
+bool cHardwareCPU::Inst_IfLess()       // Execute next if ?bx? < ?cx?
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  const int reg_used2 = FindComplementRegister(reg_used);
+  if (Register(reg_used) >=  Register(reg_used2))  IP().Advance();
+  return true;
+}
+
+bool cHardwareCPU::Inst_IfLsEqu0()       // Execute next if ?bx? != 0.
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  if (Register(reg_used) > 0) IP().Advance();
+  return true;
+}
+
+bool cHardwareCPU::Inst_IfLsEqu()       // Execute next if bx > ?cx?
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  const int reg_used2 = FindComplementRegister(reg_used);
+  if (Register(reg_used) >  Register(reg_used2))  IP().Advance();
+  return true;
+}
+
+bool cHardwareCPU::Inst_IfBit1()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  if ((Register(reg_used) & 1) == 0)  IP().Advance();
+  return true;
+}
+
+bool cHardwareCPU::Inst_IfANotEqB()     // Execute next if AX != BX
+{
+  if (Register(REG_AX) == Register(REG_BX) )  IP().Advance();
+  return true;
+}
+
+bool cHardwareCPU::Inst_IfBNotEqC()     // Execute next if BX != CX
+{
+  if (Register(REG_BX) == Register(REG_CX) )  IP().Advance();
+  return true;
+}
+
+bool cHardwareCPU::Inst_IfANotEqC()     // Execute next if AX != BX
+{
+  if (Register(REG_AX) == Register(REG_CX) )  IP().Advance();
+  return true;
+}
+
+bool cHardwareCPU::Inst_JumpF()
+{
+  ReadLabel();
+  GetLabel().Rotate(1, NUM_NOPS);
+
+  // If there is no label, jump BX steps.
+  if (GetLabel().GetSize() == 0) {
+    GetActiveHead().Jump(Register(REG_BX));
+    return true;
+  }
+
+  // Otherwise, try to jump to the complement label.
+  const cCPUHead jump_location(FindLabel(1));
+  if ( jump_location.GetPosition() != -1 ) {
+    GetActiveHead().Set(jump_location);
+    return true;
+  }
+
+  // If complement label was not found; record an error.
+  organism->Fault(FAULT_LOC_JUMP, FAULT_TYPE_ERROR,
+		  "jump-f: No complement label");
+  return false;
+}
+
+
+bool cHardwareCPU::Inst_JumpB()
+{
+  ReadLabel();
+  GetLabel().Rotate(1, NUM_NOPS);
+
+  // If there is no label, jump BX steps.
+  if (GetLabel().GetSize() == 0) {
+    GetActiveHead().Jump(-Register(REG_BX));
+    return true;
+  }
+
+  // otherwise jump to the complement label.
+  const cCPUHead jump_location(FindLabel(-1));
+  if ( jump_location.GetPosition() != -1 ) {
+    GetActiveHead().Set(jump_location);
+    return true;
+  }
+
+  // If complement label was not found; record an error.
+  organism->Fault(FAULT_LOC_JUMP, FAULT_TYPE_ERROR,
+		  "jump-b: No complement label");
+  return false;
+}
+
+bool cHardwareCPU::Inst_JumpP()
+{
+  cOrganism * other_organism = organism->GetNeighbor();
+
+  // Make sure the other organism was found and that its hardware is of the
+  // same type, or else we won't be able to be parasitic on it.
+  if (other_organism == NULL ||
+      other_organism->GetHardware().GetType() != GetType()) {
+    // Without another organism, its hard to determine if we're dealing
+    // with a parasite.  For the moment, we'll assume it is and move on.
+    // @CAO Do better!
+    organism->GetPhenotype().IsParasite() = true;
+    return true;
+  }
+
+  // Otherwise, grab the hardware from the neighbor, and use it!
+  cHardwareCPU & other_hardware = (cHardwareCPU &) other_organism->GetHardware();
+
+  ReadLabel();
+  GetLabel().Rotate(1, NUM_NOPS);
+
+  // If there is no label, jump to line BX in creature.
+  if (GetLabel().GetSize() == 0) {
+    const int new_pos = Register(REG_BX);
+    IP().Set(new_pos, &other_hardware);
+    organism->GetPhenotype().IsParasite() = true;
+    return true;
+  }
+
+  // otherwise jump to the complement label.
+  const cCPUHead jump_location(other_hardware.FindFullLabel(GetLabel()));
+  if (jump_location.GetPosition() != -1) {
+    IP().Set(jump_location);
+    organism->GetPhenotype().IsParasite() = true;
+    return true;
+  }
+
+  // If complement label was not found; record a warning (since the
+  // actual neighbors are not under the organisms control, this is not
+  // a full-scale error).
+  organism->Fault(FAULT_LOC_JUMP, FAULT_TYPE_WARNING,
+		  "jump-p: No complement label");
+  return false;
+}
+
+bool cHardwareCPU::Inst_JumpSelf()
+{
+  ReadLabel();
+  GetLabel().Rotate(1, NUM_NOPS);
+
+  // If there is no label, jump to line BX in creature.
+  if (GetLabel().GetSize() == 0) {
+    IP().Set(Register(REG_BX), this);
+    return true;
+  }
+
+  // otherwise jump to the complement label.
+  const cCPUHead jump_location( FindFullLabel(GetLabel()) );
+  if ( jump_location.GetPosition() != -1 ) {
+    IP().Set(jump_location);
+    return true;
+  }
+
+  // If complement label was not found; record an error.
+  organism->Fault(FAULT_LOC_JUMP, FAULT_TYPE_ERROR,
+		  "jump-slf: no complement label");
+  return false;
+}
+
+bool cHardwareCPU::Inst_Call()
+{
+  // Put the starting location onto the stack
+  const int location = IP().GetPosition();
+  StackPush(location);
+
+  // Jump to the compliment label (or by the ammount in the bx register)
+  ReadLabel();
+  GetLabel().Rotate(1, NUM_NOPS);
+
+  if (GetLabel().GetSize() == 0) {
+    IP().Jump(Register(REG_BX));
+    return true;
+  }
+
+  const cCPUHead jump_location(FindLabel(1));
+  if (jump_location.GetPosition() != -1) {
+    IP().Set(jump_location);
+    return true;
+  }
+
+  // If complement label was not found; record an error.
+  organism->Fault(FAULT_LOC_JUMP, FAULT_TYPE_ERROR,
+		  "call: no complement label");
+  return false;
+}
+
+bool cHardwareCPU::Inst_Return()
+{
+  IP().Set(StackPop());
+  return true;
+}
+
+bool cHardwareCPU::Inst_Pop()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  Register(reg_used) = StackPop();
+  return true;
+}
+
+bool cHardwareCPU::Inst_Push()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  StackPush(Register(reg_used));
+  return true;
+}
+
+bool cHardwareCPU::Inst_HeadPop()
+{
+  const int head_used = FindModifiedHead(HEAD_IP);
+  GetHead(head_used).Set(StackPop(), this);
+  return true;
+}
+
+bool cHardwareCPU::Inst_HeadPush()
+{
+  const int head_used = FindModifiedHead(HEAD_IP);
+  StackPush(GetHead(head_used).GetPosition());
+  if (head_used == HEAD_IP) {
+    GetHead(head_used).Set(GetHead(HEAD_FLOW));
+    advance_ip = false;
+  }
+  return true;
+}
+
+
+bool cHardwareCPU::Inst_PopA() { Register(REG_AX) = StackPop(); return true;}
+bool cHardwareCPU::Inst_PopB() { Register(REG_BX) = StackPop(); return true;}
+bool cHardwareCPU::Inst_PopC() { Register(REG_CX) = StackPop(); return true;}
+
+bool cHardwareCPU::Inst_PushA() { StackPush(Register(REG_AX)); return true;}
+bool cHardwareCPU::Inst_PushB() { StackPush(Register(REG_BX)); return true;}
+bool cHardwareCPU::Inst_PushC() { StackPush(Register(REG_CX)); return true;}
+
+bool cHardwareCPU::Inst_SwitchStack() { SwitchStack(); return true;}
+bool cHardwareCPU::Inst_FlipStack()   { StackFlip(); return true;}
+
+bool cHardwareCPU::Inst_Swap()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  const int other_reg = FindComplementRegister(reg_used);
+  Swap(Register(reg_used), Register(other_reg));
+  return true;
+}
+
+bool cHardwareCPU::Inst_SwapAB() { Swap(Register(REG_AX), Register(REG_BX)); return true; }
+bool cHardwareCPU::Inst_SwapBC() { Swap(Register(REG_BX), Register(REG_CX)); return true; }
+bool cHardwareCPU::Inst_SwapAC() { Swap(Register(REG_AX), Register(REG_CX)); return true; }
+
+bool cHardwareCPU::Inst_CopyReg()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  const int other_reg = FindComplementRegister(reg_used);
+  Register(other_reg) = Register(reg_used);
+  return true;
+}
+
+bool cHardwareCPU::Inst_CopyRegAB() { Register(REG_AX) = Register(REG_BX);   return true;
+}
+bool cHardwareCPU::Inst_CopyRegAC() { Register(REG_AX) = Register(REG_CX);   return true;
+}
+bool cHardwareCPU::Inst_CopyRegBA() { Register(REG_BX) = Register(REG_AX);   return true;
+}
+bool cHardwareCPU::Inst_CopyRegBC() { Register(REG_BX) = Register(REG_CX);   return true;
+}
+bool cHardwareCPU::Inst_CopyRegCA() { Register(REG_CX) = Register(REG_AX);   return true;
+}
+bool cHardwareCPU::Inst_CopyRegCB() { Register(REG_CX) = Register(REG_BX);   return true;
+}
+
+bool cHardwareCPU::Inst_Reset()
+{
+  Register(REG_AX) = 0;
+  Register(REG_BX) = 0;
+  Register(REG_CX) = 0;
+  StackClear();
+  return true;
+}
+
+bool cHardwareCPU::Inst_ShiftR()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  Register(reg_used) >>= 1;
+  return true;
+}
+
+bool cHardwareCPU::Inst_ShiftL()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  Register(reg_used) <<= 1;
+  return true;
+}
+
+bool cHardwareCPU::Inst_Bit1()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  Register(reg_used) |=  1;
+  return true;
+}
+
+bool cHardwareCPU::Inst_SetNum()
+{
+  ReadLabel();
+  Register(REG_BX) = GetLabel().AsInt(NUM_NOPS);
+  return true;
+}
+
+bool cHardwareCPU::Inst_Inc()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  Register(reg_used) += 1;
+  return true;
+}
+
+bool cHardwareCPU::Inst_Dec()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  Register(reg_used) -= 1;
+  return true;
+}
+
+bool cHardwareCPU::Inst_Zero()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  Register(reg_used) = 0;
+  return true;
+}
+
+bool cHardwareCPU::Inst_Neg()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  Register(reg_used) = 0-Register(reg_used);
+  return true;
+}
+
+bool cHardwareCPU::Inst_Square()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  Register(reg_used) = Register(reg_used) * Register(reg_used);
+  return true;
+}
+
+bool cHardwareCPU::Inst_Sqrt()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  const int value = Register(reg_used);
+  if (value > 1) Register(reg_used) = (int) sqrt((double) value);
+  else if (value < 0) {
+    Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "sqrt: value is negative");
+    return false;
+  }
+  return true;
+}
+
+bool cHardwareCPU::Inst_Log()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  const int value = Register(reg_used);
+  if (value >= 1) Register(reg_used) = (int) log((double) value);
+  else if (value < 0) {
+    Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "log: value is negative");
+    return false;
+  }
+  return true;
+}
+
+bool cHardwareCPU::Inst_Log10()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  const int value = Register(reg_used);
+  if (value >= 1) Register(reg_used) = (int) log10((double) value);
+  else if (value < 0) {
+    Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "log10: value is negative");
+    return false;
+  }
+  return true;
+}
+
+bool cHardwareCPU::Inst_Minus17()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  Register(reg_used) -= 17;
+  return true;
+}
+
+bool cHardwareCPU::Inst_Add()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  Register(reg_used) = Register(REG_BX) + Register(REG_CX);
+  return true;
+}
+
+bool cHardwareCPU::Inst_Sub()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  Register(reg_used) = Register(REG_BX) - Register(REG_CX);
+  return true;
+}
+
+bool cHardwareCPU::Inst_Mult()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  Register(reg_used) = Register(REG_BX) * Register(REG_CX);
+  return true;
+}
+
+bool cHardwareCPU::Inst_Div()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  if (Register(REG_CX) != 0) {
+    if (0-INT_MAX > Register(REG_BX) && Register(REG_CX) == -1)
+      Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "div: Float exception");
+    else
+      Register(reg_used) = Register(REG_BX) / Register(REG_CX);
+  } else {
+    Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "div: dividing by 0");
+    return false;
+  }
+  return true;
+}
+
+bool cHardwareCPU::Inst_Mod()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  if (Register(REG_CX) != 0) {
+    Register(reg_used) = Register(REG_BX) % Register(REG_CX);
+  } else {
+    Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "mod: modding by 0");
+  return false;
+  }
+  return true;
+}
+
+
+bool cHardwareCPU::Inst_Nand()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  Register(reg_used) = ~(Register(REG_BX) & Register(REG_CX));
+  return true;
+}
+
+bool cHardwareCPU::Inst_Nor()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  Register(reg_used) = ~(Register(REG_BX) | Register(REG_CX));
+  return true;
+}
+
+bool cHardwareCPU::Inst_And()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  Register(reg_used) = (Register(REG_BX) & Register(REG_CX));
+  return true;
+}
+
+bool cHardwareCPU::Inst_Not()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  Register(reg_used) = ~(Register(reg_used));
+  return true;
+}
+
+bool cHardwareCPU::Inst_Order()
+{
+  if (Register(REG_BX) > Register(REG_CX)) {
+    Swap(Register(REG_BX), Register(REG_CX));
+  }
+  return true;
+}
+
+bool cHardwareCPU::Inst_Xor()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  Register(reg_used) = Register(REG_BX) ^ Register(REG_CX);
+  return true;
+}
+
+bool cHardwareCPU::Inst_Copy()
+{
+  const cCPUHead from(this, Register(REG_BX));
+  cCPUHead to(this, Register(REG_AX) + Register(REG_BX));
+  sCPUStats & cpu_stats = organism->CPUStats();
+
+  if (organism->TestCopyMut()) {
+    to.SetInst(GetRandomInst());
+    to.FlagMutated() = true;  // Mark this instruction as mutated...
+    to.FlagCopyMut() = true;  // Mark this instruction as copy mut...
+    //organism->GetPhenotype().IsMutated() = true;
+    cpu_stats.mut_stats.copy_mut_count++;
+  } else {
+    to.SetInst(from.GetInst());
+    to.FlagMutated() = false;  // UnMark
+    to.FlagCopyMut() = false;  // UnMark
+  }
+
+  to.FlagCopied() = true;  // Set the copied flag.
+  cpu_stats.mut_stats.copies_exec++;
+  return true;
+}
+
+bool cHardwareCPU::Inst_ReadInst()
+{
+  const int reg_used = FindModifiedRegister(REG_CX);
+  const cCPUHead from(this, Register(REG_BX));
+
+  // Dis-allowing mutations on read, for the moment (write only...)
+  // @CAO This allows perfect error-correction...
+  Register(reg_used) = from.GetInst().GetOp();
+  return true;
+}
+
+bool cHardwareCPU::Inst_WriteInst()
+{
+  cCPUHead to(this, Register(REG_AX) + Register(REG_BX));
+  const int reg_used = FindModifiedRegister(REG_CX);
+  const int value = Mod(Register(reg_used), GetNumInst());
+  sCPUStats & cpu_stats = organism->CPUStats();
+
+  // Change value on a mutation...
+  if (organism->TestCopyMut()) {
+    to.SetInst(GetRandomInst());
+    to.FlagMutated() = true;      // Mark this instruction as mutated...
+    to.FlagCopyMut() = true;      // Mark this instruction as copy mut...
+    //organism->GetPhenotype().IsMutated() = true;
+    cpu_stats.mut_stats.copy_mut_count++;
+  } else {
+    to.SetInst(cInstruction(value));
+    to.FlagMutated() = false;     // UnMark
+    to.FlagCopyMut() = false;     // UnMark
+  }
+
+  to.FlagCopied() = true;  // Set the copied flag.
+  cpu_stats.mut_stats.copies_exec++;
+  return true;
+}
+
+bool cHardwareCPU::Inst_StackReadInst()
+{
+  const int reg_used = FindModifiedRegister(REG_CX);
+  cCPUHead from(this, Register(reg_used));
+  StackPush(from.GetInst().GetOp());
+  return true;
+}
+
+bool cHardwareCPU::Inst_StackWriteInst()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  cCPUHead to(this, Register(REG_AX) + Register(reg_used));
+  const int value = Mod(StackPop(), GetNumInst());
+  sCPUStats & cpu_stats = organism->CPUStats();
+
+  // Change value on a mutation...
+  if (organism->TestCopyMut()) {
+    to.SetInst(GetRandomInst());
+    to.FlagMutated() = true;      // Mark this instruction as mutated...
+    to.FlagCopyMut() = true;      // Mark this instruction as copy mut...
+    //organism->GetPhenotype().IsMutated() = true;
+    cpu_stats.mut_stats.copy_mut_count++;
+  } else {
+    to.SetInst(cInstruction(value));
+    to.FlagMutated() = false;     // UnMark
+    to.FlagCopyMut() = false;     // UnMark
+  }
+
+  to.FlagCopied() = true;  // Set the copied flag.
+  cpu_stats.mut_stats.copies_exec++;
+  return true;
+}
+
+bool cHardwareCPU::Inst_Compare()
+{
+  const int reg_used = FindModifiedRegister(REG_CX);
+  cCPUHead from(this, Register(REG_BX));
+  cCPUHead to(this, Register(REG_AX) + Register(REG_BX));
+
+  // Compare is dangerous -- it can cause mutations!
+  if (organism->TestCopyMut()) {
+    to.SetInst(GetRandomInst());
+    to.FlagMutated() = true;      // Mark this instruction as mutated...
+    to.FlagCopyMut() = true;      // Mark this instruction as copy mut...
+    //organism->GetPhenotype().IsMutated() = true;
+  }
+
+  Register(reg_used) = from.GetInst().GetOp() - to.GetInst().GetOp();
+
+  return true;
+}
+
+bool cHardwareCPU::Inst_IfNCpy()
+{
+  const cCPUHead from(this, Register(REG_BX));
+  const cCPUHead to(this, Register(REG_AX) + Register(REG_BX));
+
+  // Allow for errors in this test...
+  if (organism->TestCopyMut()) {
+    if (from.GetInst() != to.GetInst()) IP().Advance();
+  } else {
+    if (from.GetInst() == to.GetInst()) IP().Advance();
+  }
+  return true;
+}
+
+bool cHardwareCPU::Inst_Allocate()   // Allocate bx more space...
+{
+  const int size = GetMemory().GetSize();
+  if( Allocate_Main(Register(REG_BX)) ) {
+    Register(REG_AX) = size;
+    return true;
+  } else return false;
+}
+
+bool cHardwareCPU::Inst_Divide()  
+{ 
+  return Divide_Main(Register(REG_AX));    
+}
+
+bool cHardwareCPU::Inst_CDivide() 
+{ 
+  return Divide_Main(GetMemory().GetSize() / 2);   
+}
+
+bool cHardwareCPU::Inst_CAlloc()  
+{ 
+  return Allocate_Main(GetMemory().GetSize());   
+}
+
+bool cHardwareCPU::Inst_MaxAlloc()   // Allocate maximal more
+{
+  const int cur_size = GetMemory().GetSize();
+  const int alloc_size = Min((int) (cConfig::GetChildSizeRange() * cur_size),
+			     MAX_CREATURE_SIZE - cur_size);
+  if( Allocate_Main(alloc_size) ) {
+    Register(REG_AX) = cur_size;
+    return true;
+  } else return false;
+}
+
+
+bool cHardwareCPU::Inst_Repro()
+{
+  // Setup child
+  cCPUMemory & child_genome = organism->ChildGenome();
+  child_genome = GetMemory();
+  organism->GetPhenotype().SetLinesCopied(GetMemory().GetSize());
+
+  int lines_executed = 0;
+  for ( int i = 0; i < GetMemory().GetSize(); i++ ) {
+    if ( GetMemory().FlagExecuted(i) == true ) lines_executed++;
+  }
+  organism->GetPhenotype().SetLinesExecuted(lines_executed);
+
+  // Perform Copy Mutations...
+  if (organism->GetCopyMutProb() > 0) { // Skip this if no mutations....
+    for (int i = 0; i < GetMemory().GetSize(); i++) {
+      if (organism->TestCopyMut()) {
+	child_genome[i]=GetRandomInst();
+	//organism->GetPhenotype().IsMutated() = true;
+      }
+    }
+  }
+  Divide_DoMutations();
+
+  // Many tests will require us to run the offspring through a test CPU;
+  // this is, for example, to see if mutations need to be reverted or if
+  // lineages need to be updated.
+  Divide_TestFitnessMeasures();
+
+#ifdef INSTRUCTION_COSTS
+  // reset first time instruction costs
+  for (int i = 0; i < inst_ft_cost.GetSize(); i++) {
+    inst_ft_cost[i] = GetInstSet().GetFTCost(cInstruction(i));
+  }
+#endif
+
+  if (cConfig::GetDivideMethod() == DIVIDE_METHOD_SPLIT) advance_ip = false;
+
+  organism->ActivateDivide();
+
+  return true;
+}
+
+
+bool cHardwareCPU::Inst_Kazi()
+{
+	const int reg_used = FindModifiedRegister(REG_AX);
+	int percentProb = Register(reg_used) % 100;
+	int random = abs(rand()) % 100;
+	if (random >= percentProb)
+	{
+		return true;
+	}
+	else
+	{
+		organism->Kaboom();
+		return true;
+	}
+}
+
+// The inject instruction can be used instead of a divide command, paired
+// with an allocate.  Note that for an inject to work, one needs to have a
+// broad range for sizes allowed to be allocated.
+//
+// This command will cut out from read-head to write-head.
+// It will then look at the template that follows the command and inject it
+// into the complement template found in a neighboring organism.
+
+bool cHardwareCPU::Inst_Inject()
+{
+  AdjustHeads();
+  const int start_pos = GetHead(HEAD_READ).GetPosition();
+  const int end_pos = GetHead(HEAD_WRITE).GetPosition();
+  const int inject_size = end_pos - start_pos;
+
+  // Make sure the creature will still be above the minimum size,
+  if (inject_size <= 0) {
+    Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: no code to inject");
+    return false; // (inject fails)
+  }
+  if (start_pos < MIN_CREATURE_SIZE) {
+    Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: new size too small");
+    return false; // (inject fails)
+  }
+
+  // Since its legal to cut out the injected piece, do so.
+  cGenome inject_code( cGenomeUtil::Crop(GetMemory(), start_pos, end_pos) );
+  GetMemory().Remove(start_pos, inject_size);
+
+  // If we don't have a host, stop here.
+  cOrganism * host_organism = organism->GetNeighbor();
+  if (host_organism == NULL) return false;
+
+  // Scan for the label to match...
+  ReadLabel();
+
+  // If there is no label, abort.
+  if (GetLabel().GetSize() == 0) {
+    Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: label required");
+    return false; // (inject fails)
+  }
+
+  // Search for the label in the host...
+  GetLabel().Rotate(1, NUM_NOPS);
+
+  const bool inject_signal =
+    host_organism->GetHardware().InjectHost(GetLabel(), inject_code);
+  if (inject_signal == 1) {
+    Fault(FAULT_LOC_INJECT, FAULT_TYPE_WARNING, "inject: host too large.");
+    return false; // Inject failed.
+  }
+  if (inject_signal == 2) {
+    Fault(FAULT_LOC_INJECT, FAULT_TYPE_WARNING, "inject: target not in host.");
+    return false; // Inject failed.
+  }
+
+  // Set the relevent flags.
+  organism->GetPhenotype().IsModifier() = true;
+
+  return inject_signal;
+}
+
+
+bool cHardwareCPU::Inst_InjectRand()
+{
+  // Rotate to a random facing and then run the normal inject instruction
+  const int num_neighbors = organism->GetNeighborhoodSize();
+  organism->Rotate(g_random.GetUInt(num_neighbors));
+  Inst_Inject();
+  return true;
+}
+
+// The inject instruction can be used instead of a divide command, paired
+// with an allocate.  Note that for an inject to work, one needs to have a
+// broad range for sizes allowed to be allocated.
+//
+// This command will cut out from read-head to write-head.
+// It will then look at the template that follows the command and inject it
+// into the complement template found in a neighboring organism.
+
+bool cHardwareCPU::Inst_InjectThread()
+{
+  AdjustHeads();
+  const int start_pos = GetHead(HEAD_READ).GetPosition();
+  const int end_pos = GetHead(HEAD_WRITE).GetPosition();
+  const int inject_size = end_pos - start_pos;
+
+  // Make sure the creature will still be above the minimum size,
+  if (inject_size <= 0) {
+    Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: no code to inject");
+    return false; // (inject fails)
+  }
+  if (start_pos < MIN_CREATURE_SIZE) {
+    Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: new size too small");
+    return false; // (inject fails)
+  }
+
+  // Since its legal to cut out the injected piece, do so.
+  cGenome inject_code( cGenomeUtil::Crop(GetMemory(), start_pos, end_pos) );
+  GetMemory().Remove(start_pos, inject_size);
+
+  // If we don't have a host, stop here.
+  cOrganism * host_organism = organism->GetNeighbor();
+  if (host_organism == NULL) return false;
+
+  // Scan for the label to match...
+  ReadLabel();
+
+  // If there is no label, abort.
+  if (GetLabel().GetSize() == 0) {
+    Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: label required");
+    return false; // (inject fails)
+  }
+
+  // Search for the label in the host...
+  GetLabel().Rotate(1, NUM_NOPS);
+
+  const int inject_signal =
+    host_organism->GetHardware().InjectThread(GetLabel(), inject_code);
+  if (inject_signal == 1) {
+    Fault(FAULT_LOC_INJECT, FAULT_TYPE_WARNING, "inject: host too large.");
+    return false; // Inject failed.
+  }
+  if (inject_signal == 2) {
+    Fault(FAULT_LOC_INJECT, FAULT_TYPE_WARNING, "inject: target not in host.");
+    return false; // Inject failed.
+  }
+
+  // Set the relevent flags.
+  organism->GetPhenotype().IsModifier() = true;
+
+  return true;
+}
+
+bool cHardwareCPU::Inst_TaskGet()
+{
+  const int reg_used = FindModifiedRegister(REG_CX);
+  const int value = organism->GetInputAt(threads[GetCurThread()].input_pointer);
+  Register(reg_used) = value;
+  DoInput(value);
+  return true;
+}
+
+bool cHardwareCPU::Inst_TaskStackGet()
+{
+  const int value = organism->GetInputAt(threads[GetCurThread()].input_pointer);
+  StackPush(value);
+  DoInput(value);
+  return true;
+}
+
+bool cHardwareCPU::Inst_TaskStackLoad()
+{
+  for (int i = 0; i < IO_SIZE; i++) 
+    StackPush( organism->GetInputAt(threads[GetCurThread()].input_pointer) );
+  return true;
+}
+
+bool cHardwareCPU::Inst_TaskPut()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  const int value = Register(reg_used);
+  Register(reg_used) = 0;
+  DoOutput(value);
+  return true;
+}
+
+bool cHardwareCPU::Inst_TaskIO()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+
+  // Do the "put" component
+  const int value_out = Register(reg_used);
+  DoOutput(value_out);  // Check for tasks compleated.
+
+  // Do the "get" component
+  const int value_in = organism->GetInputAt(threads[GetCurThread()].input_pointer);
+  Register(reg_used) = value_in;
+  DoInput(value_in);
+  return true;
+}
+
+bool cHardwareCPU::Inst_SearchF()
+{
+  ReadLabel();
+  GetLabel().Rotate(1, NUM_NOPS);
+  const int search_size = FindLabel(1).GetPosition() - IP().GetPosition();
+  Register(REG_BX) = search_size;
+  Register(REG_CX) = GetLabel().GetSize();
+  return true;
+}
+
+bool cHardwareCPU::Inst_SearchB()
+{
+  ReadLabel();
+  GetLabel().Rotate(1, NUM_NOPS);
+  const int search_size = IP().GetPosition() - FindLabel(-1).GetPosition();
+  Register(REG_BX) = search_size;
+  Register(REG_CX) = GetLabel().GetSize();
+  return true;
+}
+
+bool cHardwareCPU::Inst_MemSize()
+{
+  Register(FindModifiedRegister(REG_BX)) = GetMemory().GetSize();
+  return true;
+}
+
+
+bool cHardwareCPU::Inst_RotateL()
+{
+  const int num_neighbors = organism->GetNeighborhoodSize();
+
+   // If this organism has no neighbors, ignore rotate.
+  if (num_neighbors == 0) return false;
+
+  ReadLabel();
+
+  // Always rotate at least once.
+  organism->Rotate(-1);
+
+  // If there is no label, then the one rotation was all we want.
+  if (!GetLabel().GetSize()) return true;
+
+  // Rotate until a complement label is found (or all have been checked).
+  GetLabel().Rotate(1, NUM_NOPS);
+  for (int i = 1; i < num_neighbors; i++) {
+    cOrganism * neighbor = organism->GetNeighbor();
+
+    // Assuming we have a neighbor and it is of the same hardware type,
+    // search for the label in it.
+    if (neighbor != NULL &&
+	neighbor->GetHardware().GetType() == GetType()) {
+
+      // If this facing has the full label, stop here.
+      cHardwareCPU & cur_hardware = (cHardwareCPU &) neighbor->GetHardware();
+      if (cur_hardware.FindFullLabel( GetLabel() ).InMemory()) return true;
+    }
+
+    // Otherwise keep rotating...
+    organism->Rotate(-1);
+  }
+  return true;
+}
+
+bool cHardwareCPU::Inst_RotateR()
+{
+  const int num_neighbors = organism->GetNeighborhoodSize();
+
+   // If this organism has no neighbors, ignore rotate.
+  if (num_neighbors == 0) return false;
+
+  ReadLabel();
+
+  // Always rotate at least once.
+  organism->Rotate(-1);
+
+  // If there is no label, then the one rotation was all we want.
+  if (!GetLabel().GetSize()) return true;
+
+  // Rotate until a complement label is found (or all have been checked).
+  GetLabel().Rotate(1, NUM_NOPS);
+  for (int i = 1; i < num_neighbors; i++) {
+    cOrganism * neighbor = organism->GetNeighbor();
+
+    // Assuming we have a neighbor and it is of the same hardware type,
+    // search for the label in it.
+    if (neighbor != NULL &&
+	neighbor->GetHardware().GetType() == GetType()) {
+
+      // If this facing has the full label, stop here.
+      cHardwareCPU & cur_hardware = (cHardwareCPU &) neighbor->GetHardware();
+      if (cur_hardware.FindFullLabel( GetLabel() ).InMemory()) return true;
+    }
+
+    // Otherwise keep rotating...
+    organism->Rotate(1);
+  }
+  return true;
+}
+
+bool cHardwareCPU::Inst_SetCopyMut()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  const int new_mut_rate = Max( Register(reg_used), 1 );
+  organism->SetCopyMutProb(((double) new_mut_rate) / 10000.0);
+  return true;
+}
+
+bool cHardwareCPU::Inst_ModCopyMut()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  const double new_mut_rate = organism->GetCopyMutProb() +
+    ((double) Register(reg_used)) / 10000.0;
+  if (new_mut_rate > 0.0) organism->SetCopyMutProb(new_mut_rate);
+  return true;
+}
+
+
+// Multi-threading.
+
+bool cHardwareCPU::Inst_ForkThread()
+{
+  IP().Advance();
+  if (!ForkThread()) Fault(FAULT_LOC_THREAD_FORK, FAULT_TYPE_FORK_TH);
+  return true;
+}
+
+bool cHardwareCPU::Inst_KillThread()
+{
+  if (!KillThread()) Fault(FAULT_LOC_THREAD_KILL, FAULT_TYPE_KILL_TH);
+  else advance_ip = false;
+  return true;
+}
+
+bool cHardwareCPU::Inst_ThreadID()
+{
+  const int reg_used = FindModifiedRegister(REG_BX);
+  Register(reg_used) = GetCurThreadID();
+  return true;
+}
+
+
+// Head-based instructions
+
+bool cHardwareCPU::Inst_SetHead()
+{
+  const int head_used = FindModifiedHead(HEAD_IP);
+  SetActiveHead(head_used);
+  return true;
+}
+
+bool cHardwareCPU::Inst_AdvanceHead()
+{
+  const int head_used = FindModifiedHead(HEAD_WRITE);
+  GetHead(head_used).Advance();
+  return true;
+}
+ 
+bool cHardwareCPU::Inst_MoveHead()
+{
+  const int head_used = FindModifiedHead(HEAD_IP);
+  GetHead(head_used).Set(GetHead(HEAD_FLOW));
+  if (head_used == HEAD_IP) advance_ip = false;
+  return true;
+}
+
+bool cHardwareCPU::Inst_JumpHead()
+{
+  const int head_used = FindModifiedHead(HEAD_IP);
+  GetHead(head_used).Jump( Register(REG_CX) );
+  return true;
+}
+
+bool cHardwareCPU::Inst_GetHead()
+{
+  const int head_used = FindModifiedHead(HEAD_IP);
+  Register(REG_CX) = GetHead(head_used).GetPosition();
+  return true;
+}
+
+bool cHardwareCPU::Inst_IfLabel()
+{
+  ReadLabel();
+  GetLabel().Rotate(1, NUM_NOPS);
+  if (GetLabel() != GetReadLabel())  IP().Advance();
+  return true;
+}
+
+bool cHardwareCPU::Inst_HeadDivideMut(double mut_multiplier)
+{
+  AdjustHeads();
+  const int divide_pos = GetHead(HEAD_READ).GetPosition();
+  int child_end =  GetHead(HEAD_WRITE).GetPosition();
+  if (child_end == 0) child_end = GetMemory().GetSize();
+  const int extra_lines = GetMemory().GetSize() - child_end;
+  bool ret_val = Divide_Main(divide_pos, extra_lines, mut_multiplier);
+  // Re-adjust heads.
+  AdjustHeads();
+  return ret_val; 
+}
+
+bool cHardwareCPU::Inst_HeadDivide()
+{
+  return Inst_HeadDivideMut(1);
+}
+
+bool cHardwareCPU::Inst_HeadDivideSex()  
+{ 
+  organism->GetPhenotype().SetDivideSex(true);
+  organism->GetPhenotype().SetCrossNum(1);
+  return Inst_HeadDivide(); 
+}
+
+bool cHardwareCPU::Inst_HeadDivideAsex()  
+{ 
+  organism->GetPhenotype().SetDivideSex(false);
+  organism->GetPhenotype().SetCrossNum(0);
+  return Inst_HeadDivide(); 
+}
+
+bool cHardwareCPU::Inst_HeadDivideAsexWait()  
+{ 
+  organism->GetPhenotype().SetDivideSex(true);
+  organism->GetPhenotype().SetCrossNum(0);
+  return Inst_HeadDivide(); 
+}
+
+bool cHardwareCPU::Inst_HeadDivide1()  { return Inst_HeadDivideMut(1); }
+bool cHardwareCPU::Inst_HeadDivide2()  { return Inst_HeadDivideMut(2); }
+bool cHardwareCPU::Inst_HeadDivide3()  { return Inst_HeadDivideMut(3); }
+bool cHardwareCPU::Inst_HeadDivide4()  { return Inst_HeadDivideMut(4); }
+bool cHardwareCPU::Inst_HeadDivide5()  { return Inst_HeadDivideMut(5); }
+bool cHardwareCPU::Inst_HeadDivide6()  { return Inst_HeadDivideMut(6); }
+bool cHardwareCPU::Inst_HeadDivide7()  { return Inst_HeadDivideMut(7); }
+bool cHardwareCPU::Inst_HeadDivide8()  { return Inst_HeadDivideMut(8); }
+bool cHardwareCPU::Inst_HeadDivide9()  { return Inst_HeadDivideMut(9); }
+bool cHardwareCPU::Inst_HeadDivide10()  { return Inst_HeadDivideMut(10); }
+bool cHardwareCPU::Inst_HeadDivide16()  { return Inst_HeadDivideMut(16); }
+bool cHardwareCPU::Inst_HeadDivide32()  { return Inst_HeadDivideMut(32); }
+bool cHardwareCPU::Inst_HeadDivide50()  { return Inst_HeadDivideMut(50); }
+bool cHardwareCPU::Inst_HeadDivide100()  { return Inst_HeadDivideMut(100); }
+bool cHardwareCPU::Inst_HeadDivide500()  { return Inst_HeadDivideMut(500); }
+bool cHardwareCPU::Inst_HeadDivide1000()  { return Inst_HeadDivideMut(1000); }
+bool cHardwareCPU::Inst_HeadDivide5000()  { return Inst_HeadDivideMut(5000); }
+bool cHardwareCPU::Inst_HeadDivide10000()  { return Inst_HeadDivideMut(10000); }
+bool cHardwareCPU::Inst_HeadDivide50000()  { return Inst_HeadDivideMut(50000); }
+bool cHardwareCPU::Inst_HeadDivide0_5()  { return Inst_HeadDivideMut(0.5); }
+bool cHardwareCPU::Inst_HeadDivide0_1()  { return Inst_HeadDivideMut(0.1); }
+bool cHardwareCPU::Inst_HeadDivide0_05()  { return Inst_HeadDivideMut(0.05); }
+bool cHardwareCPU::Inst_HeadDivide0_01()  { return Inst_HeadDivideMut(0.01); }
+bool cHardwareCPU::Inst_HeadDivide0_001()  { return Inst_HeadDivideMut(0.001); }
+
+bool cHardwareCPU::Inst_HeadRead()
+{
+  const int head_id = FindModifiedHead(HEAD_READ);
+  GetHead(head_id).Adjust();
+  sCPUStats & cpu_stats = organism->CPUStats();
+
+  // Mutations only occur on the read, for the moment.
+  int read_inst = 0;
+  if (organism->TestCopyMut()) {
+    read_inst = GetRandomInst().GetOp();
+    cpu_stats.mut_stats.copy_mut_count++;  // @CAO, hope this is good!
+  } else {
+    read_inst = GetHead(head_id).GetInst().GetOp();
+  }
+  Register(REG_BX) = read_inst;
+  ReadInst(read_inst);
+
+  cpu_stats.mut_stats.copies_exec++;  // @CAO, this too..
+  GetHead(head_id).Advance();
+  return true;
+}
+
+bool cHardwareCPU::Inst_HeadWrite()
+{
+  const int head_id = FindModifiedHead(HEAD_WRITE);
+  cCPUHead & active_head = GetHead(head_id);
+
+  active_head.Adjust();
+
+  int value = Register(REG_BX);
+  if (value < 0 || value >= GetNumInst()) value = 0;
+
+  active_head.SetInst(cInstruction(value));
+  active_head.FlagCopied() = true;
+
+  // Advance the head after write...
+  active_head++;
+  return true;
+}
+
+bool cHardwareCPU::Inst_HeadCopy()
+{
+  // For the moment, this cannot be nop-modified.
+  cCPUHead & read_head = GetHead(HEAD_READ);
+  cCPUHead & write_head = GetHead(HEAD_WRITE);
+  sCPUStats & cpu_stats = organism->CPUStats();
+
+  read_head.Adjust();
+  write_head.Adjust();
+
+  // TriggerMutations(MUTATION_TRIGGER_READ, read_head);
+  
+  // Do mutations.
+  cInstruction read_inst = read_head.GetInst();
+  if (organism->TestCopyMut()) {
+    read_inst = GetRandomInst();
+    cpu_stats.mut_stats.copy_mut_count++; 
+    write_head.FlagMutated() = true;
+    write_head.FlagCopyMut() = true;
+    //organism->GetPhenotype().IsMutated() = true;
+  }
+  ReadInst(read_inst.GetOp());
+
+  cpu_stats.mut_stats.copies_exec++;
+
+  write_head.SetInst(read_inst);
+  write_head.FlagCopied() = true;  // Set the copied flag...
+
+  // TriggerMutations(MUTATION_TRIGGER_WRITE, write_head);
+
+  read_head.Advance();
+  write_head.Advance();
+  return true;
+}
+
+bool cHardwareCPU::HeadCopy_ErrorCorrect(double reduction)
+{
+  // For the moment, this cannot be nop-modified.
+  cCPUHead & read_head = GetHead(HEAD_READ);
+  cCPUHead & write_head = GetHead(HEAD_WRITE);
+  sCPUStats & cpu_stats = organism->CPUStats();
+
+  read_head.Adjust();
+  write_head.Adjust();
+
+  // Do mutations.
+  cInstruction read_inst = read_head.GetInst();
+  if ( g_random.P(organism->GetCopyMutProb() / reduction) ) {
+    read_inst = GetRandomInst();
+    cpu_stats.mut_stats.copy_mut_count++; 
+    write_head.FlagMutated() = true;
+    write_head.FlagCopyMut() = true;
+    //organism->GetPhenotype().IsMutated() = true;
+  }
+  ReadInst(read_inst.GetOp());
+
+  cpu_stats.mut_stats.copies_exec++;
+
+  write_head.SetInst(read_inst);
+  write_head.FlagCopied() = true;  // Set the copied flag...
+
+  read_head.Advance();
+  write_head.Advance();
+  return true;
+}
+
+bool cHardwareCPU::Inst_HeadCopy2()  { return HeadCopy_ErrorCorrect(2); }
+bool cHardwareCPU::Inst_HeadCopy3()  { return HeadCopy_ErrorCorrect(3); }
+bool cHardwareCPU::Inst_HeadCopy4()  { return HeadCopy_ErrorCorrect(4); }
+bool cHardwareCPU::Inst_HeadCopy5()  { return HeadCopy_ErrorCorrect(5); }
+bool cHardwareCPU::Inst_HeadCopy6()  { return HeadCopy_ErrorCorrect(6); }
+bool cHardwareCPU::Inst_HeadCopy7()  { return HeadCopy_ErrorCorrect(7); }
+bool cHardwareCPU::Inst_HeadCopy8()  { return HeadCopy_ErrorCorrect(8); }
+bool cHardwareCPU::Inst_HeadCopy9()  { return HeadCopy_ErrorCorrect(9); }
+bool cHardwareCPU::Inst_HeadCopy10() { return HeadCopy_ErrorCorrect(10); }
+
+bool cHardwareCPU::Inst_HeadSearch()
+{
+  ReadLabel();
+  GetLabel().Rotate(1, NUM_NOPS);
+  cCPUHead found_pos = FindLabel(0);
+  const int search_size = found_pos.GetPosition() - IP().GetPosition();
+  Register(REG_BX) = search_size;
+  Register(REG_CX) = GetLabel().GetSize();
+  GetHead(HEAD_FLOW).Set(found_pos);
+  GetHead(HEAD_FLOW).Advance();
+  return true; 
+}
+
+bool cHardwareCPU::Inst_SetFlow()
+{
+  const int reg_used = FindModifiedRegister(REG_CX);
+  GetHead(HEAD_FLOW).Set(Register(reg_used), this);
+  return true; 
+}
+
+// Direct Matching Templates
+
+bool cHardwareCPU::Inst_DMJumpF()
+{
+  ReadLabel();
+
+  // If there is no label, jump BX steps.
+  if (GetLabel().GetSize() == 0) {
+    IP().Jump(Register(REG_BX));
+    return true;
+  }
+
+  // Otherwise, jump to the label.
+  cCPUHead jump_location(FindLabel(1));
+  if (jump_location.GetPosition() != -1) {
+    IP().Set(jump_location);
+    return true;
+  }
+
+  // If complement label was not found; record an error.
+  organism->Fault(FAULT_LOC_JUMP, FAULT_TYPE_ERROR,
+		  "dm-jump-f: no complement label");
+  return false;
+}
+
+
+//// Placebo insts ////
+bool cHardwareCPU::Inst_Skip()
+{
+  IP().Advance();
+  return true;
+}
+
+
Index: avida/current/source/cpu/hardware_cpu.hh
diff -u /dev/null avida/current/source/cpu/hardware_cpu.hh:1.38
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/cpu/hardware_cpu.hh	Tue Nov 25 09:37:55 2003
@@ -0,0 +1,575 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef HARDWARE_CPU_HH
+#define HARDWARE_CPU_HH
+
+#include <iomanip>
+#include <vector>
+
+#ifndef DEFS_HH
+#include "defs.hh"
+#endif
+#ifndef CODE_LABEL_HH
+#include "code_label.hh"
+#endif
+#ifndef CPU_DEFS_HH
+#include "cpu_defs.hh"
+#endif
+#ifndef CPU_HEAD_HH
+#include "cpu_head.hh"
+#endif
+#ifndef CPU_MEMORY_HH
+#include "cpu_memory.hh"
+#endif
+#ifndef CPU_STACK_HH
+#include "cpu_stack.hh"
+#endif
+#ifndef HARDWARE_BASE_HH
+#include "hardware_base.hh"
+#endif
+#ifndef HARDWARE_CPU_THREAD_HH
+#include "hardware_cpu_thread.hh"
+#endif
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+#ifndef TARRAY_HH
+#include "tArray.hh"
+#endif
+
+class cInstSet;
+class cInstLibBase;
+class cOrganism;
+class cMutation;
+class cHardwareCPU_Thread;
+static const int NUM_NOPS = 3;
+
+#ifdef SINGLE_IO_BUFFER   // For Single IOBuffer vs IOBuffer for each Thread
+# define IO_THREAD 0
+#else
+# define IO_THREAD cur_thread
+#endif
+
+/**
+ * Each organism may have a cHardwareCPU structure which keeps track of the
+ * current status of all the components of the simulated hardware.
+ *
+ * @see cHardwareCPU_Thread, cCPUStack, cCPUMemory, cInstSet
+ **/
+
+class cCodeLabel; // access
+class cCPUHead; // access
+class cCPUMemory; // aggregate
+class cCPUStack; // aggregate
+class cGenome;
+class cHardwareCPU_Thread; // access
+class cInstLibBase;
+class cInstLibCPU;
+class cInstruction;
+class cInstSet;
+class cMutation;
+class cOrganism;
+class cString; // aggregate
+template <class T> class tBuffer;
+template <class T> class tArray; // aggregate
+
+class cHardwareCPU : public cHardwareBase {
+public:
+  typedef bool (cHardwareCPU::*tHardwareCPUMethod)();
+private:
+  static cInstLibCPU *s_inst_slib;
+  static cInstLibCPU *initInstLib(void);
+  tHardwareCPUMethod *m_functions;
+private:
+  cCPUMemory memory;          // Memory...
+  cCPUStack global_stack;     // A stack that all threads share.
+  int thread_time_used;
+
+  tArray<cHardwareCPU_Thread> threads;
+  int thread_id_chart;
+  int cur_thread;
+
+  // Flags...
+  bool mal_active;         // Has an allocate occured since last divide?
+  bool advance_ip;         // Should the IP advance after this instruction?
+
+  // Instruction costs...
+#ifdef INSTRUCTION_COSTS
+  tArray<int> inst_cost;
+  tArray<int> inst_ft_cost;
+#endif
+
+public:
+  cHardwareCPU(cOrganism * in_organism, cInstSet * in_inst_set);
+  ~cHardwareCPU();
+  void Recycle(cOrganism * new_organism, cInstSet * in_inst_set);
+  static cInstLibBase *GetInstLib();
+  static cString GetDefaultInstFilename() { return "inst_lib.default"; }
+  static void WriteDefaultInstSet() { ; }
+
+  void Reset();
+  void SingleProcess(std::ostream * trace_fp=NULL);
+  bool SingleProcess_PayCosts(const cInstruction & cur_inst);
+  bool SingleProcess_ExecuteInst(const cInstruction & cur_inst);
+  void LoadGenome(const cGenome & new_genome);
+
+  // --------  Helper methods  --------
+  bool OK();
+  void PrintStatus(std::ostream & fp);
+
+
+  // --------  Flag Accessors --------
+  bool GetMalActive() const   { return mal_active; }
+
+  // --------  Stack Manipulation...  --------
+  inline void StackPush(int value);
+  inline int StackPop();
+  inline void StackFlip();
+  inline int GetStack(int depth=0, int stack_id=-1) const;
+  inline void StackClear();
+  inline void SwitchStack();
+  int GetActiveStackID() const { return threads[cur_thread].cur_stack; }
+
+  // --------  Tasks & IO  --------
+  tBuffer<int> & GetInputBuffer() { return threads[cur_thread].input_buf; }
+  tBuffer<int> & GetOutputBuffer() { return threads[cur_thread].output_buf; }
+  void DoInput(const int value);
+  void DoOutput(const int value);
+
+  // --------  Head Manipulation (including IP)  --------
+  inline void SetActiveHead(const int new_head)
+  { threads[cur_thread].cur_head = (UCHAR) new_head; }
+
+  int GetCurHead() const { return threads[cur_thread].cur_head; }
+  const cCPUHead & GetHead(int head_id) const
+    { return threads[cur_thread].heads[head_id]; }
+  cCPUHead & GetHead(int head_id) { return threads[cur_thread].heads[head_id];}
+
+  const cCPUHead & GetActiveHead() const { return GetHead(GetCurHead()); }
+  cCPUHead & GetActiveHead() { return GetHead(GetCurHead()); }
+
+  void AdjustHeads();
+
+  inline const cCPUHead & IP() const
+    { return threads[cur_thread].heads[HEAD_IP]; }
+  inline cCPUHead & IP() { return threads[cur_thread].heads[HEAD_IP]; }
+
+
+  // --------  Label Manipulation  -------
+  void ReadLabel(int max_size=MAX_LABEL_SIZE);
+  const cCodeLabel & GetLabel() const 
+    { return threads[cur_thread].next_label; }
+  cCodeLabel & GetLabel() { return threads[cur_thread].next_label; }
+  const cCodeLabel & GetReadLabel() const
+    { return threads[cur_thread].read_label; }
+  cCodeLabel & GetReadLabel() { return threads[cur_thread].read_label; }
+
+
+  // --------  Register Manipulation  --------
+  int Register(int reg_id) const { return threads[cur_thread].reg[reg_id]; }
+  int & Register(int reg_id) { return threads[cur_thread].reg[reg_id]; }
+
+  // --------  Memory Manipulation  --------
+  inline const cCPUMemory & Memory() const { return memory; }
+  inline cCPUMemory & Memory() { return memory; }
+
+  // --------  Thread Manipulation  --------
+  bool ForkThread(); // Adds a new thread based off of cur_thread.
+  bool KillThread(); // Kill the current thread!
+  inline void PrevThread(); // Shift the current thread in use.
+  inline void NextThread();
+  inline void SetThread(int value);
+
+  // --------  Tests  --------
+
+  int TestParasite() const;
+
+  // --------  Accessors  --------
+  const cCPUMemory & GetMemory() const { return memory; }
+  cCPUMemory & GetMemory() { return memory; }
+  const cCPUMemory & GetMemory(int value) const { return memory;}
+  cCPUMemory & GetMemory(int value) { return memory; }
+
+  int GetThreadTimeUsed() const { return thread_time_used; }
+  int GetNumThreads() const     { return threads.GetSize(); }
+  int GetCurThread() const      { return cur_thread; }
+  int GetCurThreadID() const    { return threads[cur_thread].GetID(); }
+
+  int GetThreadDist() const {
+    if (GetNumThreads() == 1) return 0;
+    return threads[0].heads[HEAD_IP].GetPosition() -
+      threads[1].heads[HEAD_IP].GetPosition();
+  }
+
+  // Complex label manipulation...
+  cCPUHead 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);
+  cCPUHead FindLabel(const cCodeLabel & in_label, int direction);
+  cCPUHead FindFullLabel(const cCodeLabel & in_label);
+
+  int GetType() const { return HARDWARE_TYPE_CPU_ORIGINAL; }
+  bool InjectHost(const cCodeLabel & in_label, const cGenome & injection);
+  int InjectThread(const cCodeLabel & in_label, const cGenome & injection);
+  void InjectCode(const cGenome & injection, const int line_num);
+  void InjectCodeThread(const cGenome & injection, const int line_num);
+  void Mutate(const int mut_point);
+  int PointMutate(const double mut_rate);
+
+  bool TriggerMutations(int trigger);
+  bool TriggerMutations(int trigger, cCPUHead & cur_head);
+  bool TriggerMutations_ScopeGenome(const cMutation * cur_mut,
+        cCPUMemory & target_memory, cCPUHead & cur_head, const double rate);
+  bool TriggerMutations_ScopeLocal(const cMutation * cur_mut,
+        cCPUMemory & target_memory, cCPUHead & cur_head, const double rate);
+  int TriggerMutations_ScopeGlobal(const cMutation * cur_mut,
+        cCPUMemory & target_memory, cCPUHead & cur_head, const double rate);
+  void TriggerMutations_Body(int type, cCPUMemory & target_memory,
+			     cCPUHead & cur_head);
+
+  void ReadInst(const int in_inst);
+
+  void SaveState(std::ostream & fp);
+  void LoadState(std::istream & fp);
+
+  void InitInstSet(const cString & filename, cInstSet & inst_set);
+
+
+private:
+ 
+ /////////---------- Instruction Helpers ------------//////////
+
+  int FindModifiedRegister(int default_register);
+  int FindModifiedHead(int default_head);
+  int FindComplementRegister(int base_reg);
+
+  void Fault(int fault_loc, int fault_type, cString fault_desc="");
+
+  bool Allocate_Necro(const int new_size);
+  bool Allocate_Random(const int old_size, const int new_size);
+  bool Allocate_Default(const int new_size);
+  bool Allocate_Main(const int allocated_size);
+
+  bool Divide_Main(const int divide_point, const int extra_lines=0, double mut_multiplier=1);
+
+  bool Divide_CheckViable(const int child_size, const int parent_size);
+  void Divide_DoMutations(double mut_multiplier=1);
+  void Divide_TestFitnessMeasures();
+
+  bool HeadCopy_ErrorCorrect(double reduction);
+  bool Inst_HeadDivideMut(double mut_multiplier=1);
+
+public:
+  /////////---------- Instruction Library ------------//////////
+
+  // Flow Control
+  bool Inst_If0();
+  bool Inst_IfEqu();
+  bool Inst_IfNot0();
+  bool Inst_IfNEqu();
+  bool Inst_IfGr0();
+  bool Inst_IfGr();
+  bool Inst_IfGrEqu0();
+  bool Inst_IfGrEqu();
+  bool Inst_IfLess0();
+  bool Inst_IfLess();
+  bool Inst_IfLsEqu0();
+  bool Inst_IfLsEqu();
+  bool Inst_IfBit1();
+  bool Inst_IfANotEqB();
+  bool Inst_IfBNotEqC();
+  bool Inst_IfANotEqC();
+
+  bool Inst_JumpF();
+  bool Inst_JumpB();
+  bool Inst_JumpP();
+  bool Inst_JumpSelf();
+  bool Inst_Call();
+  bool Inst_Return();
+
+  // Stack and Register Operations
+  bool Inst_Pop();
+  bool Inst_Push();
+  bool Inst_HeadPop();
+  bool Inst_HeadPush();
+
+  bool Inst_PopA();
+  bool Inst_PopB();
+  bool Inst_PopC();
+  bool Inst_PushA();
+  bool Inst_PushB();
+  bool Inst_PushC();
+
+  bool Inst_SwitchStack();
+  bool Inst_FlipStack();
+  bool Inst_Swap();
+  bool Inst_SwapAB();
+  bool Inst_SwapBC();
+  bool Inst_SwapAC();
+  bool Inst_CopyReg();
+  bool Inst_CopyRegAB();
+  bool Inst_CopyRegAC();
+  bool Inst_CopyRegBA();
+  bool Inst_CopyRegBC();
+  bool Inst_CopyRegCA();
+  bool Inst_CopyRegCB();
+  bool Inst_Reset();
+
+  // Single-Argument Math
+  bool Inst_ShiftR();
+  bool Inst_ShiftL();
+  bool Inst_Bit1();
+  bool Inst_SetNum();
+  bool Inst_Inc();
+  bool Inst_Dec();
+  bool Inst_Zero();
+  bool Inst_Not();
+  bool Inst_Neg();
+  bool Inst_Square();
+  bool Inst_Sqrt();
+  bool Inst_Log();
+  bool Inst_Log10();
+  bool Inst_Minus17();
+
+  // Double Argument Math
+  bool Inst_Add();
+  bool Inst_Sub();
+  bool Inst_Mult();
+  bool Inst_Div();
+  bool Inst_Mod();
+  bool Inst_Nand();
+  bool Inst_Nor();
+  bool Inst_And();
+  bool Inst_Order();
+  bool Inst_Xor();
+
+  // Biological
+  bool Inst_Copy();
+  bool Inst_ReadInst();
+  bool Inst_WriteInst();
+  bool Inst_StackReadInst();
+  bool Inst_StackWriteInst();
+  bool Inst_Compare();
+  bool Inst_IfNCpy();
+  bool Inst_Allocate();
+  bool Inst_Divide();
+  bool Inst_CAlloc();
+  bool Inst_CDivide();
+  bool Inst_MaxAlloc();
+  bool Inst_Inject();
+  bool Inst_InjectRand();
+  bool Inst_InjectThread();
+  bool Inst_Repro();
+  bool Inst_Kazi();
+
+  // I/O and Sensory
+  bool Inst_TaskGet();
+  bool Inst_TaskStackGet();
+  bool Inst_TaskStackLoad();
+  bool Inst_TaskPut();
+  bool Inst_TaskIO();
+  bool Inst_SearchF();
+  bool Inst_SearchB();
+  bool Inst_MemSize();
+
+  // Environment
+
+  bool Inst_RotateL();
+  bool Inst_RotateR();
+  bool Inst_SetCopyMut();
+  bool Inst_ModCopyMut();
+
+  // Multi-threading...
+
+  bool Inst_ForkThread();
+  bool Inst_KillThread();
+  bool Inst_ThreadID();
+
+  // Head-based instructions...
+
+  bool Inst_SetHead();
+  bool Inst_AdvanceHead();
+  bool Inst_MoveHead();
+  bool Inst_JumpHead();
+  bool Inst_GetHead();
+  bool Inst_IfLabel();
+  bool Inst_HeadDivide();
+  bool Inst_HeadRead();
+  bool Inst_HeadWrite();
+  bool Inst_HeadCopy();
+  bool Inst_HeadSearch();
+  bool Inst_SetFlow();
+
+  bool Inst_HeadCopy2();
+  bool Inst_HeadCopy3();
+  bool Inst_HeadCopy4();
+  bool Inst_HeadCopy5();
+  bool Inst_HeadCopy6();
+  bool Inst_HeadCopy7();
+  bool Inst_HeadCopy8();
+  bool Inst_HeadCopy9();
+  bool Inst_HeadCopy10();
+
+  bool Inst_HeadDivideSex();
+  bool Inst_HeadDivideAsex();
+  bool Inst_HeadDivideAsexWait();
+
+  bool Inst_HeadDivide1();
+  bool Inst_HeadDivide2();
+  bool Inst_HeadDivide3();
+  bool Inst_HeadDivide4();
+  bool Inst_HeadDivide5();
+  bool Inst_HeadDivide6();
+  bool Inst_HeadDivide7();
+  bool Inst_HeadDivide8();
+  bool Inst_HeadDivide9();
+  bool Inst_HeadDivide10();
+  bool Inst_HeadDivide16();
+  bool Inst_HeadDivide32();
+  bool Inst_HeadDivide50();
+  bool Inst_HeadDivide100();
+  bool Inst_HeadDivide500();
+  bool Inst_HeadDivide1000();
+  bool Inst_HeadDivide5000();
+  bool Inst_HeadDivide10000();
+  bool Inst_HeadDivide50000();
+  bool Inst_HeadDivide0_5();
+  bool Inst_HeadDivide0_1();
+  bool Inst_HeadDivide0_05();
+  bool Inst_HeadDivide0_01();
+  bool Inst_HeadDivide0_001();
+
+
+  // Direct Matching Templates
+
+  bool Inst_DMJumpF();
+  bool Inst_DMJumpB();
+  bool Inst_DMCall();
+  bool Inst_DMSearchF();
+  bool Inst_DMSearchB();
+
+  // Relative Addressed Jumps
+
+  bool Inst_REJumpF();
+  bool Inst_REJumpB();
+
+  // Absoulte Addressed Jumps
+
+  bool Inst_ABSJump();
+
+
+  // Biologically inspired reproduction
+  bool Inst_BCAlloc();
+  bool Inst_BCopy();
+  bool Inst_BDivide();
+private:
+  bool Inst_BCopy_Main(double mut_prob); // Internal called by all BCopy's
+public:
+  // Bio Error Correction
+  bool Inst_BCopyDiv2();
+  bool Inst_BCopyDiv3();
+  bool Inst_BCopyDiv4();
+  bool Inst_BCopyDiv5();
+  bool Inst_BCopyDiv6();
+  bool Inst_BCopyDiv7();
+  bool Inst_BCopyDiv8();
+  bool Inst_BCopyDiv9();
+  bool Inst_BCopyDiv10();
+  bool Inst_BCopyPow2();
+  bool Inst_BIfNotCopy();
+  bool Inst_BIfCopy();
+
+
+  //// Placebo ////
+  bool Inst_Skip();
+};
+
+
+//////////////////
+//  cHardwareCPU
+//////////////////
+
+inline void cHardwareCPU::NextThread()
+{
+  cur_thread++;
+  if (cur_thread >= GetNumThreads()) cur_thread = 0;
+}
+
+inline void cHardwareCPU::PrevThread()
+{
+  if (cur_thread == 0) cur_thread = GetNumThreads() - 1;
+  else cur_thread--;
+}
+
+inline void cHardwareCPU::SetThread(int value)
+{
+     if (value>=0 && value < GetNumThreads())
+          cur_thread=value;
+}
+
+inline void cHardwareCPU::StackPush(int value)
+{
+  if (threads[cur_thread].cur_stack == 0) {
+    threads[cur_thread].stack.Push(value);
+  } else {
+    global_stack.Push(value);
+  }
+}
+
+inline int cHardwareCPU::StackPop()
+{
+  int pop_value;
+
+  if (threads[cur_thread].cur_stack == 0) {
+    pop_value = threads[cur_thread].stack.Pop();
+  } else {
+    pop_value = global_stack.Pop();
+  }
+
+  return pop_value;
+}
+
+inline void cHardwareCPU::StackFlip()
+{
+  if (threads[cur_thread].cur_stack == 0) {
+    threads[cur_thread].stack.Flip();
+  } else {
+    global_stack.Flip();
+  }
+}
+
+inline int cHardwareCPU::GetStack(int depth, int stack_id) const
+{
+  int value = 0;
+
+  if (stack_id == -1) stack_id = threads[cur_thread].cur_stack;
+
+  if (stack_id == 0) value = threads[cur_thread].stack.Get(depth);
+  else if (stack_id == 1) value = global_stack.Get(depth);
+
+  return value;
+}
+
+inline void cHardwareCPU::StackClear()
+{
+  if (threads[cur_thread].cur_stack == 0) {
+    threads[cur_thread].stack.Clear();
+  } else {
+    global_stack.Clear();
+  }
+}
+
+inline void cHardwareCPU::SwitchStack()
+{
+  threads[cur_thread].cur_stack++;
+  if (threads[cur_thread].cur_stack > 1) threads[cur_thread].cur_stack = 0;
+}
+
+#endif
Index: avida/current/source/cpu/hardware_factory.cc
diff -u /dev/null avida/current/source/cpu/hardware_factory.cc:1.11
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/cpu/hardware_factory.cc	Tue Nov 25 09:37:55 2003
@@ -0,0 +1,87 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef HARDWARE_FACTORY_HH
+#include "hardware_factory.hh"
+#endif
+
+#ifndef HARDWARE_BASE_HH
+#include "hardware_base.hh"
+#endif
+#ifndef HARDWARE_CPU_HH
+#include "hardware_cpu.hh"
+#endif
+#ifndef HARDWARE_4STACK_HH
+#include "hardware_4stack.hh"
+#endif
+#ifndef INST_SET_HH
+#include "inst_set.hh"
+#endif
+#ifndef ORGANISM_HH
+#include "organism.hh"
+#endif
+
+using namespace std;
+
+// Static private variables...
+tList<cHardwareBase> cHardwareFactory::hardware_cpu_list;
+int cHardwareFactory::new_count(0);
+int cHardwareFactory::recycle_count(0);
+
+cHardwareBase * cHardwareFactory::Create(cOrganism * in_org,
+					 cInstSet * inst_set, int type)
+{
+  assert(in_org != NULL);
+  assert(inst_set != NULL && inst_set->OK());
+
+  cHardwareBase * new_hardware = NULL;
+
+  // If there is nothing to recycle, just create a new one.
+  if (hardware_cpu_list.GetSize() == 0) {
+    new_count++;
+    if (type == HARDWARE_TYPE_CPU_ORIGINAL) {
+      new_hardware = new cHardwareCPU(in_org, inst_set);
+    }
+    else if (type == HARDWARE_TYPE_CPU_4STACK) {
+      new_hardware = new cHardware4Stack(in_org, inst_set);
+    }
+  }
+
+  // If we do have hardware to recycle, do so!
+  else {
+    new_hardware = hardware_cpu_list.PopRear();
+    new_hardware->Recycle(in_org, inst_set);
+    recycle_count++;
+  }
+
+  return new_hardware;
+}
+
+// Recycled hardware may be *briefly* in use, so don't delete immediately.
+void cHardwareFactory::Recycle(cHardwareBase * out_hardware)
+{
+  hardware_cpu_list.Push(out_hardware);
+}
+
+// Delete any hardware that needs it, save the rest for re-use.
+void cHardwareFactory::Update()
+{
+  int delete_count = 0;
+  while (hardware_cpu_list.GetSize() > 100) {
+    delete hardware_cpu_list.Pop();
+    delete_count++;
+  }
+
+//    cerr << "   NewHardware: " << new_count
+//         << "   Recycled: " << recycle_count
+//         << "   Deleted: " << delete_count
+//         << "   Stored: " << hardware_cpu_list.GetSize()
+//         << "   Existing: " << cHardwareBase::GetInstanceCount()
+//         << endl;
+
+  new_count = recycle_count = 0;
+}
Index: avida/current/source/cpu/hardware_factory.hh
diff -u /dev/null avida/current/source/cpu/hardware_factory.hh:1.6
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/cpu/hardware_factory.hh	Tue Nov 25 09:37:55 2003
@@ -0,0 +1,32 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef HARDWARE_FACTORY_HH
+#define HARDWARE_FACTORY_HH
+
+#ifndef TLIST_HH
+#include "tList.hh"
+#endif
+
+class cHardwareBase;
+class cOrganism;
+class cInstSet;
+
+class cHardwareFactory {
+private:
+  // A static list for each hardware type.
+  static tList<cHardwareBase> hardware_cpu_list;
+  static int new_count;
+  static int recycle_count;
+public:
+  static cHardwareBase * Create(cOrganism * in_org, cInstSet * inst_set,
+				int type=0);
+  static void Recycle(cHardwareBase * out_hardware);
+  static void Update();
+};
+
+#endif
Index: avida/current/source/cpu/hardware_util.cc
diff -u /dev/null avida/current/source/cpu/hardware_util.cc:1.32
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/cpu/hardware_util.cc	Tue Nov 25 09:37:55 2003
@@ -0,0 +1,183 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef HARDWARE_UTIL_HH
+#include "hardware_util.hh"
+#endif
+
+#ifndef CONFIG_HH
+#include "config.hh"
+#endif
+#ifndef HARDWARE_UTIL_HH
+#include "hardware_base.hh"
+#endif
+#ifndef HARDWARE_CPU_HH
+#include "hardware_cpu.hh"
+#endif
+#ifndef HARDWARE_4STACK_HH
+#include "hardware_4stack.hh"
+#endif
+#ifndef INIT_FILE_HH
+#include "init_file.hh"
+#endif
+#ifndef INST_SET_HH
+#include "inst_set.hh"
+#endif
+
+using namespace std;
+
+
+void cHardwareUtil::LoadInstSet(cString filename, cInstSet & inst_set, 
+				tDictionary<int> & nop_dict,
+				tDictionary<int> & inst_dict
+){
+  // If there is no filename, use the default for the appropriate hardware.
+  cString default_filename = "unknown";
+  if (cConfig::GetHardwareType() == HARDWARE_TYPE_CPU_ORIGINAL) {
+    default_filename = cHardwareCPU::GetDefaultInstFilename();
+  }
+  else if (cConfig::GetHardwareType() == HARDWARE_TYPE_CPU_4STACK) {
+    default_filename = cHardware4Stack::GetDefaultInstFilename();
+  }
+
+  if (filename == "") {
+    cerr << "Warning: No instruction set specified; using default '"
+	 << filename << "'." << endl;
+    filename = default_filename;
+  }
+
+  cInitFile file(filename);
+
+  // If we could not open the instruction set what to do?
+  if (file.IsOpen() == false) {
+
+    // If this is the default filename, write the file and try again.
+    if (filename == default_filename) {
+      if (cConfig::GetHardwareType() == HARDWARE_TYPE_CPU_ORIGINAL) {
+	cHardwareCPU::WriteDefaultInstSet();
+      }
+      else if (cConfig::GetHardwareType() == HARDWARE_TYPE_CPU_4STACK) {
+	cHardware4Stack::WriteDefaultInstSet();
+      }      
+    }
+
+    // If this is not the default filename, give and error and stop.
+    else {
+      cerr << "Error: Could not open instruction set '" << filename
+	   << "'.  Halting." << endl;
+      exit(1);
+    }
+  }
+
+  file.Load();
+  file.Compress();
+
+  for (int line_id = 0; line_id < file.GetNumLines(); line_id++) {
+    cString cur_line = file.GetLine(line_id);
+    cString inst_name = cur_line.PopWord();
+    int redundancy = cur_line.PopWord().AsInt();
+    int cost = cur_line.PopWord().AsInt();
+    int ft_cost = cur_line.PopWord().AsInt();
+    double prob_fail = cur_line.PopWord().AsDouble();
+
+    // If this instruction has 0 redundancy, we don't want it!
+    if (redundancy < 0) continue;
+    if (redundancy > 256) {
+      cerr << "Error: Max redundancy is 256.  Resetting redundancy of \""
+	   << inst_name << "\" from " << redundancy << " to 256." << endl;
+      redundancy = 256;
+    }
+    
+    // Otherwise, this instruction will be in the set.
+    // First, determine if it is a nop...
+    int nop_mod = -1;
+    if(nop_dict.Find(inst_name, nop_mod) == true) {
+      inst_set.AddNop2(nop_mod, redundancy, ft_cost, cost, prob_fail);
+      continue;
+    }
+
+    // Otherwise, it had better be in the main dictionary...
+    int fun_id = -1;
+    if(inst_dict.Find(inst_name, fun_id) == true){
+      inst_set.Add2(fun_id, redundancy, ft_cost, cost, prob_fail);
+      continue;
+    }
+
+    // Oh oh!  Didn't find an instruction!
+    cerr << endl
+	 << "Error: Could not find instruction '" << inst_name << "'" << endl
+	 << "       (Best match = '"
+	 << inst_dict.NearMatch(inst_name) << "')" << endl;
+    exit(1);
+  }
+
+  cerr << "Loaded Instruction Library \"" << filename
+       << "\" with " << inst_set.GetSize() << " instructions." << endl;
+}
+
+void cHardwareUtil::LoadInstSet_CPUOriginal(const cString & filename, cInstSet & inst_set)
+{
+  // Nops (or other modifying-instructions...)  Note: Nops must be the
+  //  first instructions added to the set.
+
+  // Build a dictionary of instructions and their corresponding methods...
+  
+  tDictionary<int> nop_dict;
+  for(int i=0; i<inst_set.GetInstLib()->GetNumNops(); i++)
+    nop_dict.Add(inst_set.GetInstLib()->GetNopName(i), i);
+
+  tDictionary<int> inst_dict;
+  for(int i=0; i<inst_set.GetInstLib()->GetSize(); i++)
+    inst_dict.Add(inst_set.GetInstLib()->GetName(i), i);
+
+  // And load it on up!
+  LoadInstSet(filename, inst_set, nop_dict, inst_dict);
+}
+
+void cHardwareUtil::LoadInstSet_CPU4Stack(const cString & filename, cInstSet & inst_set)
+{
+  // Nops (or other modifying-instructions...)  Note: Nops must be the
+  //  first instructions added to the set.
+
+  // Build a dictionary of instructions and their corresponding methods...
+  
+  tDictionary<int> nop_dict;
+  for(int i=0; i<inst_set.GetInstLib()->GetNumNops(); i++)
+    nop_dict.Add(inst_set.GetInstLib()->GetNopName(i), i);
+
+  tDictionary<int> inst_dict;
+  for(int i=0; i<inst_set.GetInstLib()->GetSize(); i++)
+    inst_dict.Add(inst_set.GetInstLib()->GetName(i), i);
+
+  cout << "Instruction Library in util has " << inst_dict.GetSize()
+       << " instructions and " << nop_dict.GetSize() <<  " nops." << endl;
+
+
+  // And load it on up!
+  LoadInstSet(filename, inst_set, nop_dict, inst_dict);
+}
+
+cInstSet & cHardwareUtil::DefaultInstSet(const cString & inst_filename)
+{
+  static cInstSet inst_set;
+
+  // If we don't have an instruction set yet, and we've been given a filename,
+  // set it up.
+  if (inst_filename != "" && inst_set.GetSize() == 0) {
+    if (cConfig::GetHardwareType() == HARDWARE_TYPE_CPU_ORIGINAL) {
+      inst_set.SetInstLib(cHardwareCPU::GetInstLib());
+      LoadInstSet_CPUOriginal(inst_filename, inst_set);
+    }
+    else if (cConfig::GetHardwareType() == HARDWARE_TYPE_CPU_4STACK) {
+      inst_set.SetInstLib(cHardware4Stack::GetInstLib());
+      LoadInstSet_CPU4Stack(inst_filename, inst_set);
+    }
+  }
+
+  return inst_set;
+}
+
Index: avida/current/source/cpu/hardware_util.hh
diff -u /dev/null avida/current/source/cpu/hardware_util.hh:1.11
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/cpu/hardware_util.hh	Tue Nov 25 09:37:55 2003
@@ -0,0 +1,33 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef HARDWARE_UTIL_HH
+#define HARDWARE_UTIL_HH
+
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+#ifndef TDICTIONARY_HH
+#include "tDictionary.hh"
+#endif
+
+class cString; // aggregate
+class cInstSet;
+template <class T> class tDictionary;
+
+class cHardwareUtil {
+public:
+  static void LoadInstSet( cString filename, cInstSet & inst_set, 
+	tDictionary<int> & nop_dict, tDictionary<int> & inst_dict );
+  static void LoadInstSet_CPUOriginal(const cString & filename,
+				      cInstSet & inst_set);
+  static void LoadInstSet_CPU4Stack(const cString & filename,
+				    cInstSet & inst_set);
+  static cInstSet & DefaultInstSet(const cString & inst_filename);
+};
+
+#endif
Index: avida/current/source/cpu/test_cpu.cc
diff -u /dev/null avida/current/source/cpu/test_cpu.cc:1.45
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/cpu/test_cpu.cc	Tue Nov 25 09:37:55 2003
@@ -0,0 +1,379 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef TEST_CPU_HH
+#include "test_cpu.hh"
+#endif
+
+#ifndef CPU_TEST_INFO_HH
+#include "cpu_test_info.hh"
+#endif
+#ifndef CONFIG_HH
+#include "config.hh"
+#endif
+#ifndef ENVIRONMENT_HH
+#include "environment.hh"
+#endif
+#ifndef FUNCTIONS_HH
+#include "functions.hh"
+#endif
+#ifndef HARDWARE_BASE_HH
+#include "hardware_base.hh"
+#endif
+#ifndef INST_SET_HH
+#include "inst_set.hh"
+#endif
+#ifndef INST_UTIL_HH
+#include "inst_util.hh"
+#endif
+#ifndef ORGANISM_HH
+#include "organism.hh"
+#endif
+#ifndef PHENOTYPE_HH
+#include "phenotype.hh"
+#endif
+#ifndef POPULATION_INTERFACE_HH
+#include "population_interface.hh"
+#endif
+#ifndef RESOURCE_COUNT_HH
+#include "resource_count.hh"
+#endif
+#ifndef STRING_UTIL_HH
+#include "string_util.hh"
+#endif
+#ifndef TMATRIX_HH
+#include "tMatrix.hh"
+#endif
+
+#include <iomanip>
+
+
+using namespace std;
+
+
+// Static Variables
+cInstSet * cTestCPU::inst_set(NULL);
+cEnvironment * cTestCPU::environment(NULL);
+cPopulationInterface cTestCPU::test_interface;
+tArray<int> cTestCPU::input_array;
+int cTestCPU::cur_input;
+cResourceCount * cTestCPU::resource_count(NULL);
+
+bool cTestCPU::initialized(false);
+
+
+
+//////////////////////////////
+//  cTestCPU  (Static Class)
+//////////////////////////////
+
+void cTestCPU::Setup(cInstSet * in_inst_set,  cEnvironment * in_env,
+		     const cPopulationInterface & in_interface)
+{
+  inst_set = in_inst_set;
+  environment = in_env;
+  test_interface = in_interface;
+
+  resource_count = new cResourceCount(environment->GetResourceLib().GetSize());
+
+  initialized = true;
+}
+
+void cTestCPU::SetInstSet(cInstSet * in_inst_set)
+{
+  inst_set = in_inst_set;
+}
+
+// NOTE: This method assumes that the organism is a fresh creation.
+bool cTestCPU::ProcessGestation(cCPUTestInfo & test_info, int cur_depth)
+{
+  assert(initialized == true);
+  assert(test_info.org_array[cur_depth] != NULL);
+
+  cOrganism & organism = *( test_info.org_array[cur_depth] );
+
+  // Determine how long this organism should be tested for...
+  int time_allocated = cConfig::GetTestCPUTimeMod() *
+    organism.GetGenome().GetSize();
+
+  // Make sure this genome stands a chance...
+  if (TestIntegrity(organism.GetGenome()) == false)  time_allocated = 0;
+
+  // Prepare the inputs...
+  cur_input = 0;
+
+  // Determine if we're tracing and what we need to print.
+  ostream * trace_fp =
+    test_info.GetTraceExecution() ? &(test_info.GetTraceFP()) : NULL;
+
+  int time_used = 0;
+  while (time_used < time_allocated &&
+	 organism.GetHardware().GetMemory().GetSize() &&
+	 organism.GetPhenotype().GetNumDivides() == 0) {
+    time_used++;
+    organism.GetHardware().SingleProcess(trace_fp);
+    // @CAO Need to watch out for parasites.
+  }
+
+  // For now, always return true.
+  return true;
+}
+
+
+bool cTestCPU::TestGenome(cCPUTestInfo & test_info, const cGenome & genome)
+{
+  assert(initialized == true);
+
+  test_info.Clear();
+  TestGenome_Body(test_info, genome, 0);
+
+  return test_info.is_viable;
+}
+
+bool cTestCPU::TestGenome(cCPUTestInfo & test_info, const cGenome & genome,
+		       ofstream & out_fp)
+{
+  assert(initialized == true);
+
+  test_info.Clear();
+  TestGenome_Body(test_info, genome, 0);
+
+  ////////////////////////////////////////////////////////////////
+  // IsViable() == false
+  //   max_depth == 0  : (0) Parent doesn't divide
+  //   max_depth == 1  : (2) Parent does divide, but child does not.
+  //   max_depth >= 2  : (3) Parent and child do divide, but neither true.
+  // ------------------------------------------------------------
+  // IsViable() == true
+  //   max_depth == 0  : (4) Parent Breed True
+  //   max_depth == 1  : (5) Parent NOT Breed True, but Child Does
+  //   max_depth >= 2  : (6) Multiple levels of non-breed true.
+  ////////////////////////////////////////////////////////////////
+
+
+  const int depth_comp = Min(test_info.max_depth, 2);
+  int repro_type = ((int) test_info.is_viable) * 3 + 1 + depth_comp;
+  if (test_info.is_viable == false && depth_comp == 0)  repro_type = 0;
+
+  out_fp << test_info.is_viable << " "
+	 << test_info.max_depth << " "
+	 << test_info.depth_found << " "
+	 << test_info.max_cycle << " "
+	 << repro_type << endl;
+
+  return test_info.is_viable;
+}
+
+
+bool cTestCPU::TestGenome_Body(cCPUTestInfo & test_info,
+			       const cGenome & genome, int cur_depth)
+{
+  assert(initialized == true);
+  assert(cur_depth < test_info.generation_tests);
+
+  if (test_info.GetUseRandomInputs() == false) {
+    // We make sure that all combinations of inputs are present.  This is
+    // done explicitly in the key columns... (0f, 33, and 55)
+    input_array.Resize(3);
+    //    input_array[0] = 0x130f149f;  // 00010011 00001111 00010100 10011111
+    //    input_array[1] = 0x0833e53e;  // 00001000 00110011 11100101 00111110
+    //    input_array[2] = 0x625541eb;  // 01100010 01010101 01000001 11101011
+
+    input_array[0] = 0x0f13149f;  // 00001111 00010011 00010100 10011111
+    input_array[1] = 0x3308e53e;  // 00110011 00001000 11100101 00111110
+    input_array[2] = 0x556241eb;  // 01010101 01100010 01000001 11101011
+  } else {
+    environment->SetupInputs(input_array);
+  }
+
+  if (cur_depth > test_info.max_depth) test_info.max_depth = cur_depth;
+
+  // Setup the organism we're working with now.
+  if (test_info.org_array[cur_depth] != NULL) {
+    delete test_info.org_array[cur_depth];
+  }
+  test_info.org_array[cur_depth] =
+    new cOrganism(genome, test_interface, *environment);
+  cOrganism & organism = *( test_info.org_array[cur_depth] );
+  organism.GetPhenotype().SetupInject(genome.GetSize());
+
+  // Run the current organism.
+  ProcessGestation(test_info, cur_depth);
+
+  // Must be able to divide twice in order to form a successful colony,
+  // assuming the CPU doesn't get reset on divides.
+  //
+  // The possibilities after this gestation cycle are:
+  //  1: It did not copy at all => Exit this level.
+  //  2: It copied true => Check next gestation cycle, or set is_viable.
+  //  3: Its copy looks like an ancestor => copy true.
+  //  4: It copied false => we must check the child.
+
+  // Case 1:  ////////////////////////////////////
+  if (organism.GetPhenotype().GetNumDivides() == 0)  return false;
+
+  // Case 2:  ////////////////////////////////////
+  if (organism.GetPhenotype().CopyTrue() == true) {
+    test_info.depth_found = cur_depth;
+    test_info.is_viable = true;
+    return true;
+  }
+
+  // Case 3:  ////////////////////////////////////
+  bool is_ancestor = false;
+  for (int anc_depth = 0; anc_depth < cur_depth; anc_depth++) {
+    if (organism.ChildGenome() == test_info.org_array[anc_depth]->GetGenome()){
+      is_ancestor = true;
+      const int cur_cycle = cur_depth - anc_depth;
+      if (test_info.max_cycle < cur_cycle) test_info.max_cycle = cur_cycle;
+      test_info.cycle_to = anc_depth;
+    }
+  }
+  if (is_ancestor) {
+    test_info.depth_found = cur_depth;
+    test_info.is_viable = true;
+    return true;
+  }
+
+  // Case 4:  ////////////////////////////////////
+  // If we haven't reached maximum depth yet, check out the child.
+  if (cur_depth+1 < test_info.generation_tests) {
+    // Run the child's genome.
+    return TestGenome_Body(test_info, organism.ChildGenome(), cur_depth+1);
+  }
+
+
+  // All options have failed; just return false.
+  return false;
+}
+
+
+
+
+void cTestCPU::TraceGenome(const cGenome & genome, cString filename)
+{
+  assert(initialized == true);
+
+  if (genome.GetSize() == 0) return;
+
+  // Build the test info for printing.
+  cCPUTestInfo test_info;
+  test_info.TestThreads();
+
+  test_info.Clear();
+  test_info.SetTraceExecution(filename);
+  TestGenome_Body(test_info, genome, 0);
+}
+
+
+void cTestCPU::TestThreads(const cGenome & genome)
+{
+  assert(initialized == true);
+
+  static ofstream fp("threads.dat");
+
+  cCPUTestInfo test_info;
+  test_info.TestThreads();
+  cTestCPU::TestGenome(test_info, genome);
+
+//  fp << cStats::GetUpdate()             << " "    // 1
+//     << genome.GetSize()                << " ";   // 2
+//       << cStats::GetAveNumThreads()      << " "   // 3
+//       << cStats::GetAveThreadDist()      << " ";  // 4
+
+//    fp << test_info.GetGenotypeMerit()          << " "   // 5
+//       << test_info.GetGenotypeGestation()      << " "   // 6
+//       << test_info.GetGenotypeFitness()        << " "   // 7
+//       << test_info.GetGenotypeThreadFrac()     << " "   // 8
+//       << test_info.GetGenotypeThreadTimeDiff() << " "   // 9
+//       << test_info.GetGenotypeThreadCodeDiff() << " ";  // 10
+
+//    fp << test_info.GetColonyMerit()          << " "   // 11
+//       << test_info.GetColonyGestation()      << " "   // 12
+//       << test_info.GetColonyFitness()        << " "   // 13
+//       << test_info.GetColonyThreadFrac()     << " "   // 14
+//       << test_info.GetColonyThreadTimeDiff() << " "   // 15
+//       << test_info.GetColonyThreadCodeDiff() << " ";  // 16
+
+  fp << endl;
+}
+
+
+void cTestCPU::PrintThreads(const cGenome & genome)
+{
+  assert(initialized == true);
+
+  cCPUTestInfo test_info;
+  test_info.TestThreads();
+  test_info.PrintThreads();
+  cTestCPU::TestGenome(test_info, genome);
+}
+
+
+bool cTestCPU::TestIntegrity(const cGenome & test_genome)
+{
+#ifdef QUICK_BASE_TEST_CPU
+  // This checks to make sure a 'copy', 'divide', and 'allocate' are all in
+  // the creatures, and if not doesn't even bother to test it.
+  static UCHAR copy_id  = inst_set->GetInstID("copy");
+  static UCHAR div_id   = inst_set->GetInstID("divide");
+  static UCHAR alloc_id = inst_set->GetInstID("allocate");
+#endif
+
+#ifdef QUICK_HEAD_TEST_CPU
+  // This checks to make sure a 'copy', 'divide', and 'allocate' are all in
+  // the creatures, and if not doesn't even bother to test it.
+  static UCHAR copy_id  = inst_set->GetInstID("h-copy");
+  static UCHAR div_id   = inst_set->GetInstID("h-divide");
+  static UCHAR alloc_id = inst_set->GetInstID("h-alloc");
+#endif
+
+
+#ifdef QUICK_TEST_CPU
+  bool copy_found = false;
+  bool div_found = false;
+  bool alloc_found = false;
+
+  for (int i = 0; i < test_genome.GetSize(); i++) {
+    if (test_genome[i].GetOp() == copy_id)  copy_found  = true;
+    if (test_genome[i].GetOp() == div_id)   div_found   = true;
+    if (test_genome[i].GetOp() == alloc_id) alloc_found = true;
+  }
+
+  if (copy_found == false || div_found == false || alloc_found == false) {
+    return false;
+  }
+#endif
+
+  return true;
+}
+
+
+
+int cTestCPU::GetInput()
+{
+  if (cur_input >= input_array.GetSize()) cur_input = 0;
+  return input_array[cur_input++];
+}
+
+int cTestCPU::GetInputAt(int & input_pointer)
+{
+  if (input_pointer >= input_array.GetSize()) input_pointer = 0;
+  return input_array[input_pointer++];
+}
+
+const tArray<double> & cTestCPU::GetResources()
+{
+  assert(resource_count != NULL);
+  return resource_count->GetResources();
+}
+
+void cTestCPU::UpdateResources(const tArray<double> & res_change)
+{
+  // Nada for now...
+}
+
Index: avida/current/source/cpu/test_cpu.hh
diff -u /dev/null avida/current/source/cpu/test_cpu.hh:1.34
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/cpu/test_cpu.hh	Tue Nov 25 09:37:55 2003
@@ -0,0 +1,71 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef TEST_CPU_HH
+#define TEST_CPU_HH
+
+#include <fstream>
+
+#ifndef TARRAY_HH
+#include "tArray.hh"
+#endif
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+
+class cInstSet;
+class cEnvironment;
+class cPopulationInterface;
+template <class T> class tArray; // aggregate
+class cResourceCount;
+class cCPUTestInfo;
+class cGenome;
+class cString; // aggregate
+
+class cTestCPU {
+private:
+  static cInstSet * inst_set;
+  static cEnvironment * environment;
+  static cPopulationInterface test_interface;
+  static tArray<int> input_array;
+  static int cur_input;
+  static cResourceCount * resource_count;
+  
+  static bool initialized;
+
+  static bool ProcessGestation(cCPUTestInfo & test_info, int cur_depth);
+
+  static bool TestGenome_Body(cCPUTestInfo & test_info, const cGenome & genome,
+			      int cur_depth);
+
+public:
+  static void Setup(cInstSet * in_inst_set,  cEnvironment * in_env,
+		    const cPopulationInterface & in_interface);
+  static void SetInstSet(cInstSet * in_inst_set);
+
+  static bool TestGenome(cCPUTestInfo & test_info, const cGenome & genome);
+  static bool TestGenome(cCPUTestInfo & test_info, const cGenome & genome,
+			 std::ofstream & out_fp);
+
+  static void TraceGenome(const cGenome &genome, cString filename="trace.dat");
+
+  static void TestThreads(const cGenome & genome);
+  static void PrintThreads(const cGenome & genome);
+
+  // Test if a genome has any chance of being a replicator (i.e., in the
+  // default set, has an allocate, a copy, and a divide).
+  static bool TestIntegrity(const cGenome & test_genome);
+
+  static cInstSet * GetInstSet() { return inst_set; }
+  static cEnvironment * GetEnvironment() { return environment; }
+  static int GetInput();
+  static int GetInputAt(int & input_pointer);
+  static const tArray<double> & GetResources();
+  static void UpdateResources(const tArray<double> & res_change);
+};
+
+#endif
Index: avida/current/source/cpu/test_util.cc
diff -u /dev/null avida/current/source/cpu/test_util.cc:1.10
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/cpu/test_util.cc	Tue Nov 25 09:37:55 2003
@@ -0,0 +1,256 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef TEST_UTIL_HH
+#include "test_util.hh"
+#endif
+
+#ifndef CPU_TEST_INFO_HH
+#include "cpu_test_info.hh"
+#endif
+#ifndef ENVIRONMENT_HH
+#include "environment.hh"
+#endif
+#ifndef GENOME_HH
+#include "genome.hh"
+#endif
+#ifndef GENOTYPE_HH
+#include "genotype.hh"
+#endif
+#ifndef HARDWARE_BASE_HH
+#include "hardware_base.hh"
+#endif
+#ifndef INJECT_GENOTYPE_HH
+#include "inject_genotype.hh"
+#endif
+#ifndef INST_UTIL_HH
+#include "inst_util.hh"
+#endif
+#ifndef ORGANISM_HH
+#include "organism.hh"
+#endif
+#ifndef PHENOTYPE_HH
+#include "phenotype.hh"
+#endif
+#ifndef STATS_HH
+#include "stats.hh"
+#endif
+#ifndef TASK_ENTRY_HH
+#include "task_entry.hh"
+#endif
+#ifndef TEST_CPU_HH
+#include "test_cpu.hh"
+#endif
+
+#include <fstream>
+#include <iomanip>
+
+using namespace std;
+
+void cTestUtil::PrintGenome(const cGenome & genome, cString filename,
+			    cGenotype * genotype, int update_out)
+{
+  if (filename == "") filename.Set("%03d-unnamed", genome.GetSize());
+
+  // Build the test info for printing.
+  cCPUTestInfo test_info;
+  test_info.TestThreads();
+  cTestCPU::TestGenome(test_info, genome);
+
+  // Open the file...
+
+  ofstream fp(filename());
+
+  // @CAO Fix!!!!!!
+  if( fp.good() == false ) {
+    cerr << "Unable to open output file '" <<  filename() << "'" <<
+    endl;
+    return;
+  }
+
+  // Print the useful info at the top...
+
+  fp << "# Filename........: " << filename << endl;
+
+  if (update_out >= 0) fp << "# Update Output...: " << update_out <<
+  endl;
+  else fp << "# Update Output...: N/A" << endl;
+
+  fp << "# Is Viable.......: " << test_info.IsViable()
+  << endl
+     << "# Repro Cycle Size: " << test_info.GetMaxCycle()
+     << endl
+     << "# Depth to Viable.: " << test_info.GetDepthFound()
+     << endl;
+
+  if (genotype != NULL) {
+    fp << "# Update Created..: " << genotype->GetUpdateBorn()     <<
+       endl
+       << "# Genotype ID.....: " << genotype->GetID()             <<
+       endl
+       << "# Parent Gen ID...: " << genotype->GetParentID()       <<
+       endl
+       << "# Tree Depth......: " << genotype->GetDepth()          <<
+       endl
+       << "# Parent Distance.: " << genotype->GetParentDistance() <<
+       endl
+      ;
+  }
+  fp << endl;
+
+  const int num_levels = test_info.GetMaxDepth() + 1;
+  for (int j = 0; j < num_levels; j++) {
+    fp << "# Generation: " << j << endl;
+    cOrganism * organism = test_info.GetTestOrganism(j);
+    assert(organism != NULL);
+    cPhenotype & phenotype = organism->GetPhenotype();
+
+    fp << "# Merit...........: "
+       << setw(12) << setfill(' ') << phenotype.GetMerit() << endl;
+    fp << "# Gestation Time..: "
+       << setw(12) << setfill(' ') << phenotype.GetGestationTime() << endl;
+    fp << "# Fitness.........: "
+       << setw(12) << setfill(' ') << phenotype.GetFitness() << endl;
+    fp << "# Errors..........: "
+       << setw(12) << setfill(' ') << phenotype.GetLastNumErrors() << endl;
+    fp << "# Genome Size.....: "
+       << setw(12) << setfill(' ') << organism->GetGenome().GetSize() << endl;
+    fp << "# Copied Size.....: "
+       << setw(12) << setfill(' ') << phenotype.GetCopiedSize() << endl;
+    fp << "# Executed Size...: "
+       << setw(12) << setfill(' ') << phenotype.GetExecutedSize() << endl;
+
+    fp << "# Offspring.......: ";
+    if (phenotype.GetNumDivides() == 0)
+      fp << setw(12) << setfill(' ') << "NONE";
+    else if (phenotype.CopyTrue() == true)
+      fp << setw(12) << setfill(' ') << "SELF";
+    else if (test_info.GetCycleTo() != -1)
+      fp << setw(12) << setfill(' ') << test_info.GetCycleTo();
+    else
+      fp << setw(12) << setfill(' ') << (j+1);
+    fp << endl;
+
+    fp << endl;     // Skip line
+  }
+  
+  // Display the tasks performed...
+  cPhenotype & phenotype = test_info.GetTestOrganism()->GetPhenotype();
+  for (int i = 0; i < phenotype.GetEnvironment().GetTaskLib().GetSize(); i++) {
+    fp << "# "<< phenotype.GetEnvironment().GetTaskLib().GetTask(i).GetName()
+       << "\t" << phenotype.GetLastTaskCount()[i]
+       << endl;
+  }
+  fp << endl; // Skip line
+
+  // Display the genome
+  const cInstSet & inst_set =
+    test_info.GetTestOrganism()->GetHardware().GetInstSet();
+  cInstUtil::SaveGenome(fp, inst_set, genome);
+}
+
+void cTestUtil::PrintGenome(cInjectGenotype * inject_genotype, 
+			    const cGenome & genome, cString filename, int update_out)
+{
+  if (filename == "") filename.Set("p%03d-unnamed", genome.GetSize());
+
+  // Build the test info for printing.
+  cCPUTestInfo test_info;
+  test_info.TestThreads();
+  cTestCPU::TestGenome(test_info, genome);
+
+  // Open the file...
+
+  ofstream fp(filename());
+
+  // @CAO Fix!!!!!!
+  if( fp.good() == false ) {
+    cerr << "Unable to open output file '" <<  filename() << "'" <<
+    endl;
+    return;
+  }
+
+  // Print the useful info at the top...
+
+  fp << "# Filename........: " << filename << endl;
+
+  if (update_out >= 0) fp << "# Update Output...: " << update_out <<
+  endl;
+  else fp << "# Update Output...: N/A" << endl;
+
+  //fp << "# Is Viable.......: " << test_info.IsViable()
+  //<< endl
+  //   << "# Repro Cycle Size: " << test_info.GetMaxCycle()
+  //   << endl
+  //   << "# Depth to Viable.: " << test_info.GetDepthFound()
+  //   << endl;
+
+  if (inject_genotype != NULL) {
+    fp << "# Update Created..: " << inject_genotype->GetUpdateBorn()     <<
+       endl
+       << "# Genotype ID.....: " << inject_genotype->GetID()             <<
+       endl
+       << "# Parent Gen ID...: " << inject_genotype->GetParentID()       <<
+       endl
+       << "# Tree Depth......: " << inject_genotype->GetDepth()          <<
+       endl
+      //<< "# Parent Distance.: " << inject_genotype->GetParentDistance() <<
+      // endl
+      ;
+  }
+  fp << endl;
+
+  //const int num_levels = test_info.GetMaxDepth() + 1;
+  /*for (int j = 0; j < num_levels; j++) {
+    fp << "# Generation: " << j << endl;
+    cOrganism * organism = test_info.GetTestOrganism(j);
+    assert(organism != NULL);
+    cPhenotype & phenotype = organism->GetPhenotype();
+
+    fp << "# Merit...........: "
+       << setw(12) << setfill(' ') << phenotype.GetMerit() << endl;
+    fp << "# Gestation Time..: "
+       << setw(12) << setfill(' ') << phenotype.GetGestationTime() << endl;
+    fp << "# Fitness.........: "
+       << setw(12) << setfill(' ') << phenotype.GetFitness() << endl;
+    fp << "# Errors..........: "
+       << setw(12) << setfill(' ') << phenotype.GetLastNumErrors() << endl;
+    fp << "# Genome Size.....: "
+       << setw(12) << setfill(' ') << organism->GetGenome().GetSize() << endl;
+    fp << "# Copied Size.....: "
+       << setw(12) << setfill(' ') << phenotype.GetCopiedSize() << endl;
+    fp << "# Executed Size...: "
+       << setw(12) << setfill(' ') << phenotype.GetExecutedSize() << endl;
+
+    fp << "# Offspring.......: ";
+    if (phenotype.GetNumDivides() == 0)
+      fp << setw(12) << setfill(' ') << "NONE";
+    else if (phenotype.CopyTrue() == true)
+      fp << setw(12) << setfill(' ') << "SELF";
+    else if (test_info.GetCycleTo() != -1)
+      fp << setw(12) << setfill(' ') << test_info.GetCycleTo();
+    else
+      fp << setw(12) << setfill(' ') << (j+1);
+    fp << endl;
+
+    fp << endl;     // Skip line
+    }
+  
+  // Display the tasks performed...
+  cPhenotype & phenotype = test_info.GetTestOrganism()->GetPhenotype();
+  for (int i = 0; i < phenotype.GetEnvironment().GetTaskLib().GetSize(); i++) {
+    fp << "# "<< phenotype.GetEnvironment().GetTaskLib().GetTask(i).GetName()
+       << "\t" << phenotype.GetLastTaskCount()[i]
+       << endl;
+  }
+  fp << endl; // Skip line
+  */
+  // Display the genome
+  const cInstSet & inst_set =
+    test_info.GetTestOrganism()->GetHardware().GetInstSet();
+  cInstUtil::SaveGenome(fp, inst_set, genome);
+}
Index: avida/current/source/cpu/test_util.hh
diff -u /dev/null avida/current/source/cpu/test_util.hh:1.5
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/cpu/test_util.hh	Tue Nov 25 09:37:55 2003
@@ -0,0 +1,33 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef TEST_UTIL_HH
+#define TEST_UTIL_HH
+
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+
+// ------------------------------------------------------------------------
+//  This class uses test CPUs in combination with genotypes and all types
+//  of hardware in order to produce more useful test info.
+// ------------------------------------------------------------------------
+
+class cString; // aggregate
+class cGenome;
+class cGenotype;
+class cInjectGenotype;
+
+class cTestUtil {
+public:
+  static void PrintGenome(const cGenome & genome, cString filename="",
+			  cGenotype * genotype=NULL, int update_out=-1);
+  static void PrintGenome(cInjectGenotype * genotype, const cGenome & genome, 
+			  cString filename="", int update_out=-1);
+};
+
+#endif
Index: avida/current/source/cpu/Makefile.am
diff -u avida/current/source/cpu/Makefile.am:1.18 avida/current/source/cpu/Makefile.am:1.19
--- avida/current/source/cpu/Makefile.am:1.18	Thu May 22 11:58:51 2003
+++ avida/current/source/cpu/Makefile.am	Tue Nov 25 09:37:53 2003
@@ -1,15 +1,30 @@
+SOURCE_DIR = $(srcdir)/..
+SOURCE_INC = -I$(SOURCE_DIR)
+EVENT_DIR = $(SOURCE_DIR)/event
+EVENT_INC = -I$(EVENT_DIR)
+CPU_DIR = $(SOURCE_DIR)/cpu
+CPU_INC = -I$(CPU_DIR)
+TOOLS_DIR = $(SOURCE_DIR)/tools
+TOOLS_INC = -I$(TOOLS_DIR)
+MAIN_DIR = $(SOURCE_DIR)/main
+MAIN_INC = -I$(MAIN_DIR)
+INCLUDES = $(EVENT_INC) $(CPU_INC) $(TOOLS_INC) $(MAIN_INC) $(SOURCE_INC)
 
 libcpu_a_SOURCES = \
+  4stack_head.cc 4stack_head.hh \
+  code_label.cc code_label.hh \
+  cpu_head.cc cpu_head.hh \
   cpu_memory.cc cpu_memory.hh \
   cpu_stack.cc cpu_stack.hh \
+  cpu_test_info.cc cpu_test_info.hh \
+  hardware_4stack.cc hardware_4stack.hh \
+  hardware_4stack_thread.cc hardware_4stack_thread.hh \
   hardware_base.cc hardware_base.hh \
   hardware_cpu.cc hardware_cpu.hh \
-  hardware_4stack.cc hardware_4stack.hh \
-  hardware_method.hh \
+  hardware_cpu_thread.cc hardware_cpu_thread.hh \
   hardware_factory.cc hardware_factory.hh \
   hardware_util.cc hardware_util.hh \
-  head.cc head.hh \
-  label.cc label.hh \
+  memory_flags.cc memory_flags.hh \
   test_cpu.cc test_cpu.hh \
   test_util.cc test_util.hh \
   cpu_defs.hh \
Index: avida/current/source/event/event.cc
diff -u /dev/null avida/current/source/event/event.cc:1.5
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/event/event.cc	Tue Nov 25 09:37:55 2003
@@ -0,0 +1,18 @@
+
+
+#include "event.hh"
+
+
+using namespace std;
+
+
+cEvent::cEvent( const cString & name, const cString & args ,
+		int factory_id )
+  : m_name( name ), m_args( args ), m_factory_id( factory_id )
+{
+}
+
+
+cEvent::~cEvent()
+{
+}
Index: avida/current/source/event/event.hh
diff -u /dev/null avida/current/source/event/event.hh:1.3
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/event/event.hh	Tue Nov 25 09:37:55 2003
@@ -0,0 +1,61 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef EVENT_HH
+#define EVENT_HH
+
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+
+/**
+ * This is a virtual base class for an event in Avida.
+ * It holds the name of the event, a string of arguments, and the id of
+ * the factory (@ref cEventFactory) it is created from.
+ **/
+
+class cString; // aggregate
+
+class cEvent {
+public:
+  enum eTriggerVariable { UPDATE, GENERATION, IMMEDIATE, UNDEFINED };
+
+private:
+  cString m_name;
+  cString m_args;
+
+  int m_factory_id;
+
+  // not implemented, prevents inadvertent wrong instantiation
+  cEvent();
+  cEvent( const cEvent & );
+  cEvent& operator=( const cEvent& );
+
+public:
+  // constructors
+  cEvent( const cString & name = "Undefined",
+	  const cString & args = "",
+	  int handler_id = -1 );
+  virtual ~cEvent();
+
+
+  // manipulators
+  void SetFactoryId(int factory_id){ m_factory_id = factory_id; }
+
+  /**
+   * This is a pure virtual function that has to be overloaded by derived
+   * classes. It does the actual 'thing' the event is supposed to do.
+   **/
+  virtual void Process() = 0;
+
+  // accessors
+  const cString &  GetName()       const { return m_name; }
+  const cString &  GetArgs()       const { return m_args; }
+  int              GetFactoryId()  const { return m_factory_id; }
+};
+
+#endif
Index: avida/current/source/event/event_factory.cc
diff -u /dev/null avida/current/source/event/event_factory.cc:1.5
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/event/event_factory.cc	Tue Nov 25 09:37:55 2003
@@ -0,0 +1,28 @@
+
+#include "event_factory.hh"
+
+
+#include "defs.hh"
+#include "file.hh"
+#include "string.hh"
+#include "./event.hh"
+
+
+using namespace std;
+
+
+//////// cEventFactory ////////////
+
+cEventFactory::cEventFactory() : m_factory_id( 0 )
+{
+}
+
+
+cEventFactory::~cEventFactory()
+{
+}
+
+
+
+
+
Index: avida/current/source/event/event_factory.hh
diff -u /dev/null avida/current/source/event/event_factory.hh:1.3
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/event/event_factory.hh	Tue Nov 25 09:37:55 2003
@@ -0,0 +1,62 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef EVENT_FACTORY_HH
+#define EVENT_FACTORY_HH
+
+/**
+ * This class is used to construct events from a given name and argument list.
+ * You have to overload it to construct events that need particular additional
+ * information (like a pointer to a class they should act on).
+ **/
+
+class cEvent;
+class cString;
+
+class cEventFactory {
+private:
+  int m_factory_id;
+
+  // not implemented, prevents inadvertent wrong instantiation
+  cEventFactory( const cEventFactory & );
+  cEventFactory& operator=( const cEventFactory& );
+
+public:
+  cEventFactory();
+  virtual ~cEventFactory();
+
+  void SetFactoryId( int id ){
+    m_factory_id = id; }
+
+  int GetFactoryId(){
+    return m_factory_id; }
+
+  /**
+   * Returns an id for an event name. The id holds only for this factory,
+   * a second factory might use the same id for something else.
+   **/
+  virtual int EventNameToEnum(const cString & name) const = 0;
+
+  /**
+   * Constructs an event.
+   *
+   * @param event_enum The identifier of the event to be constructed.
+   * @param args The argument list of the event.
+   **/
+  virtual cEvent * ConstructEvent( int event_enum, const cString & args )=0;
+
+  /**
+   * Constructs an event.
+   *
+   * @param name The name of the event to be constructed.
+   * @param args The argument list of the event.
+   **/
+  cEvent * ConstructEvent( const cString & name, const cString & args ){
+    return ConstructEvent( EventNameToEnum(name), args ); }
+};
+
+#endif
Index: avida/current/source/event/event_factory_manager.cc
diff -u /dev/null avida/current/source/event/event_factory_manager.cc:1.5
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/event/event_factory_manager.cc	Tue Nov 25 09:37:55 2003
@@ -0,0 +1,76 @@
+
+#include "event_factory_manager.hh"
+
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+
+#ifndef EVENT_HH
+#include "event.hh"
+#endif
+
+#ifndef EVENT_FACTORY_HH
+#include "event_factory.hh"
+#endif
+
+
+using namespace std;
+
+
+/////////////////
+//  cEventFactoryManager
+/////////////////
+
+cEventFactoryManager::cEventFactoryManager()
+{
+}
+
+cEventFactoryManager::~cEventFactoryManager(){
+  vector<cEventFactory*>::iterator it = m_factory_list.begin();
+
+  for( ; it != m_factory_list.end(); it++ )
+    delete *it;
+}
+
+
+cEvent*
+cEventFactoryManager::ConstructEvent(const cString name,
+			      const cString & args,
+			      int factory_id){
+  cEvent* event = NULL;
+
+  // factory_id < 0 => send to all factories
+  if( factory_id < 0 ){
+    vector<cEventFactory*>::iterator it;
+    for( it = m_factory_list.begin(); it != m_factory_list.end(); it++ ){
+      if( *it != NULL )
+	event = (*it)->ConstructEvent(name,args);
+      if ( event != NULL ) // if we have found one factory that can create the
+	//                    event we want we stop.
+	break;
+    }
+  }
+  else{
+    // send to particular factory
+    if ( factory_id >= static_cast<int>( m_factory_list.size() ) )
+      return NULL;
+    if( m_factory_list[factory_id] != NULL )
+      event = m_factory_list[factory_id]->ConstructEvent(name,args);
+  }
+  return event;
+}
+
+
+int
+cEventFactoryManager::AddFactory( cEventFactory *factory )
+{
+  assert( factory != NULL );
+  m_factory_list.push_back( factory );
+
+  int id = m_factory_list.size();
+  factory->SetFactoryId( id );
+
+  return id;
+}
+
+
Index: avida/current/source/event/event_factory_manager.hh
diff -u /dev/null avida/current/source/event/event_factory_manager.hh:1.4
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/event/event_factory_manager.hh	Tue Nov 25 09:37:55 2003
@@ -0,0 +1,52 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef EVENT_FACTORY_MANAGER_HH
+#define EVENT_FACTORY_MANAGER_HH
+
+#include <vector>
+
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+
+/**
+ * This class serves as a collection of different event factories
+ * (@ref cEventFactory). It is useful to have different event factories if
+ * we want to have events with different base types, say one type that operates
+ * on class A, while the other operates on class B.
+ **/
+
+class cEventFactory;
+class cEvent;
+class cString; // aggregate
+
+class cEventFactoryManager {
+private:
+  std::vector<cEventFactory*> m_factory_list;
+
+
+  // not implemented, prevents inadvertent wrong instantiation
+  cEventFactoryManager( const cEventFactoryManager & );
+  cEventFactoryManager& operator=( const cEventFactoryManager& );
+public:
+  cEventFactoryManager();
+  ~cEventFactoryManager();
+
+  int AddFactory(cEventFactory* factory);
+
+  /**
+   * This function is used to construct an event. It sends the event's name
+   * to all registered factories if no factory id is given, otherwise it
+   * sends it to the particular factory requested.
+   **/
+  cEvent* ConstructEvent(const cString name, const cString & args,
+			 int factory_id = -1);
+
+};
+
+#endif
Index: avida/current/source/event/event_list.cc
diff -u /dev/null avida/current/source/event/event_list.cc:1.12
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/event/event_list.cc	Tue Nov 25 09:37:55 2003
@@ -0,0 +1,408 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef EVENT_LIST_HH
+#include "event_list.hh"
+#endif
+
+#ifndef DEFS_HH
+#include "defs.hh"
+#endif
+#ifndef EVENT_FACTORY_MANAGER_HH
+#include "event_factory_manager.hh"
+#endif
+#ifndef EVENT_LIST_ENTRY_HH
+#include "event_list_entry.hh"
+#endif
+#ifndef EVENT_TRIGGERS_HH
+#include "event_triggers.hh"
+#endif
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+
+#include <float.h>           // for DBL_MIN
+
+using namespace std;
+
+class cEventFactoryManager; // access
+class cEventTriggers; // access
+class cEventListEntry; // access
+class cString; // aggregate
+class cEvent;
+
+/////////////////
+//  cEventList
+/////////////////
+cEventList::cEventList( cEventFactoryManager* factory_manager,  cEventTriggers *triggers ) :
+  m_factory_manager( factory_manager ),
+  m_triggers( triggers ),
+  m_head(NULL),
+  m_tail(NULL),
+  m_current(NULL),
+  m_num_events(0)
+{
+}
+
+cEventList::~cEventList() {
+  /*
+  XXX:  modified by kaben.  DeleteAll is equivalent.
+  */
+  //while( m_head != NULL ){
+  //  m_current = m_head;
+  //  m_head = m_head->GetNext();
+  //  delete m_head;
+  //}
+  DeleteAll();
+
+  delete m_factory_manager;
+  delete m_triggers;
+}
+
+bool
+cEventList::AddEvent( cEventTriggers::eTriggerVariable trigger,
+			   double start, double interval, double stop,
+			   const cString & name, const cString & args ){
+  assert( m_factory_manager != NULL );
+  cEvent *event = m_factory_manager->ConstructEvent( name, args );
+
+  ///// Adding Event to the list /////
+  if( event != NULL ){
+    InsertEvent(event, trigger, start, interval, stop);
+    return true;
+  }
+  else return false;
+}
+
+
+void cEventList::InsertEvent(cEvent *event,
+			     cEventTriggers::eTriggerVariable trigger,
+			     double start, double interval, double stop){
+  assert( event != NULL );
+  cEventListEntry *entry = new cEventListEntry(event, trigger,
+						start, interval, stop);
+  // If there are no events in the list yet.
+  if( m_tail == NULL ){
+    assert( m_head == NULL );
+    m_head = entry;
+    m_tail = entry;
+  }
+  else{
+    // Add to the end of the list
+    m_tail->SetNext( entry );
+    entry->SetPrev( m_tail );
+    m_tail = entry;
+  }
+  SyncEvent(entry);
+  ++m_num_events;
+}
+
+
+void cEventList::Delete(cEventListEntry *entry){
+  assert( entry != NULL );
+
+  if( entry->GetPrev() != NULL ){
+    entry->GetPrev()->SetNext( entry->GetNext() );
+  }
+  else{
+    assert( entry == m_head );
+    m_head = entry->GetNext();
+  }
+  if( entry->GetNext() != NULL ){
+    entry->GetNext()->SetPrev( entry->GetPrev() );
+  }
+  else{
+    assert( entry == m_tail );
+    m_tail = entry->GetPrev();
+  }
+
+  delete entry;
+}
+
+
+/*
+public manipulator used while rebuilding event list.
+XXX:  added by kaben.
+*/
+void cEventList::DeleteAll(void){
+  while( m_head != NULL ){
+    m_current = m_head;
+    m_head = m_head->GetNext();
+    delete m_head;
+  }
+
+  m_head = 0;
+  m_tail = 0;
+  m_current = 0;
+  m_num_events = 0;
+}
+
+
+void cEventList::Process(){
+  double t_val = 0; // trigger value
+
+  // Iterate through all entrys in event list
+  cEventListEntry * entry = m_head;
+  while( entry != NULL ){
+
+    cEventListEntry * next_entry = entry->GetNext();
+
+    // Check trigger condition
+
+    // IMMEDIATE Events always happen and are always deleted
+    if( entry->GetTrigger() == cEventTriggers::IMMEDIATE  ){
+      //cerr<<"IMMEDIATE EVENT "<<event->GetName()<<endl;
+      entry->GetEvent()->Process();
+      Delete(entry);
+    }else{
+
+      // Get the value of the appropriate trigger variable
+      t_val = m_triggers->GetTriggerValue(entry->GetTrigger());
+
+      if( t_val != DBL_MAX &&
+	  ( t_val >= entry->GetStart() ||
+	    entry->GetStart() == cEventTriggers::TRIGGER_BEGIN ) &&
+	  ( t_val <= entry->GetStop() ||
+	    entry->GetStop() == cEventTriggers::TRIGGER_END ) ){
+	
+	entry->GetEvent()->Process();
+	
+	if( entry == NULL ){ // It is possible for an event to kill itself
+	}else{	
+	  // Handle the interval thing
+	  if( entry->GetInterval() == cEventTriggers::TRIGGER_ALL ){
+	    // Do Nothing
+	  }else if( entry->GetInterval() == cEventTriggers::TRIGGER_ONCE ){
+	    // If it is a onetime thing, remove it...
+	    Delete(entry);
+	  }else{
+	    // There is an interal.. so add it
+	    entry->NextInterval();
+	  }
+
+	  // If the event can never happen now... excize it
+	  if( entry != NULL  &&  entry->GetStop() != cEventTriggers::TRIGGER_END ){
+	    if( entry->GetStart() > entry->GetStop() &&
+		entry->GetInterval() > 0 ){
+	      Delete(entry);
+	    }else if( entry->GetStart() < entry->GetStop() &&
+		      entry->GetInterval() < 0 ){
+	      Delete(entry);
+	    }
+	  }
+	
+	}
+	
+      } // End Non-IMMEDITAE events
+
+    }  // end condition to do event
+
+    entry = next_entry;
+  }
+}
+
+
+void cEventList::Sync(){
+  cEventListEntry *entry = m_head;
+  cEventListEntry *next_entry;
+  while( entry != NULL ){
+    next_entry = entry->GetNext();
+    assert( entry != NULL);
+    SyncEvent( entry );
+    entry = next_entry;
+  }
+}
+
+
+void cEventList::SyncEvent(cEventListEntry *entry){
+  // Ignore events that are immdeiate
+  if( entry->GetTrigger() == cEventTriggers::IMMEDIATE ){ return; }
+
+  double t_val = m_triggers->GetTriggerValue( entry->GetTrigger() );
+
+  // If t_val has past the end, remove (even if it is TRIGGER_ALL)
+  if( t_val > entry->GetStop() ){
+    Delete(entry);
+    return;
+  }
+
+  // If it is a trigger once and has passed, remove
+  if( t_val > entry->GetStart() && entry->GetInterval() == cEventTriggers::TRIGGER_ONCE ){
+    Delete(entry);
+    return;
+  }
+
+  // If for some reason t_val has been reset or soemthing, rewind
+  if( t_val + entry->GetInterval() <= entry->GetStart() ){
+    entry->Reset();
+  }
+
+  // Can't fast forward events that are Triger All
+  if( entry->GetInterval() == cEventTriggers::TRIGGER_ALL ){ return; }
+
+  // Keep adding interval to start until we are caught up
+  while( t_val > entry->GetStart() ){
+    entry->NextInterval();
+  }
+}
+
+
+void cEventList::PrintEventList( ostream & os ){
+  cEventListEntry * entry = m_head;
+  cEventListEntry * next_entry;
+  while( entry != NULL ){
+    next_entry = entry->GetNext();
+    PrintEvent( entry, os );
+    entry = next_entry;
+  }
+}
+
+/*
+XXX:  modified by kaben to stream-dump in parseable format.
+*/
+void cEventList::PrintEvent(cEventListEntry * entry, ostream & os){
+    assert( entry != NULL );
+    switch ( entry->GetTrigger() ){
+    case cEventTriggers::UPDATE:
+      //os<<"UPDATE ";
+      os<<"update ";
+      break;
+    case cEventTriggers::GENERATION:
+      //os<<"GENERATION ";
+      os<<"generation ";
+      break;
+    case cEventTriggers::IMMEDIATE:
+      //os<<"IMMEDIATE ";
+      os<<"immediate ";
+      break;
+    default:
+      //os<<"UNDEFINED ";
+      os<<"undefined ";
+    }
+    //os<<"[";
+    if (entry->GetTrigger() != cEventTriggers::IMMEDIATE ){
+      if( entry->GetStart() == cEventTriggers::TRIGGER_BEGIN ){
+        os<<"begin";
+      }else{
+        os<<entry->GetStart();
+      }
+      os<<":";
+      if( entry->GetInterval() == cEventTriggers::TRIGGER_ONCE ){
+        os<<"once";
+      }else if( entry->GetInterval() == cEventTriggers::TRIGGER_ALL ){
+        os<<"all";
+      }else{
+        os<<entry->GetInterval();
+      }
+      os<<":";
+      if( entry->GetStop() == cEventTriggers::TRIGGER_END ){
+        os<<"end";
+      }else{
+        os<<entry->GetStop();
+      }
+      os<<" ";
+    }
+    //os<<"] "<<entry->GetName()<<" "<<entry->GetArgs()<<endl;
+    os<<entry->GetName()<<" "<<entry->GetArgs()<<endl;
+}
+
+
+//// Parsing Event List File Format ////
+bool cEventList::AddEventFileFormat(const cString & in_line){
+  cString cur_line = in_line;
+
+  // Timing
+  cEventTriggers::eTriggerVariable trigger = cEventTriggers::UPDATE;
+  double start = cEventTriggers::TRIGGER_BEGIN;
+  double interval = cEventTriggers::TRIGGER_ONCE;
+  double stop = cEventTriggers::TRIGGER_END;
+
+  cString name;
+  cString arg_list;
+
+  cString tmp;
+
+  cString cur_word = cur_line.PopWord();
+
+  // Get the trigger variable if there
+  if( cur_word == "i"  ||
+      cur_word == "immediate" ){
+    trigger = cEventTriggers::IMMEDIATE;
+    name = cur_line.PopWord();
+    return AddEvent(name, cur_line); // If event is IMMEDIATE shortcut
+  }else if( cur_word == "u"  ||
+	    cur_word == "update" ){
+    trigger = cEventTriggers::UPDATE;
+    cur_word = cur_line.PopWord();
+  }else if( cur_word == "g"  ||
+	    cur_word == "generation" ){
+    trigger = cEventTriggers::GENERATION;
+    cur_word = cur_line.PopWord();
+  }else{
+    // If Trigger is skipped so assume IMMEDIATE
+    trigger = cEventTriggers::IMMEDIATE;
+  }
+
+  // Do we now have timing specified?
+  // Parse the Timing
+  cString timing_str = cur_word;
+
+  // Get the start:interval:stop
+  tmp = timing_str.Pop(':');
+
+  // If first value is valid, we are getting a timing.
+  if( tmp.IsNumber() || tmp == "begin" ){
+
+    // First number is start
+    if( tmp == "begin" ){
+      start = cEventTriggers::TRIGGER_BEGIN;
+    }else{
+      start = tmp.AsDouble();
+    }
+
+    // If no other words... is "start" syntax
+    if( timing_str.GetSize() == 0 ){
+      interval = cEventTriggers::TRIGGER_ONCE;
+      stop     = cEventTriggers::TRIGGER_END;
+    }else{
+      // Second word is interval
+      tmp = timing_str.Pop(':');
+      if( tmp == "all" ){
+	  interval = cEventTriggers::TRIGGER_ALL;
+      }else if( tmp == "once" ){
+	interval = cEventTriggers::TRIGGER_ONCE;
+      }else{
+	interval = tmp.AsDouble();
+      }
+      // If no other words... is "start:interval" syntax
+      if( timing_str.GetSize() == 0 ){
+	stop     = cEventTriggers::TRIGGER_END;
+      }else{
+	// We have "start:interval:stop" syntax
+	tmp = timing_str;
+	if( tmp == "end" ){
+	  stop = cEventTriggers::TRIGGER_END;
+	}else{
+	  stop = tmp.AsDouble();
+	}
+      }
+    }
+    cur_word = cur_line.PopWord(); // timing provided, so get next word
+
+  }else{ // We don't have timing, so assume IMMEDIATE
+    trigger = cEventTriggers::IMMEDIATE;
+    start = cEventTriggers::TRIGGER_BEGIN;
+    interval = cEventTriggers::TRIGGER_ONCE;
+    stop = cEventTriggers::TRIGGER_END;
+  }
+
+  // Get the rest of the info
+  name = cur_word;
+  arg_list = cur_line;
+
+  return AddEvent( trigger, start, interval, stop, name, arg_list );
+}
Index: avida/current/source/event/event_list.hh
diff -u /dev/null avida/current/source/event/event_list.hh:1.9
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/event/event_list.hh	Tue Nov 25 09:37:55 2003
@@ -0,0 +1,147 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+/* event_list.hh *************************************************************
+ Builds a queue for holding and processing events
+
+ charles at krl.caltech.edu & travc at ugcs.caltech.edu
+
+******************************************************************************/
+
+#ifndef EVENT_LIST_HH
+#define EVENT_LIST_HH
+
+#ifndef EVENT_LIST_ENTRY_HH
+#include "event_list_entry.hh"
+#endif
+#ifndef EVENT_LIST_ITERATOR_HH
+#include "event_list_iterator.hh"
+#endif
+#ifndef EVENT_TRIGGERS_HH
+#include "event_triggers.hh"
+#endif
+
+/**
+ * This is the fundamental class for event management. It holds a list of all
+ * events, and provides methods to add new events and to process existing
+ * events.
+ **/
+
+class cEvent;
+class cEventFactoryManager;
+class cEventListEntry; // access
+class cEventListIterator; // access
+class cEventTriggers; // access
+class cString;
+
+class cEventList {
+friend class cEventListIterator;
+public:
+  cEventListIterator begin() { return cEventListIterator(m_head); }
+  const cEventListIterator end() const { return cEventListIterator(0); }
+protected:
+  cEventFactoryManager *m_factory_manager;
+  cEventTriggers *m_triggers;
+
+  cEventListEntry *m_head;
+  cEventListEntry *m_tail;
+  cEventListEntry *m_current;
+  int m_num_events;
+
+  void InsertEvent(cEvent *event, cEventTriggers::eTriggerVariable trigger,
+		   double start, double interval, double stop);
+  void Delete( cEventListEntry *entry );
+  void Delete(){ Delete( m_current); }
+
+  double GetTriggerValue( cEventTriggers::eTriggerVariable trigger);
+
+private:
+  // not implemented, prevents inadvertent wrong instantiation
+  cEventList();
+  cEventList( const cEventList& );
+  cEventList& operator=( const cEventList& );
+
+public:
+  // creators
+  /**
+   * The cEventList assumes ownership of both objects it is handed, and
+   * destroys them when it is done.
+   *
+   * @param factory_manager A pointer to an event factory manager,
+   * @ref cEventFactoryManager. The event factory manager is responsible
+   * for finding the appropriate event factory to construct a given event.
+   *
+   * @param triggers A trigger object. The event list needs a trigger object
+   * to determine what events to call when.
+   **/
+  cEventList( cEventFactoryManager *factory_manager, cEventTriggers *triggers );
+  ~cEventList();
+
+  // manipulators
+  /**
+   * Adds an event with given name and argument list. The event will be of
+   * type immediate, i.e. it is processed only once, and then deleted.
+   *
+   * @param name The name of the event.
+   * @param args The argument list.
+   **/
+  bool AddEvent( const cString & name, const cString & args ){
+    return AddEvent( cEventTriggers::IMMEDIATE, cEventTriggers::TRIGGER_BEGIN, cEventTriggers::TRIGGER_ONCE, cEventTriggers::TRIGGER_END, name, args); }
+
+
+  /**
+   * Adds an event with specified trigger type.
+   *
+   * @param trigger The type of the trigger.
+   * @param start The start value of the trigger variable.
+   * @param interval The length of the interval between one processing
+   * and the next.
+   * @param stop The value of the trigger variable at which the event should
+   * be deleted.
+   * @param name The name of the even.
+   * @param args The argument list.
+   **/
+  bool AddEvent( cEventTriggers::eTriggerVariable trigger,
+		 double start, double interval, double stop,
+		 const cString &name, const cString &args );
+
+  /**
+   * This function adds an event that is given in the event list file format.
+   * In other words, it can be used to parse one line from an event list file,
+   * and construct the appropriate event.
+   **/
+  bool AddEventFileFormat(const cString & line);
+
+  /**
+   * Delete all events in list; leave list ready for insertion of new
+   * events.
+   **/
+  void DeleteAll(void);
+
+  /**
+   * Go through list executing appropriate events.
+   **/
+  void Process();
+
+  /**
+   * Get all events caught up.
+   **/
+  void Sync();
+
+  /**
+   * Get this event caught up.
+   **/
+  void SyncEvent(cEventListEntry *event);
+
+  void PrintEventList(std::ostream & os = std::cout);
+
+  // kaben changed this member function to static for easy access by
+  // cEventListIterator.
+  static void PrintEvent(cEventListEntry * event, std::ostream & os = std::cout);
+};
+
+#endif
Index: avida/current/source/event/population_event_factory.cc
diff -u /dev/null avida/current/source/event/population_event_factory.cc:1.11
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/event/population_event_factory.cc	Tue Nov 25 09:37:55 2003
@@ -0,0 +1,144 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef POPULATION_EVENT_FACTORY_HH
+#include "population_event_factory.hh"
+#endif
+
+#ifndef ANALYZE_UTIL_HH
+#include "analyze_util.hh"
+#endif
+#ifndef AVIDA_HH
+#include "avida.hh"
+#endif
+#ifndef AVIDA_DRIVER_BASE_HH
+#include "avida_driver_base.hh"
+#endif
+#ifndef CONFIG_HH
+#include "config.hh"
+#endif
+#ifndef ENVIRONMENT_HH
+#include "environment.hh"
+#endif
+#ifndef EVENT_HH
+#include "event.hh"
+#endif
+#ifndef GENEBANK_HH
+#include "genebank.hh"
+#endif
+#ifndef GENOTYPE_HH
+#include "genotype.hh"
+#endif
+#ifndef INJECT_GENEBANK_HH
+#include "inject_genebank.hh"
+#endif
+#ifndef INJECT_GENOTYPE_HH
+#include "inject_genotype.hh"
+#endif
+#ifndef INST_UTIL_HH
+#include "inst_util.hh"
+#endif
+#ifndef LANDSCAPE_HH
+#include "landscape.hh"
+#endif
+#ifndef LINEAGE_CONTROL_HH
+#include "lineage_control.hh"
+#endif
+#ifndef ORGANISM_HH
+#include "organism.hh"
+#endif
+#ifndef PHENOTYPE_HH
+#include "phenotype.hh"
+#endif
+#ifndef POPULATION_HH
+#include "population.hh"
+#endif
+#ifndef POPULATION_CELL_HH
+#include "population_cell.hh"
+#endif
+#ifndef POPULATION_EVENT_HH
+#include "population_event.hh"
+#endif
+#ifndef RESOURCE_HH
+#include "resource.hh"
+#endif
+#ifndef STATS_HH
+#include "stats.hh"
+#endif
+#ifndef STRING_UTIL_HH
+#include "string_util.hh"
+#endif
+#ifndef TEST_CPU_HH
+#include "test_cpu.hh"
+#endif
+#ifndef TEST_UTIL_HH
+#include "test_util.hh"
+#endif
+#ifndef TOOLS_HH
+#include "tools.hh"
+#endif
+
+#include <ctype.h>           // for isdigit
+
+using namespace std;
+
+
+
+/////////////////
+//  events derived from cPopulationEvent (autogenerated code)
+/////////////////
+
+// The Process() functions
+using namespace std;
+#include "cPopulation_process_auto.ci"
+
+// EventNameToEnum()
+#include "cPopulation_name2enum_auto.ci"
+
+
+/////////////////
+// cPopulationEventFactory
+/////////////////
+
+cPopulationEventFactory::cPopulationEventFactory( cPopulation *pop ) 
+  : m_population( pop )
+{
+}
+
+cPopulationEventFactory::~cPopulationEventFactory()
+{
+}
+
+//******* construction of events **********//
+cEvent *
+cPopulationEventFactory::ConstructEvent( int event_enum,
+				    const cString & arg_list )
+{
+  cPopulationEvent *event = NULL;
+
+  switch (event_enum){
+
+#include "cPopulation_construct_event_auto.ci"
+
+    default:
+      event = NULL;
+      break;
+  }
+
+  if( event != NULL ){
+    // Have to setup the base class variables
+    event->SetFactoryId( GetFactoryId() );
+
+    assert( m_population != NULL );
+    event->SetPopulation( m_population );
+  }
+  return event;
+}
+
+
+
+
Index: avida/current/source/event/population_event_factory.hh
diff -u /dev/null avida/current/source/event/population_event_factory.hh:1.7
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/event/population_event_factory.hh	Tue Nov 25 09:37:55 2003
@@ -0,0 +1,33 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef POPULATION_EVENT_FACTORY_HH
+#define POPULATION_EVENT_FACTORY_HH
+
+#ifndef EVENT_FACTORY_HH
+#include "event_factory.hh"
+#endif
+
+class cEvent;
+class cPopulation;
+class cString;
+
+class cPopulationEventFactory : public cEventFactory {
+private:
+  cPopulation *m_population;
+public:
+  // event enums
+#include "cPopulation_enums_auto.ci"
+
+  cPopulationEventFactory( cPopulation *pop );
+  ~cPopulationEventFactory();
+
+  int EventNameToEnum(const cString & name) const;
+  cEvent * ConstructEvent(int event_enum, const cString & args );
+};
+
+#endif
Index: avida/current/source/event/Makefile.am
diff -u avida/current/source/event/Makefile.am:1.15 avida/current/source/event/Makefile.am:1.16
--- avida/current/source/event/Makefile.am:1.15	Thu Oct 16 10:38:45 2003
+++ avida/current/source/event/Makefile.am	Tue Nov 25 09:37:55 2003
@@ -1,4 +1,15 @@
 
+SOURCE_DIR = $(srcdir)/..
+SOURCE_INC = -I$(SOURCE_DIR)
+EVENT_DIR = $(SOURCE_DIR)/event
+EVENT_INC = -I$(EVENT_DIR)
+CPU_DIR = $(SOURCE_DIR)/cpu
+CPU_INC = -I$(CPU_DIR)
+TOOLS_DIR = $(SOURCE_DIR)/tools
+TOOLS_INC = -I$(TOOLS_DIR)
+MAIN_DIR = $(SOURCE_DIR)/main
+MAIN_INC = -I$(MAIN_DIR)
+INCLUDES = $(EVENT_INC) $(CPU_INC) $(TOOLS_INC) $(MAIN_INC) $(SOURCE_INC)
 
 ## This is a somewhat ugly hack to build the autogenerated code.
 ## We pretend that the autogenerated code is actually a program, then
@@ -26,12 +37,15 @@
 ##
 
 ## now come the actual sources for libevent.a
-libevent_a_SOURCES = event.cc event.hh			\
-		event_factory.cc event_factory.hh   	\
-		event_factory_manager.cc event_factory_manager.hh        \
-		event_list.cc event_list.hh              \
-		population_event_factory.cc		 \
-		population_event_factory.hh
+libevent_a_SOURCES = event.cc event.hh \
+  event_factory.cc event_factory.hh \
+  event_factory_manager.cc event_factory_manager.hh \
+  event_list.cc event_list.hh \
+  event_list_entry.cc event_list_entry.hh \
+  event_list_iterator.cc event_list_iterator.hh \
+  event_triggers.cc event_triggers.hh \
+  population_event.cc population_event.hh \
+  population_event_factory.cc population_event_factory.hh
 
 noinst_LIBRARIES = libevent.a
 
Index: avida/current/source/main/analyze.cc
diff -u /dev/null avida/current/source/main/analyze.cc:1.86
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/analyze.cc	Tue Nov 25 09:37:56 2003
@@ -0,0 +1,4355 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef ANALYZE_HH
+#include "analyze.hh"
+#endif
+
+#ifndef ANALYZE_COMMAND_HH
+#include "analyze_command.hh"
+#endif
+#ifndef ANALYZE_COMMAND_DEF_HH
+#include "analyze_command_def.hh"
+#endif
+#ifndef ANALYZE_COMMAND_DEF_BASE_HH
+#include "analyze_command_def_base.hh"
+#endif
+#ifndef ANALYZE_FLOW_COMMAND_HH
+#include "analyze_flow_command.hh"
+#endif
+#ifndef ANALYZE_FLOW_COMMAND_DEF_HH
+#include "analyze_flow_command_def.hh"
+#endif
+#ifndef ANALYZE_FUNCTION_HH
+#include "analyze_function.hh"
+#endif
+#ifndef ANALYZE_GENOTYPE_HH
+#include "analyze_genotype.hh"
+#endif
+#ifndef CONFIG_HH
+#include "config.hh"
+#endif
+#ifndef DATA_FILE_HH
+#include "data_file.hh"
+#endif
+#ifndef ENVIRONMENT_HH
+#include "environment.hh"
+#endif
+#ifndef FITNESS_MATRIX_HH
+#include "fitness_matrix.hh"
+#endif
+#ifndef GENOME_UTIL_HH
+#include "genome_util.hh"
+#endif
+#ifndef HARDWARE_BASE_HH
+#include "hardware_base.hh"
+#endif
+#ifndef HARDWARE_UTIL_HH
+#include "hardware_util.hh"
+#endif
+#ifndef HELP_MANAGER_HH
+#include "help_manager.hh"
+#endif
+#ifndef INIT_FILE_HH
+#include "init_file.hh"
+#endif
+#ifndef INST_SET_HH
+#include "inst_set.hh"
+#endif
+#ifndef INST_UTIL_HH
+#include "inst_util.hh"
+#endif
+#ifndef LANDSCAPE_HH
+#include "landscape.hh"
+#endif
+#ifndef PHENOTYPE_HH
+#include "phenotype.hh"
+#endif
+#ifndef SPECIES_HH
+#include "species.hh"
+#endif
+#ifndef TARGDATAENTRY_HH
+#include "tArgDataEntry.hh"
+#endif
+#ifndef TASK_ENTRY_HH
+#include "task_entry.hh"
+#endif
+#ifndef TDATAENTRY_HH
+#include "tDataEntry.hh"
+#endif
+#ifndef TDATAENTRYCOMMAND_HH
+#include "tDataEntryCommand.hh"
+#endif
+#ifndef TEST_CPU_HH
+#include "test_cpu.hh"
+#endif
+#ifndef TEST_UTIL_HH
+#include "test_util.hh"
+#endif
+#ifdef WIN32
+# ifndef WIN32_MKDIR_HACK_HH
+#  include "win32_mkdir_hack.hh"
+# endif
+#endif
+
+#include <sys/stat.h>
+
+using namespace std;
+
+
+
+
+//////////////
+//  cAnalyze
+//////////////
+
+cAnalyze::cAnalyze(cString filename)
+  : cur_batch(0)
+  , verbose(false)
+  , interactive_depth(0)
+  , inst_set(cHardwareUtil::DefaultInstSet(cConfig::GetInstFilename()))
+{
+  random.ResetSeed(cConfig::GetRandSeed());
+
+  for (int i = 0; i < MAX_BATCHES; i++) {
+    batch[i].Name().Set("Batch%d", i);
+  }
+
+  cInitFile analyze_file(filename);
+  analyze_file.Load();
+  analyze_file.Compress();
+  analyze_file.Close();
+
+  LoadCommandList(analyze_file, command_list);
+  ProcessCommands(command_list);
+}
+
+cAnalyze::~cAnalyze()
+{
+  data_file_manager.FlushAll();
+  while (genotype_data_list.GetSize()) delete genotype_data_list.Pop();
+  while (command_list.GetSize()) delete command_list.Pop();
+  while (function_list.GetSize()) delete function_list.Pop();
+}
+
+
+//////////////// Loading methods...
+
+void cAnalyze::LoadOrganism(cString cur_string)
+{
+  // LOAD_ORGANISM command...
+
+  cString filename = cur_string.PopWord();
+
+  cout << "Loading: " << filename << endl;
+
+  // Setup the genome...
+  cGenome genome( cInstUtil::LoadGenome(filename, inst_set) );
+
+  // Construct the new genotype..
+  cAnalyzeGenotype * genotype = new cAnalyzeGenotype(genome, inst_set);
+
+  // Determine the organism's original name -- strip off directory...
+  while (filename.Find('/') != -1) filename.Pop('/');
+  while (filename.Find('\\') != -1) filename.Pop('\\');
+  filename.Replace(".gen", "");  // Remove the .gen from the filename.
+  genotype->SetName(filename);
+
+  // And save it in the current batch.
+  batch[cur_batch].List().PushRear(genotype);
+
+  // Adjust the flags on this batch
+  batch[cur_batch].SetLineage(false);
+  batch[cur_batch].SetAligned(false);
+}
+
+void cAnalyze::LoadBasicDump(cString cur_string)
+{
+  // LOAD_BASE_DUMP
+
+  cString filename = cur_string.PopWord();
+
+  cout << "Loading: " << filename << endl;
+
+  cInitFile input_file(filename);
+  if (!input_file.IsOpen()) {
+    cerr << "Error: Cannot load file: \"" << filename << "\"." << endl;
+    exit(1);
+  }
+  input_file.Load();
+  input_file.Compress();
+  input_file.Close();
+
+  // Setup the genome...
+
+  for (int line_id = 0; line_id < input_file.GetNumLines(); line_id++) {
+    cString cur_line = input_file.GetLine(line_id);
+
+    // Setup the genotype for this line...
+    cAnalyzeGenotype * genotype =
+      new cAnalyzeGenotype(cur_line.PopWord(), inst_set);
+    int num_cpus = cur_line.PopWord().AsInt();
+    int id_num = cur_line.PopWord().AsInt();
+    cString name = cStringUtil::Stringf("org-%d", id_num);
+
+    genotype->SetNumCPUs(num_cpus);
+    genotype->SetID(id_num);
+    genotype->SetName(name);
+
+    // Add this genotype to the proper batch.
+    batch[cur_batch].List().PushRear(genotype);
+  }
+
+  // Adjust the flags on this batch
+  batch[cur_batch].SetLineage(false);
+  batch[cur_batch].SetAligned(false);
+}
+
+void cAnalyze::LoadDetailDump(cString cur_string)
+{
+  // LOAD_DETAIL_DUMP
+
+  cString filename = cur_string.PopWord();
+
+  cout << "Loading: " << filename << endl;
+
+  cInitFile input_file(filename);
+  if (!input_file.IsOpen()) {
+    cerr << "Error: Cannot load file: \"" << filename << "\"." << endl;
+    exit(1);
+  }
+  input_file.Load();
+  input_file.Compress();
+  input_file.Close();
+
+  // Setup the genome...
+
+  for (int line_id = 0; line_id < input_file.GetNumLines(); line_id++) {
+    cString cur_line = input_file.GetLine(line_id);
+
+    // Setup the genotype for this line...
+
+    int id_num      = cur_line.PopWord().AsInt();
+    int parent_id   = cur_line.PopWord().AsInt();
+    int parent_dist = cur_line.PopWord().AsInt();
+    int num_cpus    = cur_line.PopWord().AsInt();
+    int total_cpus  = cur_line.PopWord().AsInt();
+    int length      = cur_line.PopWord().AsInt();
+    double merit    = cur_line.PopWord().AsDouble();
+    int gest_time   = cur_line.PopWord().AsInt();
+    double fitness  = cur_line.PopWord().AsDouble();
+    int update_born = cur_line.PopWord().AsInt();
+    int update_dead = cur_line.PopWord().AsInt();
+    int depth       = cur_line.PopWord().AsInt();
+    cString name = cStringUtil::Stringf("org-%d", id_num);
+
+    cAnalyzeGenotype * genotype =
+      new cAnalyzeGenotype(cur_line.PopWord(), inst_set);
+
+    genotype->SetID(id_num);
+    genotype->SetParentID(parent_id);
+    genotype->SetParentDist(parent_dist);
+    genotype->SetNumCPUs(num_cpus);
+    genotype->SetTotalCPUs(total_cpus);
+    genotype->SetLength(length);
+    genotype->SetMerit(merit);
+    genotype->SetGestTime(gest_time);
+    genotype->SetFitness(fitness);
+    genotype->SetUpdateBorn(update_born);
+    genotype->SetUpdateDead(update_dead);
+    genotype->SetDepth(depth);
+    genotype->SetName(name);
+
+    // Add this genotype to the proper batch.
+    batch[cur_batch].List().PushRear(genotype);
+  }
+
+  // Adjust the flags on this batch
+  batch[cur_batch].SetLineage(false);
+  batch[cur_batch].SetAligned(false);
+}
+
+void cAnalyze::LoadSequence(cString cur_string)
+{
+  // LOAD_SEQUENCE
+
+  static int sequence_count = 1;
+  cString sequence = cur_string.PopWord();
+  cString seq_name = cur_string.PopWord();
+
+  cout << "Loading: " << sequence << endl;
+
+  // Setup the genotype...
+  cAnalyzeGenotype * genotype = new cAnalyzeGenotype(sequence, inst_set);
+
+  genotype->SetNumCPUs(1);      // Initialize to a single organism.
+  if (seq_name == "") {
+    seq_name = cStringUtil::Stringf("org-S%d", sequence_count);
+  }
+  genotype->SetName(seq_name);
+  sequence_count++;
+
+  // Add this genotype to the proper batch.
+  batch[cur_batch].List().PushRear(genotype);
+
+  // Adjust the flags on this batch
+  batch[cur_batch].SetLineage(false);
+  batch[cur_batch].SetAligned(false);
+}
+
+void cAnalyze::LoadDominant(cString cur_string)
+{
+  (void) cur_string;
+  cerr << "Warning: \"LOAD_DOMINANT\" not implmented yet!"<<endl;
+}
+
+void cAnalyze::LoadFile(cString cur_string)
+{
+  // LOAD
+
+  cString filename = cur_string.PopWord();
+
+  cout << "Loading: " << filename << endl;
+
+  cInitFile input_file(filename);
+  if (!input_file.IsOpen()) {
+    cerr << "Error: Cannot load file: \"" << filename << "\"." << endl;
+    exit(1);
+  }
+  input_file.Load();
+  input_file.ReadHeader();
+  input_file.Compress();
+  input_file.Close();
+
+  const cString filetype = input_file.GetFiletype();
+  if (filetype != "population_data") {
+    cerr << "Error: Cannot load files of type \"" << filetype << "\"." << endl;
+    exit(1);
+  }
+
+  if (verbose == true) {
+    cout << "Loading file of type: " << filetype << endl;
+  }
+
+  
+  // Construct a linked list of data types that can be loaded...
+  tList< tDataEntryCommand<cAnalyzeGenotype> > output_list;
+  tListIterator< tDataEntryCommand<cAnalyzeGenotype> > output_it(output_list);
+  LoadGenotypeDataList(input_file.GetFormat(), output_list);
+
+
+  // Setup the genome...
+  cGenome default_genome(1);
+  int load_count = 0;
+
+  for (int line_id = 0; line_id < input_file.GetNumLines(); line_id++) {
+    cString cur_line = input_file.GetLine(line_id);
+
+    cAnalyzeGenotype * genotype =
+      new cAnalyzeGenotype(default_genome, inst_set);
+
+    output_it.Reset();
+    tDataEntryCommand<cAnalyzeGenotype> * data_command = NULL;
+    while ((data_command = output_it.Next()) != NULL) {
+      data_command->SetTarget(genotype);
+//        genotype->SetSpecialArgs(data_command->GetArgs());
+      data_command->SetValue(cur_line.PopWord());
+    }
+
+    // Make sure this genotype has a name...
+    if (genotype->GetName() == "") {
+      cString name = cStringUtil::Stringf("org-D%d", load_count++);
+      genotype->SetName(name);
+    }
+
+    // Add this genotype to the proper batch.
+    batch[cur_batch].List().PushRear(genotype);
+  }
+
+  // Adjust the flags on this batch
+  batch[cur_batch].SetLineage(false);
+  batch[cur_batch].SetAligned(false);
+}
+
+
+//////////////// Reduction....
+
+void cAnalyze::FindGenotype(cString cur_string)
+{
+  // If no arguments are passed in, just find max num_cpus.
+  if (cur_string.GetSize() == 0) cur_string = "num_cpus";
+
+  if (verbose == true) {
+    cout << "Reducing batch " << cur_batch << " to genotypes: ";
+  }
+
+  tList<cAnalyzeGenotype> & gen_list = batch[cur_batch].List();
+  tList<cAnalyzeGenotype> found_list;
+  while (cur_string.CountNumWords() > 0) {
+    cString gen_desc(cur_string.PopWord());
+    if (verbose) cout << gen_desc << " ";
+
+    // Determine by lin_type which genotype were are tracking...
+    cAnalyzeGenotype * found_gen = PopGenotype(gen_desc, cur_batch);
+
+    if (found_gen == NULL) {
+      cerr << "  Warning: genotype not found!" << endl;
+      continue;
+    }
+
+    // Save this genotype...
+    found_list.Push(found_gen);
+  }
+  cout << endl;
+
+  // Delete all genotypes other than the ones found!
+  while (gen_list.GetSize() > 0) delete gen_list.Pop();
+
+  // And fill it back in with the good stuff.
+  while (found_list.GetSize() > 0) gen_list.Push(found_list.Pop());
+
+  // Adjust the flags on this batch
+  batch[cur_batch].SetLineage(false);
+  batch[cur_batch].SetAligned(false);
+}
+
+void cAnalyze::FindLineage(cString cur_string)
+{
+  cString lin_type = "num_cpus";
+  if (cur_string.CountNumWords() > 0) lin_type = cur_string.PopWord();
+
+  if (verbose == true) {
+    cout << "Reducing batch " << cur_batch
+	 << " to " << lin_type << " lineage " << endl;
+  } else cout << "Performing lineage scan..." << endl;
+
+
+  // Determine by lin_type which genotype we are tracking...
+  cAnalyzeGenotype * found_gen = PopGenotype(lin_type, cur_batch);
+
+  if (found_gen == NULL) {
+    cerr << "  Warning: Genotype " << lin_type
+	 << " not found.  Lineage scan aborted." << endl;
+    return;
+  }
+
+  // Otherwise, trace back through the id numbers to mark all of those
+  // in the ancestral lineage...
+
+  // Construct a list of genotypes found...
+
+  tList<cAnalyzeGenotype> found_list;
+  found_list.Push(found_gen);
+  int next_id = found_gen->GetParentID();
+  bool found = true;
+  while (found == true) {
+    found = false;
+
+    tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+    while ((found_gen = batch_it.Next()) != NULL) {
+      if (found_gen->GetID() == next_id) {
+	batch_it.Remove();
+	found_list.Push(found_gen);
+	next_id = found_gen->GetParentID();
+	found = true;
+	break;
+      }
+    }
+  }
+
+  // We now have all of the genotypes in this lineage, delete everything
+  // else.
+
+  const int total_removed = batch[cur_batch].List().GetSize();
+  while (batch[cur_batch].List().GetSize() > 0) {
+    delete batch[cur_batch].List().Pop();
+  }
+
+  // And fill it back in with the good stuff.
+  int total_kept = found_list.GetSize();
+  while (found_list.GetSize() > 0) {
+    batch[cur_batch].List().PushRear(found_list.Pop());
+  }
+
+  if (verbose == true) {
+    cout << "  Lineage has " << total_kept << " genotypes; "
+	 << total_removed << " were removed." << endl;
+  }
+
+  // Adjust the flags on this batch
+  batch[cur_batch].SetLineage(true);
+  batch[cur_batch].SetAligned(false);
+}
+
+void cAnalyze::FindClade(cString cur_string)
+{
+  if (cur_string.GetSize() == 0) {
+    cerr << "  Warning: No clade specified for FIND_CLADE.  Aborting." << endl;
+    return;
+  }
+
+  cString clade_type( cur_string.PopWord() );
+
+  if (verbose == true) {
+    cout << "Reducing batch " << cur_batch
+	 << " to clade " << clade_type << "." << endl;
+  } else cout << "Performing clade scan..." << endl;
+
+
+  // Determine by clade_type which genotype we are tracking...
+  cAnalyzeGenotype * found_gen = PopGenotype(clade_type, cur_batch);
+
+  if (found_gen == NULL) {
+    cerr << "  Warning: Ancestral genotype " << clade_type
+	 << " not found.  Clade scan aborted." << endl;
+    return;
+  }
+
+  // Do this the brute force way... scan for one step at a time.
+
+  // Construct a list of genotypes found...
+
+  tList<cAnalyzeGenotype> found_list; // Found and finished.
+  tList<cAnalyzeGenotype> scan_list;  // Found, but need to scan for children.
+  scan_list.Push(found_gen);
+
+  // Keep going as long as there is something in the scan list...
+  while (scan_list.GetSize() > 0) {
+    // Move the next genotype from the scan list to the found_list.
+    found_gen = scan_list.Pop();
+    int parent_id = found_gen->GetID();
+    found_list.Push(found_gen);
+
+    // Seach for all of the children of this genotype...
+    tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+    while ((found_gen = batch_it.Next()) != NULL) {
+      // If we found a child, place it into the scan list.
+      if (found_gen->GetParentID() == parent_id) {
+	batch_it.Remove();
+	scan_list.Push(found_gen);
+      }
+    }
+  }
+
+  // We now have all of the genotypes in this clade, delete everything else.
+
+  const int total_removed = batch[cur_batch].List().GetSize();
+  while (batch[cur_batch].List().GetSize() > 0) {
+    delete batch[cur_batch].List().Pop();
+  }
+
+  // And fill it back in with the good stuff.
+  int total_kept = found_list.GetSize();
+  while (found_list.GetSize() > 0) {
+    batch[cur_batch].List().PushRear(found_list.Pop());
+  }
+
+  if (verbose == true) {
+    cout << "  Clade has " << total_kept << " genotypes; "
+	 << total_removed << " were removed." << endl;
+  }
+
+  // Adjust the flags on this batch
+  batch[cur_batch].SetLineage(false);
+  batch[cur_batch].SetAligned(false);
+}
+
+void cAnalyze::SampleOrganisms(cString cur_string)
+{
+  double fraction = cur_string.PopWord().AsDouble();
+  int init_genotypes = batch[cur_batch].List().GetSize();
+
+  if (verbose == true) {
+    cout << "Sampling " << fraction << " organisms from batch "
+	 << cur_batch << "." << endl;
+  }
+  else cout << "Sampling Organisms..." << endl;
+
+  int old_total = 0;
+  int new_total = 0;
+
+  cAnalyzeGenotype * genotype = NULL;
+  tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+  while ((genotype = batch_it.Next()) != NULL) {
+    const int old_count = genotype->GetNumCPUs();
+    const int new_count = random.GetRandBinomial(old_count, fraction);
+    old_total += old_count;
+    new_total += new_count;
+
+    if (new_count == 0) {
+      batch_it.Remove();
+      delete genotype;
+    } else {
+      genotype->SetNumCPUs(new_count);
+    }
+  }
+
+  int num_genotypes = batch[cur_batch].List().GetSize();
+  if (verbose) {
+    cout << "  Removed " << old_total - new_total
+	 << " organisms (" << init_genotypes - num_genotypes
+	 << " genotypes); " << new_total
+	 << " orgs (" << num_genotypes << " gens) remaining."
+	 << endl;
+  }
+
+  // Adjust the flags on this batch
+  batch[cur_batch].SetLineage(false);
+  batch[cur_batch].SetAligned(false);
+}
+
+void cAnalyze::SampleGenotypes(cString cur_string)
+{
+  double fraction = cur_string.PopWord().AsDouble();
+  int init_genotypes = batch[cur_batch].List().GetSize();
+
+  if (verbose == true) {
+    cout << "Sampling " << fraction << " genotypes from batch "
+	 << cur_batch << "." << endl;
+  }
+  else cout << "Sampling Genotypes..." << endl;
+
+  double frac_remove = 1.0 - fraction;
+
+  cAnalyzeGenotype * genotype = NULL;
+
+  tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+  while ((genotype = batch_it.Next()) != NULL) {
+    if (random.P(frac_remove)) {
+      batch_it.Remove();
+      delete genotype;
+    }
+  }
+
+  int num_genotypes = batch[cur_batch].List().GetSize();
+  if (verbose == true) {
+    cout << "  Removed " << init_genotypes - num_genotypes
+	 << " genotypes; " << num_genotypes << " remaining."
+	 << endl;
+  }
+
+  // Adjust the flags on this batch
+  batch[cur_batch].SetLineage(false);
+  batch[cur_batch].SetAligned(false);
+}
+
+void cAnalyze::KeepTopGenotypes(cString cur_string)
+{
+  const int num_kept = cur_string.PopWord().AsInt();
+  const int num_genotypes = batch[cur_batch].List().GetSize();
+  const int num_removed = num_genotypes - num_kept;
+
+  for (int i = 0; i < num_removed; i++) {
+    delete batch[cur_batch].List().PopRear();
+  }
+
+  // Adjust the flags on this batch
+  // batch[cur_batch].SetLineage(false); // Should not destroy a lineage...
+  batch[cur_batch].SetAligned(false);
+}
+
+
+
+//////////////// Output Commands...
+
+void cAnalyze::CommandPrint(cString cur_string)
+{
+  if (verbose == true) cout << "Printing batch " << cur_batch << endl;
+  else cout << "Printing organisms..." << endl;
+
+  cString directory = PopDirectory(cur_string, "genebank/");
+
+  tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+  cAnalyzeGenotype * genotype = NULL;
+  while ((genotype = batch_it.Next()) != NULL) {
+    cString filename(directory);
+    filename += genotype->GetName();
+    filename += ".gen";
+    cTestUtil::PrintGenome(genotype->GetGenome(), filename);
+    if (verbose) cout << "Printing: " << filename << endl;
+  }
+}
+
+void cAnalyze::CommandTrace(cString cur_string)
+{
+  if (verbose == true) cout << "Tracing batch " << cur_batch << endl;
+  else cout << "Tracing organisms..." << endl;
+
+  cString directory = PopDirectory(cur_string, "genebank/");
+
+  tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+  cAnalyzeGenotype * genotype = NULL;
+  while ((genotype = batch_it.Next()) != NULL) {
+    cString filename(directory);
+    filename += genotype->GetName();
+    filename += ".trace";
+    cTestCPU::TraceGenome(genotype->GetGenome(), filename);
+    if (verbose) cout << "  Tracing: " << filename << endl;
+  }
+}
+
+void cAnalyze::CommandPrintTasks(cString cur_string)
+{
+  if (verbose == true) cout << "Printing tasks in batch " << cur_batch << endl;
+  else cout << "Printing tasks..." << endl;
+
+  // Load in the variables...
+  cString filename("tasks.dat");
+  if (cur_string.GetSize() != 0) filename = cur_string.PopWord();
+
+  ofstream & fp = data_file_manager.GetOFStream(filename);
+
+  // Loop through all of the genotypes in this batch...
+  tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+  cAnalyzeGenotype * genotype = NULL;
+  while ((genotype = batch_it.Next()) != NULL) {
+    fp << genotype->GetID() << " ";
+    genotype->PrintTasks(fp);
+    fp << endl;
+  }
+}
+
+void cAnalyze::CommandDetail(cString cur_string)
+{
+  if (verbose == true) cout << "Detailing batch " << cur_batch << endl;
+  else cout << "Detailing..." << endl;
+
+  // Load in the variables...
+  cString filename("detail.dat");
+  if (cur_string.GetSize() != 0) filename = cur_string.PopWord();
+
+  // Construct a linked list of details needed...
+  tList< tDataEntryCommand<cAnalyzeGenotype> > output_list;
+  tListIterator< tDataEntryCommand<cAnalyzeGenotype> > output_it(output_list);
+  LoadGenotypeDataList(cur_string, output_list);
+
+  // Determine the file type...
+  int file_type = FILE_TYPE_TEXT;
+  cString file_extension(filename);
+  while (file_extension.Find('.') != -1) file_extension.Pop('.');
+  if (file_extension == "html") file_type = FILE_TYPE_HTML;
+
+  // Setup the file...
+  if (filename == "cout") {
+    CommandDetail_Header(cout, file_type, output_it);
+    CommandDetail_Body(cout, file_type, output_it);
+  } else {
+    ofstream & fp = data_file_manager.GetOFStream(filename);
+    CommandDetail_Header(fp, file_type, output_it);
+    CommandDetail_Body(fp, file_type, output_it);
+  }
+
+  // And clean up...
+  while (output_list.GetSize() != 0) delete output_list.Pop();
+}
+
+
+void cAnalyze::CommandDetailTimeline(cString cur_string)
+{
+  if (verbose == true) cout << "Detailing batch "
+         << cur_batch << " based on time" << endl;
+  else cout << "Detailing..." << endl;
+
+  // Load in the variables...
+  cString filename("detail_timeline.dat");
+  int time_step = 100;
+  int max_time = 100000;
+  if (cur_string.GetSize() != 0) filename = cur_string.PopWord();
+  if (cur_string.GetSize() != 0) time_step = cur_string.PopWord().AsInt();
+  if (cur_string.GetSize() != 0) max_time = cur_string.PopWord().AsInt();
+
+  if (verbose == true) {
+    cout << "  Time step = " << time_step << endl
+  << "  Max time = " << max_time << endl;
+  }
+
+  // Construct a linked list of details needed...
+  tList< tDataEntryCommand<cAnalyzeGenotype> > output_list;
+  tListIterator< tDataEntryCommand<cAnalyzeGenotype> > output_it(output_list);
+  LoadGenotypeDataList(cur_string, output_list);
+
+  // Determine the file type...
+  int file_type = FILE_TYPE_TEXT;
+  cString file_extension(filename);
+  while (file_extension.Find('.') != -1) file_extension.Pop('.');
+  if (file_extension == "html") file_type = FILE_TYPE_HTML;
+
+  // Setup the file...
+  if (filename == "cout") {
+    CommandDetail_Header(cout, file_type, output_it, time_step);
+    CommandDetail_Body(cout, file_type, output_it, time_step, max_time);
+  } else {
+    ofstream & fp = data_file_manager.GetOFStream(filename);
+    CommandDetail_Header(fp, file_type, output_it, time_step);
+    CommandDetail_Body(fp, file_type, output_it, time_step, max_time);
+  }
+
+  // And clean up...
+  while (output_list.GetSize() != 0) delete output_list.Pop();
+}
+
+
+void cAnalyze::CommandDetail_Header(ostream & fp, int format_type,
+	    tListIterator< tDataEntryCommand<cAnalyzeGenotype> > & output_it,
+	    int time_step)
+{
+  // Write out the header on the file
+  if (format_type == FILE_TYPE_TEXT) {
+    fp << "#filetype genotype_data" << endl;
+    fp << "#format ";
+    if (time_step > 0) fp << "update ";
+    while (output_it.Next() != NULL) {
+      const cString & entry_name = output_it.Get()->GetName();
+      fp << entry_name << " ";
+    }
+    fp << endl << endl;
+
+    // Give the more human-readable legend.
+    fp << "# Legend:" << endl;
+    int count = 0;
+    if (time_step > 0) fp << "# " << ++count << ": Update" << endl;
+    while (output_it.Next() != NULL) {
+      const cString & entry_desc = output_it.Get()->GetDesc();
+      fp << "# " << ++count << ": " << entry_desc << endl;
+    }
+    fp << endl;
+  } else { // if (format_type == FILE_TYPE_HTML) {
+    fp << "<html>" << endl
+       << "<body bgcolor=\"#FFFFFF\"" << endl
+       << " text=\"#000000\"" << endl
+       << " link=\"#0000AA\"" << endl
+       << " alink=\"#0000FF\"" << endl
+       << " vlink=\"#000044\">" << endl
+       << endl
+       << "<h1 align=center>Run " << batch[cur_batch].Name() << endl
+       << endl
+       << "<center>" << endl
+       << "<table border=1 cellpadding=2><tr>" << endl;
+
+    if (time_step > 0) fp << "<th bgcolor=\"#AAAAFF\">Update ";
+    while (output_it.Next() != NULL) {
+      const cString & entry_desc = output_it.Get()->GetDesc();
+      fp << "<th bgcolor=\"#AAAAFF\">" << entry_desc << " ";
+    }
+    fp << "</tr>" << endl;
+
+  }
+
+}
+
+
+void cAnalyze::CommandDetail_Body(ostream & fp, int format_type,
+	    tListIterator< tDataEntryCommand<cAnalyzeGenotype> > & output_it,
+	    int time_step, int max_time)
+{
+  // Loop through all of the genotypes in this batch...
+  tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+  cAnalyzeGenotype * cur_genotype = batch_it.Next();
+  cAnalyzeGenotype * next_genotype = batch_it.Next();
+  cAnalyzeGenotype * prev_genotype = NULL;
+
+  int cur_time = 0;
+  while (cur_genotype != NULL && cur_time <= max_time) {
+    output_it.Reset();
+    tDataEntryCommand<cAnalyzeGenotype> * data_command = NULL;
+    if (format_type == FILE_TYPE_HTML) {
+      fp << "<tr>";
+      if (time_step > 0) fp << "<td>" << cur_time << " ";
+    }
+    else if (time_step > 0) {  // TEXT file, printing times...
+      fp << cur_time << " ";
+    }
+
+    while ((data_command = output_it.Next()) != NULL) {
+      data_command->SetTarget(cur_genotype);
+      cur_genotype->SetSpecialArgs(data_command->GetArgs());
+      if (format_type == FILE_TYPE_HTML) {
+	int compare = 0;
+        if (prev_genotype) {
+          prev_genotype->SetSpecialArgs(data_command->GetArgs());
+          compare = data_command->Compare(prev_genotype);
+	}
+	data_command->HTMLPrint(fp, compare);
+      }
+      else {  // if (format_type == FILE_TYPE_TEXT) {
+	fp << data_command->GetEntry() << " ";
+      }
+    }
+    if (format_type == FILE_TYPE_HTML) fp << "</tr>";
+    fp << endl;
+
+    cur_time += time_step;
+    if (time_step > 0) {
+      while (next_genotype && next_genotype->GetUpdateBorn() < cur_time) {
+       prev_genotype = cur_genotype;
+       cur_genotype = next_genotype;
+       next_genotype = batch_it.Next();
+      }
+    }
+    else {
+      // Always moveon if we're not basing this on time, or if we've run out
+      // of genotypes.
+      prev_genotype = cur_genotype;
+      cur_genotype = next_genotype;
+      next_genotype = batch_it.Next();
+    }
+
+  }
+
+  // If in HTML mode, we need to end the file...
+  if (format_type == FILE_TYPE_HTML) {
+    fp << "</table>" << endl
+       << "</center>" << endl;
+  }
+}
+
+void cAnalyze::CommandDetailBatches(cString cur_string)
+{
+  // Load in the variables...
+  cString keyword("num_cpus");
+  cString filename("detail_batch.dat");
+  if (cur_string.GetSize() != 0) keyword = cur_string.PopWord();
+  if (cur_string.GetSize() != 0) filename = cur_string.PopWord();
+
+  if (verbose == true) cout << "Detailing batches for " << keyword << endl;
+  else cout << "Detailing Batches..." << endl;
+
+  // Scan the functions list for the keyword we need...
+  SetupGenotypeDataList();
+  tListIterator< tDataEntryBase<cAnalyzeGenotype> >
+    output_it(genotype_data_list);
+
+  // Divide up the keyword into its acrual entry and its arguments...
+  cString cur_args = keyword;
+  cString cur_entry = cur_args.Pop(':');
+
+  // Find its associated command...
+  tDataEntryCommand<cAnalyzeGenotype> * cur_command = NULL;
+  bool found = false;
+  while (output_it.Next() != NULL) {
+    if (output_it.Get()->GetName() == cur_entry) {
+      cur_command = new tDataEntryCommand<cAnalyzeGenotype>
+	(output_it.Get(), cur_args);
+      found = true;
+      break;
+    }
+  }
+  if (found == false) {
+    cout << "Error: Unknown data type: " << cur_entry << endl;
+    return;
+  }
+
+
+  // Determine the file type...
+  int file_type = FILE_TYPE_TEXT;
+  cString file_extension(filename);
+  while (file_extension.Find('.') != -1) file_extension.Pop('.');
+  if (file_extension == "html") file_type = FILE_TYPE_HTML;
+
+  ofstream & fp = data_file_manager.GetOFStream(filename);
+
+  // Write out the header on the file
+  if (file_type == FILE_TYPE_TEXT) {
+    fp << "#filetype batch_data" << endl
+       << "#format batch_id " << keyword << endl
+       << endl;
+
+    // Give the more human-readable legend.
+    fp << "# Legend:" << endl
+       << "#  Column 1 = Batch ID" << endl
+       << "#  Remaining entries: " << cur_command->GetDesc() << endl
+       << endl;
+
+  } else { // if (file_type == FILE_TYPE_HTML) {
+    fp << "<html>" << endl
+       << "<body bgcolor=\"#FFFFFF\"" << endl
+       << " text=\"#000000\"" << endl
+       << " link=\"#0000AA\"" << endl
+       << " alink=\"#0000FF\"" << endl
+       << " vlink=\"#000044\">" << endl
+       << endl
+       << "<h1 align=center> Distribution of " << cur_command->GetDesc()
+       << endl << endl
+       << "<center>" << endl
+       << "<table border=1 cellpadding=2>" << endl
+       << "<tr><th bgcolor=\"#AAAAFF\">" << cur_command->GetDesc() << "</tr>"
+       << endl;
+  }
+
+
+  // Loop through all of the batches...
+  for (int i = 0; i < MAX_BATCHES; i++) {
+    if (batch[i].List().GetSize() == 0) continue;
+
+    if (file_type == FILE_TYPE_HTML) fp << "<tr><td>";
+    fp << i << " ";
+  
+    tListIterator<cAnalyzeGenotype> batch_it(batch[i].List());
+    cAnalyzeGenotype * genotype = NULL;
+    while ((genotype = batch_it.Next()) != NULL) {
+      output_it.Reset();
+      if (file_type == FILE_TYPE_HTML) fp << "<td>";
+
+      cur_command->SetTarget(genotype);
+      genotype->SetSpecialArgs(cur_command->GetArgs());
+      if (file_type == FILE_TYPE_HTML) {
+	cur_command->HTMLPrint(fp, 0);
+      }
+      else {  // if (file_type == FILE_TYPE_TEXT) {
+	fp << cur_command->GetEntry() << " ";
+      }
+    }
+    if (file_type == FILE_TYPE_HTML) fp << "</tr>";
+    fp << endl;
+  }
+
+  // If in HTML mode, we need to end the file...
+  if (file_type == FILE_TYPE_HTML) {
+    fp << "</table>" << endl
+       << "</center>" << endl;
+  }
+  
+  delete cur_command;
+}
+
+
+
+void cAnalyze::CommandDetailIndex(cString cur_string)
+{
+  cout << "Creating a Detail Index..." << endl;
+
+  // A filename and min and max batches must be included.
+  if (cur_string.CountNumWords() < 3) {
+    cerr << "Error: must include filename, and min and max batch numbers."
+	 << endl;
+    exit(1);
+  }
+
+  // Load in the variables...
+  cString filename(cur_string.PopWord());
+  int min_batch = cur_string.PopWord().AsInt();
+  int max_batch = cur_string.PopWord().AsInt();
+
+  if (max_batch < min_batch) {
+    cerr << "Error: min_batch=" << min_batch
+	 << ", max_batch=" << max_batch << "  (incorrect order?)" << endl;
+    exit(1);
+  }
+
+  // Construct a linked list of details needed...
+  tList< tDataEntryBase<cAnalyzeGenotype> > output_list;
+  tListIterator< tDataEntryBase<cAnalyzeGenotype> > output_it(output_list);
+
+  // For the moment, just put everything into the output list.
+  SetupGenotypeDataList();
+
+  // If no args were given, load all of the stats.
+  if (cur_string.CountNumWords() == 0) {
+    tListIterator< tDataEntryBase<cAnalyzeGenotype> >
+      genotype_data_it(genotype_data_list);
+    while (genotype_data_it.Next() != NULL) {
+      output_list.PushRear(genotype_data_it.Get());
+    }
+  }
+  // Otherwise, load only those listed.
+  else {
+    while (cur_string.GetSize() != 0) {
+      // Setup the next entry
+      cString cur_entry = cur_string.PopWord();
+      bool found_entry = false;
+
+      // Scan the genotype data list for the current entry
+      tListIterator< tDataEntryBase<cAnalyzeGenotype> >
+	genotype_data_it(genotype_data_list);
+
+      while (genotype_data_it.Next() != NULL) {
+	if (genotype_data_it.Get()->GetName() == cur_entry) {
+	  output_list.PushRear(genotype_data_it.Get());
+	  found_entry = true;
+	  break;
+	}
+      }
+
+      // If the entry was not found, give a warning.
+      if (found_entry == false) {
+	int best_match = 1000;
+	cString best_entry;
+
+	genotype_data_it.Reset();
+	while (genotype_data_it.Next() != NULL) {
+	  const cString & test_str = genotype_data_it.Get()->GetName();
+	  const int test_dist = cStringUtil::EditDistance(test_str, cur_entry);
+	  if (test_dist < best_match) {
+	    best_match = test_dist;
+	    best_entry = test_str;
+	  }
+	}	
+
+	cerr << "Warning: Format entry \"" << cur_entry
+	     << "\" not found.  Best match is \""
+	     << best_entry << "\"." << endl;
+      }
+
+    }
+  }
+
+  // Setup the file...
+  ofstream fp;
+  fp.open(filename);
+
+  // Determine the file type...
+  int file_type = FILE_TYPE_TEXT;
+  while (filename.Find('.') != -1) filename.Pop('.'); // Grab only extension
+  if (filename == "html") file_type = FILE_TYPE_HTML;
+
+  // Write out the header on the file
+  if (file_type == FILE_TYPE_TEXT) {
+    fp << "#filetype genotype_data" << endl;
+    fp << "#format ";
+    while (output_it.Next() != NULL) {
+      const cString & entry_name = output_it.Get()->GetName();
+      fp << entry_name << " ";
+    }
+    fp << endl << endl;
+
+    // Give the more human-readable legend.
+    fp << "# Legend:" << endl;
+    fp << "# 1: Batch Name" << endl;
+    int count = 1;
+    while (output_it.Next() != NULL) {
+      const cString & entry_desc = output_it.Get()->GetDesc();
+      fp << "# " << ++count << ": " << entry_desc << endl;
+    }
+    fp << endl;
+  } else { // if (file_type == FILE_TYPE_HTML) {
+    fp << "<html>" << endl
+       << "<body bgcolor=\"#FFFFFF\"" << endl
+       << " text=\"#000000\"" << endl
+       << " link=\"#0000AA\"" << endl
+       << " alink=\"#0000FF\"" << endl
+       << " vlink=\"#000044\">" << endl
+       << endl
+       << "<h1 align=center>Batch Index" << endl
+       << endl
+       << "<center>" << endl
+       << "<table border=1 cellpadding=2><tr>" << endl;
+
+    fp << "<th bgcolor=\"#AAAAFF\">Batch ";
+    while (output_it.Next() != NULL) {
+      const cString & entry_desc = output_it.Get()->GetDesc();
+      fp << "<th bgcolor=\"#AAAAFF\">" << entry_desc << " ";
+    }
+    fp << "</tr>" << endl;
+
+  }
+
+  // Loop through all of the batchs...
+  for (int batch_id = min_batch; batch_id <= max_batch; batch_id++) {
+    cAnalyzeGenotype * genotype = batch[batch_id].List().GetFirst();
+    if (genotype == NULL) continue;
+    output_it.Reset();
+    tDataEntryBase<cAnalyzeGenotype> * data_entry = NULL;
+    const cString & batch_name = batch[batch_id].Name();
+    if (file_type == FILE_TYPE_HTML) {
+      fp << "<tr><th><a href=lineage." << batch_name << ".html>"
+	 << batch_name << "</a> ";
+    }
+    else {
+      fp << batch_name << " ";
+    }
+
+    while ((data_entry = output_it.Next()) != NULL) {
+      data_entry->SetTarget(genotype);
+      if (file_type == FILE_TYPE_HTML) {
+	fp << "<td align=center><a href=\""
+	   << data_entry->GetName() << "." << batch_name << ".png\">"
+	   << *data_entry << "</a> ";
+      }
+      else {  // if (file_type == FILE_TYPE_TEXT) {
+	fp << *data_entry << " ";
+      }
+    }
+    if (file_type == FILE_TYPE_HTML) fp << "</tr>";
+    fp << endl;
+  }
+
+  // If in HTML mode, we need to end the file...
+  if (file_type == FILE_TYPE_HTML) {
+    fp << "</table>" << endl
+       << "</center>" << endl;
+  }
+}
+
+
+///// Population Analysis Commands ////
+
+void cAnalyze::CommandPrintPhenotypes(cString cur_string)
+{
+  if (verbose == true) cout << "Printing phenotypes in batch "
+			    << cur_batch << endl;
+  else cout << "Printing phenotypes..." << endl;
+
+  // Load in the variables...
+  cString filename("phenotype.dat");
+  if (cur_string.GetSize() != 0) filename = cur_string.PopWord();
+
+  // Make sure we have at least one genotype...
+  if (batch[cur_batch].List().GetSize() == 0) return;
+
+  // Setup the phenotype categories...
+  const int num_tasks = batch[cur_batch].List().GetFirst()->GetNumTasks();
+  const int num_phenotypes = 1 << (num_tasks + 1);
+  tArray<int> phenotype_counts(num_phenotypes);
+  tArray<int> genotype_counts(num_phenotypes);
+  tArray<double> total_length(num_phenotypes);
+  tArray<double> total_gest(num_phenotypes);
+
+  phenotype_counts.SetAll(0);
+  genotype_counts.SetAll(0);
+  total_length.SetAll(0.0);
+  total_gest.SetAll(0.0);
+
+  // Loop through all of the genotypes in this batch...
+  tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+  cAnalyzeGenotype * genotype = NULL;
+  while ((genotype = batch_it.Next()) != NULL) {
+    int phen_id = 0;
+    if (genotype->GetViable() == true) phen_id++;
+    for (int i = 0; i < num_tasks; i++) {
+      if (genotype->GetTaskCount(i) > 0)  phen_id += 1 << (i+1);
+    }
+    phenotype_counts[phen_id] += genotype->GetNumCPUs();
+    genotype_counts[phen_id]++;
+    total_length[phen_id] += genotype->GetNumCPUs() * genotype->GetLength();
+    total_gest[phen_id] += genotype->GetNumCPUs() * genotype->GetGestTime();
+  }
+
+  // Print out the results...
+  
+  ofstream & fp = data_file_manager.GetOFStream(filename);
+
+  fp << "# 1: Number of organisms of this phenotype" << endl
+     << "# 2: Number of genotypes of this phenotye" << endl
+     << "# 3: Average Genome Length" << endl
+     << "# 4: Average Gestation Time" << endl
+     << "# 5: Viability of Phenotype" << endl
+     << "# 6+: Tasks performed in this phenotype" << endl
+     << endl;
+
+  // @CAO Lets do this inefficiently for the moment, but print out the
+  // phenotypes in order.
+
+  while (true) {
+    // Find the next phenotype to print...
+    int max_count = phenotype_counts[0];
+    int max_position = 0;
+    for (int i = 0; i < num_phenotypes; i++) {
+      if (phenotype_counts[i] > max_count) {
+	max_count = phenotype_counts[i];
+	max_position = i;
+      }
+    }
+
+    if (max_count == 0) break; // we're done!
+
+    fp << phenotype_counts[max_position] << " "
+       << genotype_counts[max_position] << " "
+       << total_length[max_position] / phenotype_counts[max_position] << " "
+       << total_gest[max_position] / phenotype_counts[max_position] << " "
+       << (max_position & 1) << "  ";
+    for (int i = 1; i <= num_tasks; i++) {
+      if ((max_position >> i) & 1 > 0) fp << "1 ";
+      else fp << "0 ";
+    }
+    fp << endl;
+    phenotype_counts[max_position] = 0;
+  }
+
+  fp.close();
+}
+
+
+// Print various diversity metrics from the current batch of genotypes...
+void cAnalyze::CommandPrintDiversity(cString cur_string)
+{
+  if (verbose == true) cout << "Printing diversity data for batch "
+			    << cur_batch << endl;
+  else cout << "Printing diversity data..." << endl;
+
+  // Load in the variables...
+  cString filename("diversity.dat");
+  if (cur_string.GetSize() != 0) filename = cur_string.PopWord();
+
+  // Make sure we have at least one genotype...
+  if (batch[cur_batch].List().GetSize() == 0) return;
+
+  // Setup the task categories...
+  const int num_tasks = batch[cur_batch].List().GetFirst()->GetNumTasks();
+  tArray<int> task_count(num_tasks);
+  tArray<int> task_gen_count(num_tasks);
+  tArray<double> task_gen_dist(num_tasks);
+  tArray<double> task_site_entropy(num_tasks);
+  task_count.SetAll(0);
+  task_gen_count.SetAll(0);
+
+  // We must determine the average hamming distance between genotypes in
+  // this batch that perform each task.  Levenstein distance would be ideal,
+  // but takes a while, so we'll do it this way first.  For the calculations,
+  // we need to know home many times each instruction appears at each
+  // position for each genotype collection that performs a particular task.
+  const int num_insts = inst_set.GetSize();
+  const int max_length = BatchUtil_GetMaxLength();
+  tMatrix<int> inst_freq(max_length, num_insts+1);
+
+  for (int task_id = 0; task_id < num_tasks; task_id++) {
+    inst_freq.SetAll(0);
+
+    // Loop through all genotypes, singling out those that do current task...
+    tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+    cAnalyzeGenotype * genotype = NULL;
+    while ((genotype = batch_it.Next()) != NULL) {
+      if (genotype->GetTaskCount(task_id) == 0) continue;
+
+      const cGenome & genome = genotype->GetGenome();
+      const int num_cpus = genotype->GetNumCPUs();
+      task_count[task_id] += num_cpus;
+      task_gen_count[task_id]++;
+      for (int i = 0; i < genotype->GetLength(); i++) {
+	inst_freq( i, genome[i].GetOp() ) += num_cpus;
+      }
+      for (int i = genotype->GetLength(); i < max_length; i++) {
+	inst_freq(i, num_insts) += num_cpus; // Entry for "past genome end"
+      }
+    }
+
+    // Analyze the data for this entry...
+    const int cur_count = task_count[task_id];
+    const int total_pairs = cur_count * (cur_count - 1) / 2;
+    int total_dist = 0;
+    double total_ent = 0;
+    for (int pos = 0; pos < max_length; pos++) {
+      // Calculate distance component...
+      for (int inst1 = 0; inst1 < num_insts; inst1++) {
+	if (inst_freq(pos, inst1) == 0) continue;
+	for (int inst2 = inst1+1; inst2 <= num_insts; inst2++) {
+	  total_dist += inst_freq(pos, inst1) * inst_freq(pos, inst2);
+	}
+      }
+
+      // Calculate entropy component...
+      for (int i = 0; i <= num_insts; i++) {
+	const int cur_freq = inst_freq(pos, i);
+	if (cur_freq == 0) continue;
+	const double p = ((double) cur_freq) / (double) cur_count;
+	total_ent -= p * log(p);
+      }
+    }
+
+    task_gen_dist[task_id] = ((double) total_dist) / (double) total_pairs;
+    task_site_entropy[task_id] = total_ent;
+  }
+
+  // Print out the results...
+  cDataFile & df = data_file_manager.Get(filename);
+
+  for (int i = 0; i < num_tasks; i++) {
+    df.Write(i,                    "# 1: Task ID");
+    df.Write(task_count[i],        "# 2: Number of organisms performing task");
+    df.Write(task_gen_count[i],    "# 3: Number of genotypes performing task");
+    df.Write(task_gen_dist[i],     "# 4: Average distance between genotypes performing task");
+    df.Write(task_site_entropy[i], "# 5: Total per-site entropy of genotypes performing task");
+    df.Endl();
+  }
+}
+
+
+void cAnalyze::CommandLandscape(cString cur_string)
+{
+  if (verbose == true) cout << "Landscaping batch " << cur_batch << endl;
+  else cout << "Landscapping..." << endl;
+
+  // Load in the variables...
+  cString filename;
+  if (cur_string.GetSize() != 0) filename = cur_string.PopWord();
+  int dist = 1;
+  if (cur_string.GetSize() != 0) dist = cur_string.PopWord().AsInt();
+
+  // If we're given a file, write to it.
+  ofstream & fp = data_file_manager.GetOFStream(filename);
+  
+  // Loop through all of the genotypes in this batch...
+  tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+  cAnalyzeGenotype * genotype = NULL;
+  while ((genotype = batch_it.Next()) != NULL) {
+    cLandscape landscape(genotype->GetGenome(), inst_set);
+    landscape.Process(dist);
+    fp << genotype->GetName() << " ";
+    landscape.PrintStats(fp);
+  }
+}
+
+void cAnalyze::CommandFitnessMatrix(cString cur_string)
+{
+  if (verbose == true) cout << "Calculating fitness matrix for batch " << cur_batch << endl;
+  else cout << "Calculating fitness matrix..." << endl;
+
+  cout << "Warning: considering only first genotype of the batch!" << endl;
+
+  // Load in the variables...
+  int depth_limit = 4;
+  if (cur_string.GetSize() != 0) depth_limit = cur_string.PopWord().AsInt();
+
+  double fitness_threshold_ratio = .9;
+  if (cur_string.GetSize() != 0) fitness_threshold_ratio = cur_string.PopWord().AsDouble();
+
+  int ham_thresh  = 1;
+  if (cur_string.GetSize() != 0) ham_thresh = cur_string.PopWord().AsInt();
+
+  double error_rate_min = 0.005;
+  if (cur_string.GetSize() != 0) error_rate_min = cur_string.PopWord().AsDouble();
+
+  double error_rate_max = 0.05;
+  if (cur_string.GetSize() != 0) error_rate_max = cur_string.PopWord().AsDouble();
+
+  double error_rate_step = 0.005;
+  if (cur_string.GetSize() != 0) error_rate_step = cur_string.PopWord().AsDouble();
+
+  double vect_fmax = 1.1;
+  if (cur_string.GetSize() != 0) vect_fmax = cur_string.PopWord().AsDouble();
+
+  double vect_fstep = .1;
+  if (cur_string.GetSize() != 0) vect_fstep = cur_string.PopWord().AsDouble();
+
+  int diag_iters = 200;
+  if (cur_string.GetSize() != 0) diag_iters = cur_string.PopWord().AsInt();
+
+  int write_ham_vector = 0;
+  if (cur_string.GetSize() != 0) write_ham_vector = cur_string.PopWord().AsInt();
+
+  int write_full_vector = 0;
+  if (cur_string.GetSize() != 0) write_full_vector = cur_string.PopWord().AsInt();
+
+  // Consider only the first genotypes in this batch...
+  tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+  cAnalyzeGenotype * genotype = batch_it.Next();
+
+  cFitnessMatrix matrix( genotype->GetGenome(), &inst_set);
+
+  matrix.CalcFitnessMatrix( depth_limit, fitness_threshold_ratio, ham_thresh, error_rate_min, error_rate_max, error_rate_step, vect_fmax, vect_fstep, diag_iters, write_ham_vector, write_full_vector );
+}
+
+
+void cAnalyze::CommandMapTasks(cString cur_string)
+{
+  cout << "Constructing genotype-phenotype maps..." << endl;
+
+  // Load in the variables...
+  cString directory = PopDirectory(cur_string, "phenotype/");
+  int print_mode = 0;   // 0=Normal, 1=Boolean results
+  int file_type = FILE_TYPE_TEXT;
+
+  // HTML special flags...
+  bool link_maps = false;  // Should muliple maps be linked together?
+  bool link_insts = false; // Should links be made to instruction descs?
+
+  // Collect any other format information needed...
+  tList< tDataEntryCommand<cAnalyzeGenotype> > output_list;
+  tListIterator< tDataEntryCommand<cAnalyzeGenotype> > output_it(output_list);
+
+  cStringList arg_list(cur_string);
+
+  cout << "Found " << arg_list.GetSize() << " args." << endl;
+
+  // Check for some command specific variables.
+  if (arg_list.PopString("0") != "") print_mode = 0;
+  if (arg_list.PopString("1") != "") print_mode = 1;
+  if (arg_list.PopString("text") != "") file_type = FILE_TYPE_TEXT;
+  if (arg_list.PopString("html") != "") file_type = FILE_TYPE_HTML;
+  if (arg_list.PopString("link_maps") != "") link_maps = true;
+  if (arg_list.PopString("link_insts") != "") link_insts = true;
+
+  cout << "There are " << arg_list.GetSize() << " column args." << endl;
+
+  LoadGenotypeDataList(arg_list, output_list);
+
+  cout << "Args are loaded." << endl;
+
+  const int num_cols = output_list.GetSize();
+
+  // Give some information in verbose mode.
+  if (verbose == true) {
+    cout << "  outputing as ";
+    if (print_mode == 1) cout << "boolean ";
+    if (file_type == FILE_TYPE_TEXT) {
+      cout << "text files." << endl;
+    } else { // if (file_type == FILE_TYPE_HTML) {
+      cout << "HTML files";
+      if (link_maps == true) cout << "; linking files together";
+      if (link_maps == true) cout << "; linking inst names to descs";
+      cout << "." << endl;
+    }
+    cout << "  Format: ";
+
+    output_it.Reset();
+    while (output_it.Next() != NULL) {
+      cout << output_it.Get()->GetName() << " ";
+    }
+    cout << endl;
+  }
+
+
+  ///////////////////////////////////////////////////////
+  // Loop through all of the genotypes in this batch...
+
+  tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+  cAnalyzeGenotype * genotype = NULL;
+  while ((genotype = batch_it.Next()) != NULL) {
+    if (verbose == true) cout << "  Mapping " << genotype->GetName() << endl;
+
+    // Construct this filename...
+    cString filename;
+    if (file_type == FILE_TYPE_TEXT) {
+      filename.Set("%stasksites.%s.dat", directory(), genotype->GetName()());
+    } else {   //  if (file_type == FILE_TYPE_HTML) {
+      filename.Set("%stasksites.%s.html", directory(), genotype->GetName()());
+    }
+    ofstream fp(filename());
+
+    // Construct linked filenames...
+    cString next_file("");
+    cString prev_file("");
+    if (link_maps == true) {
+      // Check the next genotype on the list...
+      if (batch_it.Next() != NULL) {
+	next_file.Set("tasksites.%s.html", batch_it.Get()->GetName()());
+      }
+      batch_it.Prev();  // Put the list back where it was...
+
+      // Check the previous genotype on the list...
+      if (batch_it.Prev() != NULL) {
+	prev_file.Set("tasksites.%s.html", batch_it.Get()->GetName()());
+      }
+      batch_it.Next();  // Put the list back where it was...
+    }
+
+    // Calculate the stats for the genotype we're working with...
+    genotype->Recalculate();
+
+    // Headers...
+    if (file_type == FILE_TYPE_TEXT) {
+      fp << "-1 "  << batch[cur_batch].Name() << " "
+	 << genotype->GetID() << " ";
+
+      tDataEntryCommand<cAnalyzeGenotype> * data_command = NULL;
+      while ((data_command = output_it.Next()) != NULL) {
+	data_command->SetTarget(genotype);
+	fp << data_command->GetEntry() << " ";
+      }
+      fp << endl;
+
+    } else { // if (file_type == FILE_TYPE_HTML) {
+      // Mark file as html
+      fp << "<html>" << endl;
+
+      // Setup any javascript macros needed...
+      fp << "<head>" << endl;
+      if (link_insts == true) {
+	fp << "<script language=\"javascript\">" << endl
+	   << "function Inst(inst_name)" << endl
+	   << "{" << endl
+	   << "var filename = \"help.\" + inst_name + \".html\";" << endl
+	   << "newwin = window.open(filename, 'Instruction', "
+	   << "'toolbar=0,status=0,location=0,directories=0,menubar=0,"
+	   << "scrollbars=1,height=150,width=300');" << endl
+	   << "newwin.focus();" << endl
+	   << "}" << endl
+	   << "</script>" << endl;
+      }
+      fp << "</head>" << endl;
+
+      // Setup the body...
+      fp << "<body bgcolor=\"#FFFFFF\"" << endl
+	 << " text=\"#000000\"" << endl
+	 << " link=\"#0000AA\"" << endl
+	 << " alink=\"#0000FF\"" << endl
+	 << " vlink=\"#000044\">" << endl
+	 << endl
+	 << "<h1 align=center>Run " << batch[cur_batch].Name()
+	 << ", ID " << genotype->GetID() << "</h1>" << endl
+	 << "<center>" << endl
+	 << endl;
+
+      // Links?
+      fp << "<table width=90%><tr><td align=left>";
+      if (prev_file != "") fp << "<a href=\"" << prev_file << "\">Prev</a>";
+      else fp << "&nbsp;";
+      fp << "<td align=right>";
+      if (next_file != "") fp << "<a href=\"" << next_file << "\">Next</a>";
+      else fp << "&nbsp;";
+      fp << "</tr></table>" << endl;
+
+      // The table
+      fp << "<table border=1 cellpadding=2>" << endl;
+
+      // The headings...///
+      fp << "<tr><td colspan=3> ";
+      output_it.Reset();
+      while (output_it.Next() != NULL) {
+	fp << "<th>" << output_it.Get()->GetDesc() << " ";
+      }
+      fp << "</tr>" << endl;
+
+      // The base creature...
+      fp << "<tr><th colspan=3>Base Creature";
+      tDataEntryCommand<cAnalyzeGenotype> * data_command = NULL;
+      cAnalyzeGenotype null_genotype("a", inst_set);
+      while ((data_command = output_it.Next()) != NULL) {
+	data_command->SetTarget(genotype);
+	genotype->SetSpecialArgs(data_command->GetArgs());
+	if (data_command->Compare(&null_genotype) > 0) {
+	  fp << "<th bgcolor=\"#00FF00\">";
+	}
+	else  fp << "<th bgcolor=\"#FF0000\">";
+
+	if (data_command->HasArg("blank") == true) fp << "&nbsp;" << " ";
+	else fp << data_command->GetEntry() << " ";
+      }
+      fp << "</tr>" << endl;
+    }
+
+
+    const int max_line = genotype->GetLength();
+    const cGenome & base_genome = genotype->GetGenome();
+    cGenome mod_genome(base_genome);
+
+    // Keep track of the number of failues/successes for attributes...
+    int * col_pass_count = new int[num_cols];
+    int * col_fail_count = new int[num_cols];
+    for (int i = 0; i < num_cols; i++) {
+      col_pass_count[i] = 0;
+      col_fail_count[i] = 0;
+    }
+
+    cInstSet map_inst_set(inst_set);
+    // Locate instruction corresponding to "NULL" in the instruction library.
+    {
+      const cInstruction inst_lib_null_inst = map_inst_set.GetInstLib()->GetInst("NULL");
+      if(inst_lib_null_inst == map_inst_set.GetInstLib()->GetInstError()){
+        cout << "<cAnalyze::CommandMapTasks> got error:" << endl;
+        cout << " --- instruction \"NULL\" isn't in the instruction library;" << endl;
+        cout << " --- get somebody to map a function to \"NULL\" in the library." << endl;
+        cout << " --- (probably to class method \"cHardware-of-some-type::initInstLib\"" << endl;
+        cout << " --- in file named \"cpu/hardware-of-some-type.cc\".)" << endl;
+        cout << " --- bailing-out." << endl;
+        exit(1);
+      }
+      // Add mapping to located instruction. 
+      map_inst_set.Add2(inst_lib_null_inst.GetOp());
+    }
+    const cInstruction null_inst = map_inst_set.GetInst("NULL");
+
+    // Loop through all the lines of code, testing the removal of each.
+    for (int line_num = 0; line_num < max_line; line_num++) {
+      int cur_inst = base_genome[line_num].GetOp();
+      char cur_symbol = base_genome[line_num].GetSymbol();
+
+      mod_genome[line_num] = null_inst;
+      cAnalyzeGenotype test_genotype(mod_genome, map_inst_set);
+      test_genotype.Recalculate();
+
+      if (file_type == FILE_TYPE_HTML) fp << "<tr><td align=right>";
+      fp << (line_num + 1) << " ";
+      if (file_type == FILE_TYPE_HTML) fp << "<td align=center>";
+      fp << cur_symbol << " ";
+      if (file_type == FILE_TYPE_HTML) fp << "<td align=center>";
+      if (link_insts == true) {
+	fp << "<a href=\"javascript:Inst('"
+	   << map_inst_set.GetName(cur_inst)
+	   << "')\">";
+      }
+      fp << map_inst_set.GetName(cur_inst) << " ";
+      if (link_insts == true) fp << "</a>";
+
+
+      // Print the individual columns...
+      output_it.Reset();
+      tDataEntryCommand<cAnalyzeGenotype> * data_command = NULL;
+      int cur_col = 0;
+      while ((data_command = output_it.Next()) != NULL) {
+	data_command->SetTarget(&test_genotype);
+	test_genotype.SetSpecialArgs(data_command->GetArgs());
+	int compare = data_command->Compare(genotype);
+	if (file_type == FILE_TYPE_HTML) {
+	  data_command->HTMLPrint(fp, compare,
+				  !(data_command->HasArg("blank")));
+	} 
+	else fp << data_command->GetEntry() << " ";
+
+	if (compare == -2) col_fail_count[cur_col]++;
+	else if (compare == 2) col_pass_count[cur_col]++;
+	cur_col++;
+      }
+      if (file_type == FILE_TYPE_HTML) fp << "</tr>";
+      fp << endl;
+
+      // Reset the mod_genome back to the original sequence.
+      mod_genome[line_num].SetOp(cur_inst);
+    }
+
+
+    // Construct the final line of the table with all totals...
+    if (file_type == FILE_TYPE_HTML) {
+      fp << "<tr><th colspan=3>Totals";
+
+      for (int i = 0; i < num_cols; i++) {
+	if (col_pass_count[i] > 0) {
+	  fp << "<th bgcolor=\"#00FF00\">" << col_pass_count[i];
+	}
+	else if (col_fail_count[i] > 0) {
+	  fp << "<th bgcolor=\"#FF0000\">" << col_fail_count[i];
+	}
+	else fp << "<th>0";
+      }
+      fp << "</tr>" << endl;
+
+      // And close everything up...
+      fp << "</table>" << endl
+	 << "</center>" << endl;
+    }
+
+    delete [] col_pass_count;
+    delete [] col_fail_count;
+
+  }
+}
+
+void cAnalyze::CommandAverageModularity(cString cur_string)
+{
+  cout << "Average Modularity calculations" << endl;
+
+  // Load in the variables...
+  cString filename = cur_string.PopWord();
+//    cString filename = "average.dat";
+
+  int print_mode = 0;   // 0=Normal, 1=Boolean results
+
+  // Collect any other format information needed...
+  tList< tDataEntryCommand<cAnalyzeGenotype> > output_list;
+  tListIterator< tDataEntryCommand<cAnalyzeGenotype> > output_it(output_list);
+
+  cStringList arg_list(cur_string);
+
+  cout << "Found " << arg_list.GetSize() << " args." << endl;
+
+  // Check for some command specific variables.
+  if (arg_list.PopString("0") != "") print_mode = 0;
+  if (arg_list.PopString("1") != "") print_mode = 1;
+
+  cout << "There are " << arg_list.GetSize() << " column args." << endl;
+
+  LoadGenotypeDataList(arg_list, output_list);
+
+  cout << "Args are loaded." << endl;
+
+  const int num_cols = output_list.GetSize();
+
+  // Give some information in verbose mode.
+  if (verbose == true) {
+    cout << "  outputing as ";
+    if (print_mode == 1) cout << "boolean ";
+      cout << "text files." << endl;
+    cout << "  Format: ";
+
+    output_it.Reset();
+    while (output_it.Next() != NULL) {
+      cout << output_it.Get()->GetName() << " ";
+    }
+    cout << endl;
+  }
+
+    ofstream & fp = data_file_manager.GetOFStream(filename);
+
+  // printing the headers
+  // not done by default since many dumps may be analyzed at the same time
+  // and results would be put in the same file
+  if (arg_list.GetSize()==0) {
+    // Headers
+    fp << "# Avida analyze modularity data" << endl;
+    fp << "# 1: organism length" << endl;
+    fp << "# 2: number of tasks done" << endl;
+    fp << "# 3: number of sites used in tasks" << endl;
+    fp << "# 4: proportion of sites used in tasks" << endl;
+    fp << "# 5: average number of tasks done per site" << endl;
+    fp << "# 6: average number sites per task done" << endl;
+    fp << "# 7: average number tasks per site per task" << endl;
+    fp << "# 8: average proportion of the non-overlaping region of a task" << endl;
+    fp << "# 9-17: average StDev in positions used for task 1-9" << endl;
+    fp << "# 18-26: average number of sites necessary for each of the tasks" << endl;
+    fp << "# 27-36: number of sites involved in 0-9 tasks" << endl;
+    fp << "# 37-45: average task length (distance from first to last inst used)" << endl;
+    fp << endl;
+    return;
+}        
+
+  // initialize various variables used in calculations
+
+    int num_orgs = 0;		// number of organisms in the dump
+
+    double  av_length = 0; 	// average organism length
+    double  av_task = 0; 	// average # of tasks done
+    double  av_inst = 0; 	// average # instructions used in tasks
+    double  av_inst_len = 0; 	// proportion of sites used for tasks
+    double  av_site_task = 0; 	// average number of sites per task
+    double  av_task_site = 0;   // average number of tasks per site
+    double  av_t_s_norm = 0;	// average number of tasks per site per task
+    double  av_task_overlap = 0; // average overlap between tasks
+
+    // average StDev in positions used for a task
+    tArray<double> std_task_position(num_cols);
+    std_task_position.SetAll(0.0);
+    
+    // # of organisms actually doing a task
+    tArray<double> org_task(num_cols);
+    org_task.SetAll(0.0);
+
+    // av. # of sites necessary for each of the tasks
+    tArray<double> av_num_inst(num_cols);
+    av_num_inst.SetAll(0.0);
+    
+    // number of sites involved in 0-9 tasks 
+    tArray<double> av_inst_task(num_cols+1);
+    av_inst_task.SetAll(0.0);
+
+    // av. # task length (distance from first to last site used)
+    tArray<double> av_task_length(num_cols);
+    av_task_length.SetAll(0.0);
+
+    
+  ///////////////////////////////////////////////////////
+  // Loop through all of the genotypes in this batch...
+  ///////////////////////////////////////////////////////
+
+  tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+  cAnalyzeGenotype * genotype = NULL;
+
+  // would like to test oly the viable ones, but they can be non-viable
+  // and still reproduce and do tasks
+  // while ((genotype = batch_it.Next()) != NULL && genotype->GetViable()) {
+  while ((genotype = batch_it.Next()) != NULL) {
+
+    int num_cpus = genotype->GetNumCPUs();
+
+    if (verbose == true) cout << "  Mapping " << genotype->GetName() << endl;
+ 
+    // Calculate the stats for the genotype we're working with...
+    genotype->Recalculate();
+
+    // Check if the organism does any tasks. 
+    int does_tasks = 0;
+    for (int i = 0; i < num_cols; i++) {
+      if (genotype->GetTaskCount(i) > 0)  does_tasks = 1;
+    }
+
+   // Don't calculate the modularity if the organism doesn't reproduce
+   // i.e. if the fitness is 0 
+   if (genotype->GetFitness() != 0 && does_tasks != 0) {
+    num_orgs = num_orgs + num_cpus;
+
+    const int max_line = genotype->GetLength();
+    const cGenome & base_genome = genotype->GetGenome();
+    cGenome mod_genome(base_genome);
+
+    // Create and initialize the modularity matrix
+    tMatrix<int> mod_matrix(num_cols, max_line);
+    mod_matrix.SetAll(0);
+
+    // Create and initialize the task overalp matrix
+    tMatrix<int> task_overlap(num_cols, num_cols);
+    task_overlap.SetAll(0);
+
+    // Create an initialize the counters for modularity
+    tArray<int> num_task(max_line); // number of tasks instruction is used in
+    tArray<int> num_inst(num_cols); // number of instructions involved in a task
+    tArray<int> sum(num_cols); 	    // helps with StDev calculations
+    tArray<int> sumsq(num_cols);    // helps with StDev calculations
+    tArray<int> inst_task(num_cols+1); // # of inst's involved in 0,1,2,3... tasks
+    tArray<int> task_length(num_cols);    // ditance between first and last inst involved in a task
+
+    num_task.SetAll(0);
+    num_inst.SetAll(0);
+    sum.SetAll(0);
+    sumsq.SetAll(0);
+    inst_task.SetAll(0);
+    task_length.SetAll(0);
+
+    int total_task = 0;        // total number of tasks done
+    int total_inst = 0;        // total number of instructions involved in tasks
+    int total_all = 0;         // sum of mod_matrix
+    double sum_task_overlap = 0;// task overlap for for this geneome
+
+    cInstSet map_inst_set(inst_set);
+
+    // Locate instruction corresponding to "NULL" in the instruction library.
+    {
+      const cInstruction inst_lib_null_inst = map_inst_set.GetInstLib()->GetInst("NULL");
+      if(inst_lib_null_inst == map_inst_set.GetInstLib()->GetInstError()){
+        cout << "<cAnalyze::CommandMapTasks> got error:" << endl;
+        cout << " --- instruction \"NULL\" isn't in the instruction library;" << endl;
+        cout << " --- get somebody to map a function to \"NULL\" in the library." << endl;
+        cout << " --- (probably to class method \"cHardware-of-some-type::initInstLib\"" << endl;
+        cout << " --- in file named \"cpu/hardware-of-some-type.cc\".)" << endl;
+        cout << " --- bailing-out." << endl;
+        exit(1);
+      }
+      // Add mapping to located instruction. 
+      map_inst_set.Add2(inst_lib_null_inst.GetOp());
+    }
+    const cInstruction null_inst = map_inst_set.GetInst("NULL");
+
+    // Loop through all the lines of code, testing the removal of each.
+    for (int line_num = 0; line_num < max_line; line_num++) {
+      int cur_inst = base_genome[line_num].GetOp();
+      char cur_symbol = base_genome[line_num].GetSymbol();
+
+      mod_genome[line_num] = null_inst;
+      cAnalyzeGenotype test_genotype(mod_genome, map_inst_set);
+      cAnalyzeGenotype old_genotype(base_genome, map_inst_set);
+      test_genotype.Recalculate();
+
+      // Print the individual columns...
+      output_it.Reset();
+      tDataEntryCommand<cAnalyzeGenotype> * data_command = NULL;
+      int cur_col = 0;
+      while ((data_command = output_it.Next()) != NULL) {
+	data_command->SetTarget(&test_genotype);
+	test_genotype.SetSpecialArgs(data_command->GetArgs());
+        // This is done so that under 'binary' option it marks
+        // the task as being influenced by the mutation iff
+        // it is completely knocked out, not just decreased
+        genotype->SetSpecialArgs(data_command->GetArgs());
+
+	int compare = data_command->Compare(genotype);
+
+	// If knocking out an instruction stops the expression of a
+	// particular task, mark that in the modularity matrix
+	// and add it to two counts
+	// Only do the checking if the test_genotype replicate, i.e.
+	// if it's fitness is not zeros
+
+	if (compare < 0  && test_genotype.GetFitness() != 0) {
+		mod_matrix(cur_col,line_num) = 1;
+		num_inst[cur_col]++;
+		num_task[line_num]++;
+	}
+	cur_col++;
+      }
+
+      // Reset the mod_genome back to the original sequence.
+      mod_genome[line_num].SetOp(cur_inst);
+    } // end of genotype-phenotype mapping for a single organism
+    
+    for (int i = 0; i < num_cols; i++) {if (num_inst[i] != 0) total_task++;}
+    for (int i = 0; i < max_line; i++) {if (num_task[i] != 0) total_inst++;}
+    for (int i = 0; i < num_cols; i++) {total_all = total_all + num_inst[i];}
+
+    // Add the values to the av_ variables, used for calculating the average
+    // in order to weigh them by abundance, multiply everything by num_cpus
+
+    av_length = av_length + max_line*num_cpus;
+    av_task = av_task + total_task*num_cpus;
+    av_inst = av_inst + total_inst*num_cpus;
+    av_inst_len = av_inst_len + (double) total_inst*num_cpus/max_line;
+
+    if (total_task !=0)  av_site_task = av_site_task + num_cpus * (double) total_all/total_task; 
+    if (total_inst !=0)  av_task_site = av_task_site + num_cpus * (double) total_all/total_inst; 
+    if (total_inst !=0 && total_task !=0) {
+	av_t_s_norm = av_t_s_norm + num_cpus * (double) total_all/(total_inst*total_task); 
+    }
+
+    for (int i = 0; i < num_cols; i++) { 
+	if (num_inst[i] > 0) {
+		av_num_inst[i] = av_num_inst[i] + num_inst[i] * num_cpus;
+		org_task[i] = org_task[i] + num_cpus;   // count how many are actually doing the task
+	}
+    }	
+
+    // calculate average task overlap
+    // first construct num_task x num_task matrix with number of sites overlapping
+    for (int i = 0; i < max_line; i++) {
+        for (int j = 0; j < num_cols; j++) {
+           for (int k = j; k < num_cols; k++) {
+               if (mod_matrix(j,i)>0 && mod_matrix(k,i)>0) {
+                       task_overlap(j,k)++;
+                       if (j!=k) task_overlap(k,j)++;
+               }               
+           }
+       }
+    }
+
+    // go though the task_overlap matrix, add and average everything up. 
+    if (total_task > 1) {
+       for (int i = 0; i < num_cols; i++) {
+          double overlap_per_task = 0;                 
+          for (int j = 0; j < num_cols; j++) {
+               if (i!=j) {overlap_per_task = overlap_per_task + task_overlap(i,j);}
+          }
+          if (task_overlap(i,i) !=0){
+              sum_task_overlap = sum_task_overlap + overlap_per_task / (task_overlap(i,i) * (total_task-1));   
+          }
+       }
+    }
+
+    // now, divide that by number of tasks done and add to the grand sum, weigthed by num_cpus 
+    if (total_task!=0) {
+       av_task_overlap = av_task_overlap + num_cpus * (double) sum_task_overlap/total_task ;
+}
+    // calculate the first/last postion of a task, the task "spread"
+    // starting from the top look for the fist command that matters for a task
+
+    for (int i = 0; i < num_cols; i++) { 
+       int j = 0; 
+       while (j < max_line) {
+            if (mod_matrix(i,j) > 0 && task_length[i] == 0 ) {
+               task_length[i] = j;
+               break;
+            }
+            j++;
+       }
+     }
+
+    // starting frm the bottom look for the last command that matters for a task
+    // and substract it from the first to get the task length
+    // add one in order to account for both the beginning and the end instruction
+    for (int i = 0; i < num_cols; i++) { 
+       int j = max_line - 1; 
+       while (j > -1) {
+            if (mod_matrix(i,j) > 0) {
+               task_length[i] = j - task_length[i] + 1;
+               break;
+            }
+            j--;
+       }
+    }
+   // add the task lengths to the average for the batch
+   // weigthed by the number of cpus for that genotype 
+   for (int i = 0; i < num_cols; i++) { 
+       av_task_length[i] = av_task_length[i] +  num_cpus * task_length[i];
+   }
+
+    // calculate the Standard Deviation in the mean position of the task
+    for (int i = 0; i < num_cols; i++) { 
+	for (int j = 0; j < max_line; j++) { 
+		if (mod_matrix(i,j)>0) sum[i] = sum[i] + j;
+	}		
+    }
+
+    double temp = 0;
+    for (int i = 0; i < num_cols; i++) {
+	if (num_inst[i]>1) { 
+		double av_sum = sum[i]/num_inst[i];
+		for (int j = 0; j < max_line; j++) {
+			if (mod_matrix(i,j)>0) temp = (av_sum - j)*(av_sum - j);
+		}
+		std_task_position[i] = std_task_position[i] + sqrt(temp/(num_inst[i]-1))*num_cpus;
+	} 
+    } 
+
+    for (int i = 0; i < max_line; i++) { inst_task[num_task[i]]++ ;}
+    for (int i = 0; i < num_cols+1; i++) { av_inst_task[i] = av_inst_task[i] + inst_task[i] * num_cpus;}
+
+   }
+  }  // this is the end of the loop going though all the organisms
+
+ // make sure there are some organisms doing task in this batch
+ // if not, return all zeros
+
+ if (num_orgs != 0) { 
+    fp << (double) av_length/num_orgs  << " ";  	// 1: average length
+    fp << (double) av_task/num_orgs << " ";		// 2: av. number of tasks done
+    fp << (double) av_inst/num_orgs << " ";		// 3: av. number of sites used for tasks
+    fp << (double) av_inst_len/num_orgs << " ";		// 4: proportion of sites used for tasks
+    fp << (double) av_task_site/num_orgs << " ";	// 5: av. number of tasks per site
+    fp << (double) av_site_task/num_orgs << " ";	// 6: av. number of sites per task
+    fp << (double) av_t_s_norm/num_orgs << " ";		// 7: av. number of tasks per site per task
+    fp << (double) 1 - av_task_overlap/num_orgs << " ";        // 8: av. proportion of a task that DOESN'T overlap
+    for (int i = 0; i < num_cols; i++) {
+	if (org_task[i] > 0) fp << std_task_position[i]/org_task[i]  << " ";
+        else fp << 0 << " ";
+    }
+    for (int i = 0; i < num_cols; i++) {
+        if (org_task[i] > 0) fp << (double) av_num_inst[i]/org_task[i]  << " ";
+        else fp << 0 << " ";
+    }
+    for (int i = 0; i < num_cols+1; i++) { fp << (double) av_inst_task[i]/num_orgs  << " ";}
+    for (int i = 0; i < num_cols; i++) { fp << (double) av_task_length[i]/num_orgs  << " ";}
+    fp << endl;
+    }
+
+ else {
+    for (int i = 0; i < 8+4*num_cols+1; i++) {fp << "0 ";}
+    fp << endl;
+ }
+}
+
+
+void cAnalyze::CommandMapMutations(cString cur_string)
+{
+  cout << "Constructing genome mutations maps..." << endl;
+
+  // Load in the variables...
+  cString directory = PopDirectory(cur_string, "mutations/");
+  int file_type = FILE_TYPE_TEXT;
+
+  cStringList arg_list(cur_string);
+
+  // Check for some command specific variables.
+  if (arg_list.PopString("text") != "") file_type = FILE_TYPE_TEXT;
+  if (arg_list.PopString("html") != "") file_type = FILE_TYPE_HTML;
+
+  // Give some information in verbose mode.
+  if (verbose == true) {
+    cout << "  outputing as ";
+    if (file_type == FILE_TYPE_TEXT) cout << "text files." << endl;
+    else cout << "HTML files." << endl;
+  }
+
+
+  ///////////////////////////////////////////////////////
+  // Loop through all of the genotypes in this batch...
+
+  tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+  cAnalyzeGenotype * genotype = NULL;
+  while ((genotype = batch_it.Next()) != NULL) {
+    if (verbose == true) {
+      cout << "  Creating mutation map for " << genotype->GetName() << endl;
+    }
+
+    // Construct this filename...
+    cString filename;
+    if (file_type == FILE_TYPE_TEXT) {
+      filename.Set("%smut_map.%s.dat", directory(), genotype->GetName()());
+    } else {   //  if (file_type == FILE_TYPE_HTML) {
+      filename.Set("%smut_map.%s.html", directory(), genotype->GetName()());
+    }
+    ofstream fp(filename());
+
+    // Calculate the stats for the genotype we're working with...
+    genotype->Recalculate();
+    const double base_fitness = genotype->GetFitness();
+    const int num_insts = inst_set.GetSize();
+
+    // Headers...
+    if (file_type == FILE_TYPE_TEXT) {
+      fp << "# 1: Genome instruction ID (pre-mutation)" << endl;
+      for (int i = 0; i < num_insts; i++) {
+	fp << "# " << i+1 <<": Fit if mutated to '"
+	   << inst_set.GetName(i) << "'" << endl;
+      }
+      fp << "# " << num_insts + 2 << ": Knockout" << endl;
+      fp << "# " << num_insts + 3 << ": Fraction Lethal" << endl;
+      fp << "# " << num_insts + 4 << ": Fraction Detremental" << endl;
+      fp << "# " << num_insts + 5 << ": Fraction Neutral" << endl;
+      fp << "# " << num_insts + 6 << ": Fraction Beneficial" << endl;
+      fp << "# " << num_insts + 7 << ": Average Fitness" << endl;
+      fp << "# " << num_insts + 8 << ": Expected Entropy" << endl;
+      fp << "# " << num_insts + 9 << ": Original Instruction Name" << endl;
+      fp << endl;
+
+    } else { // if (file_type == FILE_TYPE_HTML) {
+      // Mark file as html
+      fp << "<html>" << endl;
+
+      // Setup the body...
+      fp << "<body bgcolor=\"#FFFFFF\"" << endl
+	 << " text=\"#000000\"" << endl
+	 << " link=\"#0000AA\"" << endl
+	 << " alink=\"#0000FF\"" << endl
+	 << " vlink=\"#000044\">" << endl
+	 << endl
+	 << "<h1 align=center>Mutation Map for Run " << batch[cur_batch].Name()
+	 << ", ID " << genotype->GetID() << "</h1>" << endl
+	 << "<center>" << endl
+	 << endl;
+
+      // The main chart...
+      fp << "<table border=1 cellpadding=2>" << endl;
+
+      // The headings...///
+      fp << "<tr><th>Genome ";
+      for (int i = 0; i < num_insts; i++) {
+	fp << "<th>" << inst_set.GetName(i) << " ";
+      }
+      fp << "<th>Knockout ";
+      fp << "<th>Frac. Lethal ";
+      fp << "<th>Frac. Detremental ";
+      fp << "<th>Frac. Neutral ";
+      fp << "<th>Frac. Beneficial ";
+      fp << "<th>Ave. Fitness ";
+      fp << "<th>Expected Entropy ";
+      fp << "</tr>" << endl << endl;
+    }
+
+    const int max_line = genotype->GetLength();
+    const cGenome & base_genome = genotype->GetGenome();
+    cGenome mod_genome(base_genome);
+
+    // Keep track of the number of mutations in each category...
+    int total_dead = 0, total_neg = 0, total_neut = 0, total_pos = 0;
+    double total_fitness = 0.0;
+    tArray<double> col_fitness(num_insts + 1);
+    col_fitness.SetAll(0.0);
+
+    // Build an empty instruction into the an instruction library.
+    cInstSet map_inst_set(inst_set);
+    // Locate instruction corresponding to "NULL" in the instruction library.
+    {
+      const cInstruction inst_lib_null_inst = map_inst_set.GetInstLib()->GetInst("NULL");
+      if (inst_lib_null_inst == map_inst_set.GetInstLib()->GetInstError()){
+        cout << "<cAnalyze::CommandMapMutations> got error:" << endl;
+        cout << " --- instruction \"NULL\" isn't in the instruction library;" << endl;
+        cout << " --- get somebody to map a function to \"NULL\" in the library." << endl;
+        cout << " --- (probably to class method \"cHardware-of-some-type::initInstLib\"" << endl;
+        cout << " --- in file named \"cpu/hardware-of-some-type.cc\".)" << endl;
+        cout << " --- bailing-out." << endl;
+        exit(1);
+      }
+      // Add mapping to located instruction. 
+      map_inst_set.Add2(inst_lib_null_inst.GetOp());
+    }
+    const cInstruction null_inst = map_inst_set.GetInst("NULL");
+
+    cString color_string;  // For coloring cells...
+
+    // Loop through all the lines of code, testing all mutations...
+    for (int line_num = 0; line_num < max_line; line_num++) {
+      int cur_inst = base_genome[line_num].GetOp();
+      char cur_symbol = base_genome[line_num].GetSymbol();
+      int row_dead = 0, row_neg = 0, row_neut = 0, row_pos = 0;
+      double row_fitness = 0.0;
+
+      // Column 1... the original instruction in the geneome.
+      if (file_type == FILE_TYPE_HTML) {
+	fp << "<tr><td align=right>" << inst_set.GetName(cur_inst)
+	   << " (" << cur_symbol << ") ";
+      } else {
+	fp << cur_inst << " ";
+      }
+      
+      // Columns 2 to D+1 (the possible mutations)
+      for (int mod_inst = 0; mod_inst < num_insts; mod_inst++) 
+      {
+        if (mod_inst == cur_inst) {
+          if (file_type == FILE_TYPE_HTML) {
+            color_string = "#FFFFFF";
+            fp << "<th bgcolor=\"" << color_string << "\">";
+          }
+        }
+        else {
+          mod_genome[line_num].SetOp(mod_inst);
+          cAnalyzeGenotype test_genotype(mod_genome, inst_set);
+          test_genotype.Recalculate();
+          const double test_fitness = test_genotype.GetFitness() / base_fitness;
+          row_fitness += test_fitness;
+          total_fitness += test_fitness;
+          col_fitness[mod_inst] += test_fitness;
+
+          // Categorize this mutation...
+          if (test_fitness == 1.0) {           // Neutral Mutation...
+            row_neut++;
+            total_neut++;
+            if (file_type == FILE_TYPE_HTML) color_string = "#FFFFFF";
+          } else if (test_fitness == 0.0) {    // Lethal Mutation...
+            row_dead++;
+            total_dead++;
+            if (file_type == FILE_TYPE_HTML) color_string = "#FF0000";
+          } else if (test_fitness < 1.0) {     // Detrimental Mutation...
+            row_neg++;
+            total_neg++;
+            if (file_type == FILE_TYPE_HTML) color_string = "#FFFF00";
+          } else {                             // Beneficial Mutation...
+            row_pos++;
+            total_pos++;
+            if (file_type == FILE_TYPE_HTML) color_string = "#00FF00";
+          }
+
+          // Write out this cell...
+          if (file_type == FILE_TYPE_HTML) {
+            fp << "<th bgcolor=\"" << color_string << "\">";
+          }
+          fp << test_fitness << " ";
+        }
+      }
+
+      // Column: Knockout
+      mod_genome[line_num] = null_inst;
+      cAnalyzeGenotype test_genotype(mod_genome, map_inst_set);
+      test_genotype.Recalculate();
+      const double test_fitness = test_genotype.GetFitness() / base_fitness;
+      col_fitness[num_insts] += test_fitness;
+
+      // Categorize this mutation if its in HTML mode (color only)...
+      if (file_type == FILE_TYPE_HTML) {
+        if (test_fitness == 1.0) color_string = "#FFFFFF";
+        else if (test_fitness == 0.0) color_string = "#FF0000";
+        else if (test_fitness < 1.0) color_string = "#FFFF00";
+        else color_string = "#00FF00";
+
+        fp << "<th bgcolor=\"" << color_string << "\">";
+      }
+
+      fp << test_fitness << " ";
+
+      // Fraction Columns...
+      if (file_type == FILE_TYPE_HTML) fp << "<th bgcolor=\"#FF0000\">";
+      fp << (double) row_dead / (double) (num_insts-1) << " ";
+
+      if (file_type == FILE_TYPE_HTML) fp << "<th bgcolor=\"#FFFF00\">";
+      fp << (double) row_neg / (double) (num_insts-1) << " ";
+
+      if (file_type == FILE_TYPE_HTML) fp << "<th bgcolor=\"#FFFFFF\">";
+      fp << (double) row_neut / (double) (num_insts-1) << " ";
+
+      if (file_type == FILE_TYPE_HTML) fp << "<th bgcolor=\"#00FF00\">";
+      fp << (double) row_pos / (double) (num_insts-1) << " ";
+
+
+      // Column: Average Fitness
+      if (file_type == FILE_TYPE_HTML) fp << "<th>";
+      fp << row_fitness / (double) (num_insts-1) << " ";
+
+      // Column: Expected Entropy  @CAO Implement!
+      if (file_type == FILE_TYPE_HTML) fp << "<th>";
+      fp << 0.0 << " ";
+      
+      // End this row...
+      if (file_type == FILE_TYPE_HTML) fp << "</tr>";
+      fp << endl;
+
+      // Reset the mod_genome back to the original sequence.
+      mod_genome[line_num].SetOp(cur_inst);
+    }
+
+
+    // Construct the final line of the table with all totals...
+    if (file_type == FILE_TYPE_HTML) {
+      fp << "<tr><th>Totals";
+      
+      // Instructions + Knockout
+      for (int i = 0; i <= num_insts; i++) {
+	fp << "<th>" << col_fitness[i] / max_line << " ";
+      }
+
+      int total_tests = max_line * (num_insts-1);
+      fp << "<th>" << (double) total_dead / (double) total_tests << " ";
+      fp << "<th>" << (double) total_neg / (double) total_tests << " ";
+      fp << "<th>" << (double) total_neut / (double) total_tests << " ";
+      fp << "<th>" << (double) total_pos / (double) total_tests << " ";
+      fp << "<th>" << total_fitness / (double) total_tests << " ";
+      fp << "<th>" << 0.0 << " ";
+
+
+      // And close everything up...
+      fp << "</table>" << endl
+	 << "</center>" << endl;
+    }
+
+  }
+}
+
+
+void cAnalyze::CommandHamming(cString cur_string)
+{
+  cString filename("hamming.dat");
+  if (cur_string.GetSize() != 0) filename = cur_string.PopWord();
+
+  int batch1 = PopBatch(cur_string.PopWord());
+  int batch2 = PopBatch(cur_string.PopWord());
+
+  // We want batch2 to be the larger one for efficiency...
+  if (batch[batch1].List().GetSize() > batch[batch2].List().GetSize()) {
+    int tmp = batch1;  batch1 = batch2;  batch2 = tmp;
+  }
+
+  if (verbose == false) {
+    cout << "Calculating Hamming Distance... ";
+    cout.flush();
+  } else {
+    cout << "Calculating Hamming Distance between batches "
+	 << batch1 << " and " << batch2 << endl;
+    cout.flush();
+  }
+
+  // Setup some variables;
+  cAnalyzeGenotype * genotype1 = NULL;
+  cAnalyzeGenotype * genotype2 = NULL;
+  int total_dist = 0;
+  int total_count = 0;
+
+  tListIterator<cAnalyzeGenotype> list1_it(batch[batch1].List());
+  tListIterator<cAnalyzeGenotype> list2_it(batch[batch2].List());
+
+  while ((genotype1 = list1_it.Next()) != NULL) {
+    list2_it.Reset();
+    while ((genotype2 = list2_it.Next()) != NULL) {
+      // Determine the counts...
+      const int count1 = genotype1->GetNumCPUs();
+      const int count2 = genotype2->GetNumCPUs();
+      const int num_pairs = (genotype1 == genotype2) ?
+	((count1 - 1) * (count2 - 1)) : (count1 * count2);
+      if (num_pairs == 0) continue;
+
+      // And do the tests...
+      const int dist =
+	cGenomeUtil::FindHammingDistance(genotype1->GetGenome(),
+					 genotype2->GetGenome());
+      total_dist += dist * num_pairs;
+      total_count += num_pairs;
+    }
+  }
+
+
+  // Calculate the final answer
+  double ave_dist = (double) total_dist / (double) total_count;
+  cout << " ave distance = " << ave_dist << endl;
+
+  cDataFile & df = data_file_manager.Get(filename);
+
+  df.WriteComment( "Hamming distance information" );
+  df.WriteTimeStamp();  
+
+  df.Write(batch[batch1].Name(), "Name of First Batch");
+  df.Write(batch[batch2].Name(), "Name of Second Batch");
+  df.Write(ave_dist,             "Average Hamming Distance");
+  df.Write(total_count,          "Total Pairs Test");
+  df.Endl();
+}
+
+void cAnalyze::CommandLevenstein(cString cur_string)
+{
+  cString filename("lev.dat");
+  if (cur_string.GetSize() != 0) filename = cur_string.PopWord();
+
+  int batch1 = PopBatch(cur_string.PopWord());
+  int batch2 = PopBatch(cur_string.PopWord());
+
+  // We want batch2 to be the larger one for efficiency...
+  if (batch[batch1].List().GetSize() > batch[batch2].List().GetSize()) {
+    int tmp = batch1;  batch1 = batch2;  batch2 = tmp;
+  }
+
+  if (verbose == false) {
+    cout << "Calculating Levenstein Distance... ";
+    cout.flush();
+  } else {
+    cout << "Calculating Levenstein Distance between batch "
+	 << batch1 << " and " << batch2 << endl;
+    cout.flush();
+  }
+
+  // Setup some variables;
+  cAnalyzeGenotype * genotype1 = NULL;
+  cAnalyzeGenotype * genotype2 = NULL;
+  int total_dist = 0;
+  int total_count = 0;
+
+  tListIterator<cAnalyzeGenotype> list1_it(batch[batch1].List());
+  tListIterator<cAnalyzeGenotype> list2_it(batch[batch2].List());
+
+  // Loop through all of the genotypes in each batch...
+  while ((genotype1 = list1_it.Next()) != NULL) {
+    list2_it.Reset();
+    while ((genotype2 = list2_it.Next()) != NULL) {
+      // Determine the counts...
+      const int count1 = genotype1->GetNumCPUs();
+      const int count2 = genotype2->GetNumCPUs();
+      const int num_pairs = (genotype1 == genotype2) ?
+	((count1 - 1) * (count2 - 1)) : (count1 * count2);
+      if (num_pairs == 0) continue;
+
+      // And do the tests...
+      const int dist = cGenomeUtil::FindEditDistance(genotype1->GetGenome(),
+						     genotype2->GetGenome());
+      total_dist += dist * num_pairs;
+      total_count += num_pairs;
+    }
+  }
+
+  // Calculate the final answer
+  double ave_dist = (double) total_dist / (double) total_count;
+  cout << " ave distance = " << ave_dist << endl;
+
+  cDataFile & df = data_file_manager.Get(filename);
+
+  df.WriteComment( "Levenstein distance information" );
+  df.WriteTimeStamp();  
+
+  df.Write(batch[batch1].Name(), "Name of First Batch");
+  df.Write(batch[batch2].Name(), "Name of Second Batch");
+  df.Write(ave_dist,             "Average Levenstein Distance");
+  df.Write(total_count,          "Total Pairs Test");
+  df.Endl();
+}
+
+void cAnalyze::CommandSpecies(cString cur_string)
+{
+  cString filename("species.dat");
+  if (cur_string.GetSize() != 0) filename = cur_string.PopWord();
+
+  int batch1 = PopBatch(cur_string.PopWord());
+  int batch2 = PopBatch(cur_string.PopWord());
+
+  // We want batch2 to be the larger one for efficiency...
+  if (batch[batch1].List().GetSize() > batch[batch2].List().GetSize()) {
+    int tmp = batch1;  batch1 = batch2;  batch2 = tmp;
+  }
+
+  if (verbose == false) cout << "Calculating Species Distance... " << endl;
+  else cout << "Calculating Species Distance between batch "
+	    << batch1 << " and " << batch2 << endl;
+
+  // Setup some variables;
+  cAnalyzeGenotype * genotype1 = NULL;
+  cAnalyzeGenotype * genotype2 = NULL;
+  int total_dist = 0;
+  int total_count = 0;
+  int fail_count = 0;
+
+  tListIterator<cAnalyzeGenotype> list1_it(batch[batch1].List());
+  tListIterator<cAnalyzeGenotype> list2_it(batch[batch2].List());
+
+  // Loop through all of the genotypes in each batch...
+  while ((genotype1 = list1_it.Next()) != NULL) {
+    cSpecies species(genotype1->GetGenome(), -1);
+    list2_it.Reset();
+    while ((genotype2 = list2_it.Next()) != NULL) {
+      // Determine the counts...
+      const int count1 = genotype1->GetNumCPUs();
+      const int count2 = genotype2->GetNumCPUs();
+      const int num_pairs = (genotype1 == genotype2) ?
+	((count1 - 1) * (count2 - 1)) : (count1 * count2);
+      if (num_pairs == 0) continue;
+
+      // And do the tests...
+      const int dist = (genotype1 == genotype2) ? 0 :
+	species.Compare(genotype2->GetGenome());
+      if (dist >= 0) {
+	total_dist += dist * num_pairs;
+	total_count += num_pairs;
+      } else {
+	fail_count += num_pairs;
+      }
+    }
+  }
+
+  // Calculate the final answer
+  double ave_dist = (double) total_dist / (double) total_count;
+  cout << "  ave distance = " << ave_dist
+       << " in " << total_count
+       << " tests, with " << fail_count
+       << " additional failures."  << endl;
+
+  cDataFile & df = data_file_manager.Get(filename);
+
+  df.WriteComment( "Species information" );
+  df.WriteTimeStamp();  
+
+  df.Write(batch[batch1].Name(), "Name of First Batch");
+  df.Write(batch[batch2].Name(), "Name of Second Batch");
+  df.Write(ave_dist,             "Average Species Distance");
+  df.Write(total_count,          "Total Legal Pairs");
+  df.Write(fail_count,           "Total Failed Pairs");
+  df.Endl();
+}
+
+void cAnalyze::CommandAlign(cString cur_string)
+{
+  // Align does not need any args yet.
+  (void) cur_string;
+
+  cout << "Aligning sequences..." << endl;
+
+  if (batch[cur_batch].IsLineage() == false && verbose == true) {
+    cerr << "  Warning: sequences may not be a consecutive lineage."
+	 << endl;
+  }
+
+  // Create an array of all the sequences we need to align.
+  tList<cAnalyzeGenotype> & glist = batch[cur_batch].List();
+  tListIterator<cAnalyzeGenotype> batch_it(glist);
+  const int num_sequences = glist.GetSize();
+  cString * sequences = new cString[num_sequences];
+
+  // Move through each sequence an update it.
+  batch_it.Reset();
+  cString diff_info;
+  for (int i = 0; i < num_sequences; i++) {
+    sequences[i] = batch_it.Next()->GetGenome().AsString();
+    if (i == 0) continue;
+    // Track of the number of insertions and deletions to shift properly.
+    int num_ins = 0;
+    int num_del = 0;
+
+    // Compare each string to the previous.
+    cStringUtil::EditDistance(sequences[i], sequences[i-1], diff_info, '_');
+    while (diff_info.GetSize() != 0) {
+      cString cur_mut = diff_info.Pop(',');
+      const char mut_type = cur_mut[0];
+      cur_mut.ClipFront(1); cur_mut.ClipEnd(1);
+      int position = cur_mut.AsInt();
+
+      // Nothing to do with Mutations
+      if (mut_type == 'M') continue;
+
+      // Handle insertions...
+      if (mut_type == 'I') {
+	// Loop back and insert an '_' into all previous sequences.
+	for (int j = 0; j < i; j++) {
+	  sequences[j].Insert('_', position + num_del);
+	}
+	num_ins++;
+      }
+
+      // Handle Deletions...
+      else if (mut_type == 'D') {
+	// Insert '_' into the current sequence at the point of deletions.
+	sequences[i].Insert("_", position + num_ins);
+	num_del++;
+      }
+
+    }
+  }
+
+  batch_it.Reset();
+  for (int i = 0; i < num_sequences; i++) {
+    batch_it.Next()->SetAlignedSequence(sequences[i]);
+  }
+
+  // Cleanup
+  delete [] sequences;
+
+  // Adjust the flags on this batch
+  // batch[cur_batch].SetLineage(false);
+  batch[cur_batch].SetAligned(true);
+}
+
+
+void cAnalyze::WriteClone(cString cur_string)
+{
+  // Load in the variables...
+  cString filename("clone.dat");
+  int num_cells = -1;
+  if (cur_string.GetSize() != 0) filename = cur_string.PopWord();
+  if (cur_string.GetSize() != 0) num_cells = cur_string.PopWord().AsInt();
+  
+
+  ofstream & fp = data_file_manager.GetOFStream(filename);
+
+  // Start up again at update zero...
+  fp << "0 ";
+
+  // Setup the genebank sizes of lists to all be zero.
+  fp << MAX_CREATURE_SIZE << " ";
+  for (int i = 0; i < MAX_CREATURE_SIZE; i++) {
+    fp << "0 ";
+  }
+
+  // Save the individual genotypes
+  fp << batch[cur_batch].List().GetSize() << " ";
+  
+  int org_count = 0;
+  tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+  cAnalyzeGenotype * genotype = NULL;
+  while ((genotype = batch_it.Next()) != NULL) {
+    org_count += genotype->GetNumCPUs();
+    const int length = genotype->GetLength();
+    const cGenome & genome = genotype->GetGenome();
+
+    fp << genotype->GetID() << " "
+       << length << " ";
+
+    for (int i = 0; i < length; i++) {
+      fp << genome[i].GetOp() << " ";
+    }
+  }
+
+  // Write out the current state of the grid.
+  
+  if (num_cells == 0) num_cells = org_count;
+  fp << num_cells << " ";
+
+  batch_it.Reset();
+  while ((genotype = batch_it.Next()) != NULL) {
+    for (int i = 0; i < genotype->GetNumCPUs(); i++) {
+      fp << genotype->GetID() << " ";
+    }
+  }
+
+  // Fill out the remainder of the grid with -1
+  for (int i = org_count; i < num_cells; i++) {
+    fp << "-1 ";
+  }
+}
+
+
+void cAnalyze::WriteInjectEvents(cString cur_string)
+{
+  // Load in the variables...
+  cString filename("clone.dat");
+  int start_cell = 0;
+  int lineage = 0;
+  if (cur_string.GetSize() != 0) filename = cur_string.PopWord();
+  if (cur_string.GetSize() != 0) start_cell = cur_string.PopWord().AsInt();
+  if (cur_string.GetSize() != 0) lineage = cur_string.PopWord().AsInt();
+  
+  ofstream & fp = data_file_manager.GetOFStream(filename);
+
+  int org_count = 0;
+  tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+  cAnalyzeGenotype * genotype = NULL;
+  while ((genotype = batch_it.Next()) != NULL) {
+    const int cur_count = genotype->GetNumCPUs();
+    org_count += cur_count;
+    const cGenome & genome = genotype->GetGenome();
+
+    fp << "u 0 inject_sequence "
+       << genome.AsString() << " "
+       << start_cell << " "
+       << start_cell + cur_count << " "
+       << genotype->GetMerit() << " "
+       << lineage << " "
+       << endl;
+    start_cell += cur_count;
+  }
+}
+
+
+void cAnalyze::AnalyzeMuts(cString cur_string)
+{
+  cout << "Analyzing Mutations" << endl;
+
+  // Make sure we have everything we need.
+  if (batch[cur_batch].IsAligned() == false) {
+    cout << "  ERROR: sequences not aligned." << endl;
+    return;
+  }
+
+  // Setup variables...
+  cString filename("analyze_muts.dat");
+  bool all_combos = false;
+  if (cur_string.GetSize() != 0) filename = cur_string.PopWord();
+  if (cur_string.GetSize() != 0) all_combos = cur_string.PopWord().AsInt();
+
+  tList<cAnalyzeGenotype> & gen_list = batch[cur_batch].List();
+  tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+
+  const int num_sequences = gen_list.GetSize();
+  const int sequence_length =
+    gen_list.GetFirst()->GetAlignedSequence().GetSize();
+  cString * sequences = new cString[num_sequences];
+  int * mut_count = new int[sequence_length];
+  for (int i = 0; i < sequence_length; i++) mut_count[i] = 0;
+
+  // Load in the sequences
+  batch_it.Reset();
+  int count = 0;
+  while (batch_it.Next() != NULL) {
+    sequences[count] = batch_it.Get()->GetAlignedSequence();
+    count++;
+  }
+
+  // Count the number of changes at each site...
+  for (int i = 1; i < num_sequences; i++) {       // For each pair...
+    cString & seq1 = sequences[i-1];
+    cString & seq2 = sequences[i];
+    for (int j = 0; j < sequence_length; j++) {   // For each site...
+      if (seq1[j] != seq2[j]) mut_count[j]++;
+    }
+  }
+
+  // Grab the two strings we're actively going to be working with.
+  cString & first_seq = sequences[0];
+  cString & last_seq = sequences[num_sequences - 1];
+
+  // Print out the header...
+  ofstream & fp = data_file_manager.GetOFStream(filename);
+  fp << "# " << sequences[0] << endl;
+  fp << "# " << sequences[num_sequences - 1] << endl;
+  fp << "# ";
+  for (int i = 0; i < sequence_length; i++) {
+    if (mut_count[i] == 0) fp << " ";
+    else if (mut_count[i] > 9) fp << "+";
+    else fp << mut_count[i];
+  }
+  fp << endl;
+  fp << "# ";
+  for (int i = 0; i < sequence_length; i++) {
+    if (first_seq[i] == last_seq[i]) fp << " ";
+    else fp << "^";
+  }
+  fp << endl << endl;
+
+  // Count the number of diffs between the two strings we're interested in.
+  const int total_diffs = cStringUtil::Distance(first_seq, last_seq);
+  if (verbose) cout << "  " << total_diffs << " mutations being tested."
+		    << endl;
+
+  // Locate each difference.
+  int * mut_positions = new int[total_diffs];
+  int cur_mut = 0;
+  for (int i = 0; i < first_seq.GetSize(); i++) {
+    if (first_seq[i] != last_seq[i]) {
+      mut_positions[cur_mut] = i;
+      cur_mut++;
+    }
+  }
+
+  // The number of mutations we need to deal with will tell us how much
+  // we can attempt to do. (@CAO should be able to overide defaults)
+  bool scan_combos = true;  // Scan all possible combos of mutations?
+  bool detail_muts = true;  // Collect detailed info on all mutations?
+  bool print_all = true;    // Print everything we collect without digestion?
+  if (total_diffs > 30) scan_combos = false;
+  if (total_diffs > 20) detail_muts = false;
+  if (total_diffs > 10) print_all = false;
+
+  // Start moving through the difference combinations...
+  if (scan_combos) {
+    const int total_combos = 1 << total_diffs;
+    cout << "  Scanning through " << total_combos << " combos." << endl;
+
+    double * total_fitness = new double[total_diffs + 1];
+    double * total_sqr_fitness = new double[total_diffs + 1];
+    double * max_fitness = new double[total_diffs + 1];
+    cString * max_sequence = new cString[total_diffs + 1];
+    int * test_count = new int[total_diffs + 1];
+    for (int i = 0; i <= total_diffs; i++) {
+      total_fitness[i] = 0.0;
+      total_sqr_fitness[i] = 0.0;
+      max_fitness[i] = 0.0;
+      test_count[i] = 0;
+    }
+
+    // Loop through all of the combos...
+    const int combo_step = total_combos / 79;
+    for (int combo_id = 0; combo_id < total_combos; combo_id++) {
+      if (combo_id % combo_step == 0) {
+	cout << '.';
+	cout.flush();
+      }
+      // Start at the first sequence and add needed changes...
+      cString test_sequence = first_seq;
+      int diff_count = 0;
+      for (int mut_id = 0; mut_id < total_diffs; mut_id++) {
+	if ((combo_id >> mut_id) & 1) {
+	  const int cur_pos = mut_positions[mut_id];
+	  test_sequence[cur_pos] = last_seq.GetData()[cur_pos];
+	  diff_count++;
+	}
+      }
+
+      // Determine the fitness of the current sequence...
+      cGenome test_genome(test_sequence);
+      cCPUTestInfo test_info;
+      test_info.TestThreads();
+      cTestCPU::TestGenome(test_info, test_genome);
+      const double fitness = test_info.GetGenotypeFitness();
+
+      //cAnalyzeGenotype test_genotype(test_sequence);
+      //test_genotype.Recalculate();
+      //const double fitness = test_genotype.GetFitness();
+
+      total_fitness[diff_count] += fitness;
+      total_sqr_fitness[diff_count] += fitness * fitness;
+      if (fitness > max_fitness[diff_count]) {
+	max_fitness[diff_count] = fitness;
+	max_sequence[diff_count] = test_sequence;
+//  	cout << endl
+//  	     << max_sequence[diff_count] << " "
+//  	     << test_info.GetGenotypeMerit() << " "
+//  	     << fitness << " "
+//  	     << combo_id << endl;
+      }
+      test_count[diff_count]++;
+    }
+
+    // Output the results...
+
+    for (int i = 0; i <= total_diffs; i++) {
+      cAnalyzeGenotype max_genotype(max_sequence[i], inst_set);
+      max_genotype.Recalculate();
+      fp << i                                         << " "  //  1
+	 << test_count[i]                             << " "  //  2
+	 << total_fitness[i] / (double) test_count[i] << " "  //  3
+	 << max_fitness[i]                            << " "  //  4
+	 << max_genotype.GetMerit()                   << " "  //  5
+	 << max_genotype.GetGestTime()                << " "  //  6
+	 << max_genotype.GetLength()                  << " "  //  7
+	 << max_genotype.GetCopyLength()              << " "  //  8
+	 << max_genotype.GetExeLength()               << " "; //  9
+      max_genotype.PrintTasks(fp, 3,12);
+      fp << max_sequence[i] << endl;
+    }
+
+    // Cleanup
+    delete [] total_fitness;
+    delete [] total_sqr_fitness;
+    delete [] max_fitness;
+    delete [] max_sequence;
+    delete [] test_count;
+  }
+  // If we can't scan through all combos, give wanring.
+  else {
+    cerr << "  Warning: too many mutations (" << total_diffs
+	 << ") to scan through combos." << endl;
+  }
+
+
+  // Cleanup...
+  delete [] sequences;
+  delete [] mut_count;
+  delete [] mut_positions;
+}
+
+void cAnalyze::AnalyzeInstructions(cString cur_string)
+{
+  if (verbose == true) {
+    cout << "Analyzing Instructions in batch " << cur_batch << endl;
+  }
+  else cout << "Analyzeing Instructions..." << endl;
+
+  // Load in the variables...
+  cString filename("inst_analyze.dat");
+  if (cur_string.GetSize() != 0) filename = cur_string.PopWord();
+  const int num_insts = inst_set.GetSize();
+
+  // Setup the file...
+  ofstream fp(filename);
+
+  // Determine the file type...
+  int file_type = FILE_TYPE_TEXT;
+  while (filename.Find('.') != -1) filename.Pop('.');
+  if (filename == "html") file_type = FILE_TYPE_HTML;
+
+  // If we're in HTML mode, setup the header...
+  if (file_type == FILE_TYPE_HTML) {
+    // Document header...
+    fp << "<html>" << endl
+       << "<body bgcolor=\"#FFFFFF\"" << endl
+       << " text=\"#000000\"" << endl
+       << " link=\"#0000AA\"" << endl
+       << " alink=\"#0000FF\"" << endl
+       << " vlink=\"#000044\">" << endl
+       << endl
+       << "<h1 align=center>Instruction Chart: "
+       << batch[cur_batch].Name() << endl
+       << "<br><br>" << endl
+       << endl;
+
+    // Instruction key...
+    const int num_cols = 6;
+    const int num_rows = ((num_insts - 1) / num_cols) + 1;
+    fp << "<table border=2 cellpadding=3>" << endl
+       << "<tr bgcolor=\"#AAAAFF\"><th colspan=6>Instruction Set Legend</tr>"
+       << endl;
+    for (int i = 0; i < num_rows; i++) {
+      fp << "<tr>";
+      for (int j = 0; j < num_cols; j++) {
+	const int inst_id = i + j * num_rows;
+	if (inst_id < num_insts) {
+	  cInstruction cur_inst(inst_id);
+	  fp << "<td><b>" << cur_inst.GetSymbol() << "</b> : "
+	     << inst_set.GetName(inst_id) << " ";
+	}
+	else {
+	  fp << "<td>&nbsp; ";
+	}
+      }
+      fp << "</tr>" << endl;
+    }
+    fp << "</table>" << endl
+       << "<br><br><br>" << endl;
+
+    // Main table header...
+    fp << "<center>" << endl
+       << "<table border=1 cellpadding=2>" << endl
+       << "<tr><th bgcolor=\"#AAAAFF\">Run # <th bgcolor=\"#AAAAFF\">Length"
+       << endl;
+    for (int i = 0; i < num_insts; i++) {
+      cInstruction cur_inst(i);
+      fp << "<th bgcolor=\"#AAAAFF\">" << cur_inst.GetSymbol() << " ";
+    }
+    fp << "</tr>" << endl;
+  }
+  else { // if (file_type == FILE_TYPE_TEXT) {
+    fp << "#RUN_NAME  LENGTH  ";
+    for (int i = 0; i < num_insts; i++) {
+      cInstruction cur_inst(i);
+      fp << cur_inst.GetSymbol() << ":" << inst_set.GetName(i) << " ";
+    }
+    fp << endl;
+  }
+
+  // Figure out how often we expect each instruction to appear...
+  const double exp_freq = 1.0 / (double) num_insts;
+  const double min_freq = exp_freq * 0.5;
+  const double max_freq = exp_freq * 2.0;
+
+  double total_length = 0.0;
+  tArray<double> total_freq(num_insts);
+  for (int i = 0; i < num_insts; i++) total_freq[i] = 0.0;
+
+  // Loop through all of the genotypes in this batch...
+  tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+  cAnalyzeGenotype * genotype = NULL;
+  while ((genotype = batch_it.Next()) != NULL) {
+    // Setup for counting...
+    tArray<int> inst_bin(num_insts);
+    for (int i = 0; i < num_insts; i++) inst_bin[i] = 0;
+
+    // Count it up!
+    const int genome_size = genotype->GetLength();
+    for (int i = 0; i < genome_size; i++) {
+      const int inst_id = genotype->GetGenome()[i].GetOp();
+      inst_bin[inst_id]++;
+    }
+
+    // Print it out...
+    if (file_type == FILE_TYPE_HTML) fp << "<tr><th>";
+    fp << genotype->GetName() << " ";
+    if (file_type == FILE_TYPE_HTML) fp << "<td align=center>";
+    total_length += genome_size;
+    fp << genome_size << " ";
+    for (int i = 0; i < num_insts; i++) {
+      const double inst_freq = ((double) inst_bin[i]) / (double) genome_size;
+      total_freq[i] += inst_freq;
+      if (file_type == FILE_TYPE_HTML) {
+	if (inst_freq == 0.0) fp << "<td bgcolor=\"FFAAAA\">";
+	else if (inst_freq < min_freq) fp << "<td bgcolor=\"FFFFAA\">";
+	else if (inst_freq < max_freq) fp << "<td bgcolor=\"AAAAFF\">";
+	else fp << "<td bgcolor=\"AAFFAA\">";
+      }
+      fp << cStringUtil::Stringf("%04.3f", inst_freq) << " ";
+    }
+    if (file_type == FILE_TYPE_HTML) fp << "</tr>";
+    fp << endl;
+  }
+
+  if (file_type == FILE_TYPE_HTML) {
+    int num_genomes = batch[cur_batch].List().GetSize();
+    fp << "<tr><th>Average <th>" << total_length / num_genomes << " ";
+    for (int i = 0; i < num_insts; i++) {
+      double inst_freq = total_freq[i] / num_genomes;
+      if (inst_freq == 0.0) fp << "<td bgcolor=\"FF0000\">";
+      else if (inst_freq < min_freq) fp << "<td bgcolor=\"FFFF00\">";
+      else if (inst_freq < max_freq) fp << "<td bgcolor=\"0000FF\">";
+      else fp << "<td bgcolor=\"00FF00\">";
+      fp << cStringUtil::Stringf("%04.3f", inst_freq) << " ";
+    }
+    fp << "</tr>" << endl
+       << "</table></center>" << endl;
+  }
+}
+
+void cAnalyze::AnalyzeBranching(cString cur_string)
+{
+  if (verbose == true) {
+    cout << "Analyzing branching patterns in batch " << cur_batch << endl;
+  }
+  else cout << "Analyzeing Branches..." << endl;
+
+  // Load in the variables...
+  cString filename("branch_analyze.dat");
+  if (cur_string.GetSize() != 0) filename = cur_string.PopWord();
+
+  // Setup the file...
+  ofstream fp(filename);
+  
+  // UNFINISHED!
+  // const int num_insts = inst_set.GetSize();
+}
+
+void cAnalyze::AnalyzeMutationTraceback(cString cur_string)
+{
+  if (verbose == true) {
+    cout << "Analyzing mutation traceback in batch " << cur_batch << endl;
+  }
+  else cout << "Analyzing mutation traceback..." << endl;
+
+  // This works best on lineages, so warn if we don't have one.
+  if (batch[cur_batch].IsLineage() == false && verbose == true) {
+    cerr << "  Warning: trying to traceback mutations outside of lineage."
+	 << endl;
+  }
+
+  if (batch[cur_batch].List().GetSize() == 0) {
+    cerr << "Error: Trying to traceback mutations with no genotypes in batch."
+	 << endl;
+    return;
+  }
+
+  // Make sure all genotypes are the same length.
+  int size = -1;
+  tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+  cAnalyzeGenotype * genotype = NULL;
+  while ((genotype = batch_it.Next()) != NULL) {
+    if (size == -1) size = genotype->GetLength();
+    if (size != genotype->GetLength()) {
+      cerr << "  Error: Trying to traceback mutations in genotypes of differing lengths." << endl;
+      cerr << "  Aborting." << endl;
+      return;
+    }
+  }
+
+  // Setup variables...
+  cString filename("analyze_traceback.dat");
+  if (cur_string.GetSize() != 0) filename = cur_string.PopWord();
+
+  // Setup a genome to store the previous values before mutations.
+  tArray<int> prev_inst(size);
+  prev_inst.SetAll(-1);  // -1 indicates never changed.
+
+  // Open the output file...
+  ofstream fp(filename);
+
+  // Loop through all of the genotypes again, testing mutation reversions.
+  cAnalyzeGenotype * prev_genotype = batch_it.Next();
+  while ((genotype = batch_it.Next()) != NULL) {
+    continue;
+    // Check to see if any sites have changed...
+    for (int i = 0; i < size; i++) {
+      if (genotype->GetGenome()[i] != prev_genotype->GetGenome()[i]) {
+	prev_inst[i] = prev_genotype->GetGenome()[i].GetOp();
+      }
+    }
+
+    // Next, determine the fraction of mutations that are currently adaptive.
+    int num_beneficial = 0;
+    int num_neutral = 0;
+    int num_detrimental = 0;
+    int num_static = 0;      // Sites that were never mutated.
+
+    cGenome test_genome = genotype->GetGenome();
+    cCPUTestInfo test_info;
+    cTestCPU::TestGenome(test_info, test_genome);
+    const double base_fitness = test_info.GetGenotypeFitness();
+    
+    for (int i = 0; i < size; i++) {
+      if (prev_inst[i] == -1) num_static++;
+      else {
+	test_genome[i].SetOp(prev_inst[i]);
+	cTestCPU::TestGenome(test_info, test_genome);
+	const double cur_fitness = test_info.GetGenotypeFitness();
+	if (cur_fitness > base_fitness) num_detrimental++;
+	else if (cur_fitness < base_fitness) num_beneficial++;
+	else num_neutral++;
+	test_genome[i] = genotype->GetGenome()[i];
+      }      
+    }
+
+    fp << genotype->GetDepth() << " "
+       << num_beneficial << " "
+       << num_neutral << " "
+       << num_detrimental << " "
+       << num_static << " "
+       << endl;
+
+    prev_genotype = genotype;
+  }
+}
+
+void cAnalyze::AnalyzeComplexity(cString cur_string)
+{
+  cout << "Analyzing genome complexity..." << endl;
+  
+  // Load in the variables...
+  double mut_rate = cur_string.PopWord().AsDouble();
+  cString directory = PopDirectory(cur_string, "complexity/");
+  
+    
+  ///////////////////////////////////////////////////////
+  // Loop through all of the genotypes in this batch...
+
+  tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+  cAnalyzeGenotype * genotype = NULL;
+
+  bool islineage = false;
+  cString lineage_filename;
+  ofstream lineage_fp;
+  if (batch[cur_batch].IsLineage() == true) {
+    lineage_filename.Set("%scomplexity.%s.dat", directory(), "lineage");
+    lineage_fp.open(lineage_filename);
+    islineage = true;
+  }
+  while ((genotype = batch_it.Next()) != NULL) {
+    if (verbose == true) {
+      cout << "  Analyzing complexity for " << genotype->GetName() << endl;
+    }
+    
+    // Construct this filename...
+    cString filename;
+    filename.Set("%s%s.complexity.dat", directory(), genotype->GetName()());
+    ofstream fp(filename());
+    
+    // Calculate the stats for the genotype we're working with ...
+    genotype->Recalculate();
+    const int num_insts = inst_set.GetSize();
+    
+    const int max_line = genotype->GetLength();
+    const cGenome & base_genome = genotype->GetGenome();
+    cGenome mod_genome(base_genome);
+
+    // Loop through all the lines of code, testing all mutations...
+    tArray<double> test_fitness(num_insts);
+    tArray<double> prob(num_insts);
+    for (int line_num = 0; line_num < max_line; line_num++) {
+      int cur_inst = base_genome[line_num].GetOp();
+      //char cur_symbol = base_genome[line_num].GetSymbol();
+      
+      // Column 1 ... the original instruction in the genome.
+      fp << cur_inst << " ";
+      
+      // Test fitness of each mutant.
+      for (int mod_inst = 0; mod_inst < num_insts; mod_inst++) {
+        mod_genome[line_num].SetOp(mod_inst);
+        cAnalyzeGenotype test_genotype(mod_genome, inst_set);
+        test_genotype.Recalculate();
+        test_fitness[mod_inst] = test_genotype.GetFitness();
+      }
+
+      // Ajust fitness
+      double cur_inst_fitness = test_fitness[cur_inst];
+      for (int mod_inst = 0; mod_inst < num_insts; mod_inst++) {
+	if (test_fitness[mod_inst] > cur_inst_fitness)
+	  test_fitness[mod_inst] = cur_inst_fitness;
+        test_fitness[mod_inst] = test_fitness[mod_inst] / cur_inst_fitness;
+      }
+      
+      // Calculate probabilities at mut-sel balance
+      double w_bar = 1;
+
+      while(1) {
+        double sum = 0.0;
+        for (int mod_inst = 0; mod_inst < num_insts; mod_inst ++) {
+          prob[mod_inst] = (mut_rate * w_bar) / (num_insts * (w_bar + test_fitness[mod_inst] * mut_rate - test_fitness[mod_inst]));
+          sum = sum + prob[mod_inst];
+        }
+        if ((sum-1.0)*(sum-1.0) <= 0.0001) 
+	  break;
+        else
+          w_bar = w_bar - 0.000001;
+      }
+
+      // Write probability
+      for (int mod_inst = 0; mod_inst < num_insts; mod_inst ++) {
+        fp << prob[mod_inst] << " ";
+      }
+
+      // Calculate complexity
+      double entropy = 0;
+      for (int i = 0; i < num_insts; i ++) {
+	entropy += prob[i] * log((double) 1.0/prob[i]) / log ((double) num_insts);
+      }
+      double complexity = 1 - entropy;
+      fp << complexity << endl;
+
+      if (islineage) {
+	lineage_fp << complexity << " ";
+      }
+
+      // Reset the mod_genome back to the original sequence.
+      mod_genome[line_num].SetOp(cur_inst);
+    }
+    fp.close();
+    lineage_fp << endl;
+  }
+  lineage_fp.close();
+        
+
+}
+
+void cAnalyze::AnalyzePopComplexity(cString cur_string)
+{
+  cout << "Analyzing population complexity ..." << endl;
+  
+  // Load in the variables...
+  cString directory = PopDirectory(cur_string, "complexity/");
+  cString file = cur_string;
+
+  // Construct filename ...
+  cString filename;
+  filename.Set("%spop%s.complexity.dat", directory(), file());
+  ofstream fp(filename());
+
+  //////////////////////////////////////////////////////////
+  // Loop through all of the genotypes in this batch ...
+
+  tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+  cAnalyzeGenotype * genotype = NULL;
+
+  genotype = batch_it.Next();
+  if (genotype == NULL) return;
+  int seq_length = genotype->GetLength();
+  const int num_insts = inst_set.GetSize();
+  tMatrix<int> inst_stat(seq_length, num_insts);
+  int pop_size = 0;
+
+  // Initializing inst_stat ...
+  for (int line_num = 0; line_num < seq_length; line_num ++) 
+    for (int inst_num = 0; inst_num < num_insts; inst_num ++) 
+      inst_stat(line_num, inst_num) = 0;
+
+  while (genotype != NULL) {
+    pop_size ++;
+    const cGenome & base_genome = genotype->GetGenome();
+    if (genotype->GetLength() != seq_length) { 
+      cout << genotype->GetName() << " " << genotype->GetLength() << endl;
+      genotype = batch_it.Next();
+      continue;
+    }
+    for (int line_num = 0; line_num < seq_length; line_num ++) {
+      int cur_inst = base_genome[line_num].GetOp();
+      inst_stat(line_num, cur_inst) ++;
+    }
+    genotype = batch_it.Next();
+  }
+
+  // Calculate complexity
+  for (int line_num = 0; line_num < seq_length; line_num ++) {
+    double entropy = 0.0;
+    for (int inst_num = 0; inst_num < num_insts; inst_num ++) {
+      if (inst_stat(line_num, inst_num) == 0) continue;
+      float prob = (float) (inst_stat(line_num, inst_num)) / (float) (pop_size);
+      entropy += prob * log((double) 1.0/prob) / log((double) num_insts);
+    }
+    double complexity = 1 - entropy;
+    fp << complexity << " ";
+  };
+  fp << endl;
+  fp.close();
+  return;
+}
+
+
+void cAnalyze::EnvironmentSetup(cString cur_string)
+{
+  cout << "Running environment command: " << endl
+       << "  " << cur_string << endl;
+
+  cTestCPU::GetEnvironment()->LoadLine(cur_string);
+}
+
+
+void cAnalyze::CommandHelpfile(cString cur_string)
+{
+  cout << "Printing helpfiles in: " << cur_string << endl;
+
+  cHelpManager help_control;
+  if (verbose == true) help_control.SetVerbose();
+  while (cur_string.GetSize() > 0) {
+    help_control.LoadFile(cur_string.PopWord());
+  }
+
+  help_control.PrintHTML();
+}
+
+void cAnalyze::CommandDocfile(cString cur_string)
+{
+  cout << "Printing documentation files in: " << cur_string << endl;
+
+  cHelpManager help_control;
+  if (verbose == true) help_control.SetVerbose();
+  while (cur_string.GetSize() > 0) {
+    help_control.LoadFile(cur_string.PopWord());
+  }
+
+  help_control.PrintHTML();
+}
+
+
+
+//////////////// Control...
+
+void cAnalyze::VarSet(cString cur_string)
+{
+  cString var = cur_string.PopWord();
+
+  if (cur_string.GetSize() == 0) {
+    cerr << "Error: No variable provided in SET command" << endl;
+    return;
+  }
+
+  cString & cur_variable = GetVariable(var);
+  cur_variable = cur_string.PopWord();
+
+  if (verbose == true) {
+    cout << "Setting " << var << " to " << cur_variable << endl;
+  }
+}
+
+void cAnalyze::BatchSet(cString cur_string)
+{
+  int next_batch = 0;
+  if (cur_string.CountNumWords() > 0) {
+    next_batch = cur_string.PopWord().AsInt();
+  }
+  if (verbose) cout << "Setting current batch to " << next_batch << endl;
+  if (next_batch >= MAX_BATCHES) {
+    cerr << "  Error: max batches is " << MAX_BATCHES << endl;
+    exit(1);
+  } else {
+    cur_batch = next_batch;
+  }
+}
+
+void cAnalyze::BatchName(cString cur_string)
+{
+  if (cur_string.CountNumWords() == 0) {
+    if (verbose) cout << "  Warning: No name given in NAME_BATCH!" << endl;
+    return;
+  }
+
+  batch[cur_batch].Name() = cur_string.PopWord();
+}
+
+void cAnalyze::BatchTag(cString cur_string)
+{
+  if (cur_string.CountNumWords() == 0) {
+    if (verbose) cout << "  Warning: No tag given in TAG_BATCH!" << endl;
+    return;
+  }
+
+  if (verbose == true) {
+    cout << "Tagging batch " << cur_batch
+	 << " with tag '" << cur_string << "'" << endl;
+  }
+
+  tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+  cAnalyzeGenotype * genotype = NULL;
+  while ((genotype = batch_it.Next()) != NULL) {
+    genotype->SetTag(cur_string);
+  }
+
+}
+
+void cAnalyze::BatchPurge(cString cur_string)
+{
+  int batch_id = cur_batch;
+  if (cur_string.CountNumWords() > 0) batch_id = cur_string.PopWord().AsInt();
+
+  if (verbose) cout << "Purging batch " << batch_id << endl;
+
+  while (batch[batch_id].List().GetSize() > 0) {
+    delete batch[batch_id].List().Pop();
+  }
+
+  batch[batch_id].SetLineage(false);
+  batch[batch_id].SetAligned(false);
+}
+
+void cAnalyze::BatchDuplicate(cString cur_string)
+{
+  if (cur_string.GetSize() == 0) {
+    cerr << "Duplicate Error: Must include from ID!" << endl;
+    exit(1);
+  }
+  int batch_from = cur_string.PopWord().AsInt();
+
+  int batch_to = cur_batch;
+  if (cur_string.GetSize() > 0) batch_to = cur_string.PopWord().AsInt();
+
+  if (verbose == true) {
+    cout << "Duplicating from batch " << batch_from
+	 << " to batch " << batch_to << "." << endl;
+  }
+
+  tListIterator<cAnalyzeGenotype> batch_from_it(batch[batch_from].List());
+  cAnalyzeGenotype * genotype = NULL;
+  while ((genotype = batch_from_it.Next()) != NULL) {
+    cAnalyzeGenotype * new_genotype = new cAnalyzeGenotype(*genotype);
+    batch[batch_to].List().PushRear(new_genotype);
+  }
+
+  batch[batch_to].SetLineage(false);
+  batch[batch_to].SetAligned(false);
+}
+
+void cAnalyze::BatchRecalculate(cString cur_string)
+{
+  // No args needed...
+  (void) cur_string;
+
+  if (verbose == true) {
+    cout << "Running batch " << cur_batch << " through test CPUs..." << endl;
+  } else cout << "Running through test CPUs..." << endl;
+
+  if (verbose == true && batch[cur_batch].IsLineage() == false) {
+    cerr << "  Warning: batch may not be a linege; "
+	 << "parent and ancestor distances may not be correct" << endl;
+  }
+
+  tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+  cAnalyzeGenotype * genotype = NULL;
+  cAnalyzeGenotype * last_genotype = NULL;
+  while ((genotype = batch_it.Next()) != NULL) {
+    if (last_genotype != NULL &&
+	genotype->GetParentID() == last_genotype->GetID()) {
+      genotype->Recalculate(last_genotype);
+    }
+    else genotype->Recalculate();
+    last_genotype = genotype;
+  }
+}
+
+void cAnalyze::BatchRename(cString cur_string)
+{
+  if (verbose == false) cout << "Renaming organisms..." << endl;
+  else cout << "Renaming organisms in batch " << cur_batch << endl;
+
+  // If a number is given with rename, start at that number...
+
+  int id_num = cur_string.PopWord().AsInt();
+  tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+  cAnalyzeGenotype * genotype = NULL;
+  while ((genotype = batch_it.Next()) != NULL) {
+    cString name = cStringUtil::Stringf("org-%d", id_num);
+    genotype->SetID(id_num);
+    genotype->SetName(name);
+    id_num++;
+  }
+}
+
+void cAnalyze::PrintStatus(cString cur_string)
+{
+  // No Args needed...
+  (void) cur_string;
+
+  cout << "Status Report:" << endl;
+  for (int i = 0; i < MAX_BATCHES; i++) {
+    if (i == cur_batch || batch[i].List().GetSize() > 0) {
+      cout << "  Batch " << i << " -- "
+	   << batch[i].List().GetSize() << " genotypes.";
+      if (i == cur_batch) cout << "  <current>";
+      if (batch[i].IsLineage() == true) cout << "  <lineage>";
+      if (batch[i].IsAligned() == true) cout << "  <aligned>";
+
+      cout << endl;
+    }
+  }
+}
+
+void cAnalyze::PrintDebug(cString cur_string)
+{
+  cerr << "Debug Args: " << cur_string << endl;
+}
+
+void cAnalyze::ToggleVerbose(cString cur_string)
+{
+  // No Args needed...
+  (void) cur_string;
+
+  if (verbose == false) {
+    cout << "Using verbose log messages..." << endl;
+    verbose = true;
+  } else {
+    cout << "Using non-verbose log messages..." << endl;
+    verbose = false;
+  }
+}
+
+void cAnalyze::IncludeFile(cString cur_string)
+{
+  while (cur_string.GetSize() > 0) {
+    cString filename = cur_string.PopWord();
+
+    cInitFile include_file(filename);
+    include_file.Load();
+    include_file.Compress();
+    include_file.Close();
+
+    tList<cAnalyzeCommand> include_list;
+    LoadCommandList(include_file, include_list);
+    ProcessCommands(include_list);
+  }
+}
+
+void cAnalyze::CommandSystem(cString cur_string)
+{
+  cout << "Running System Command: " << cur_string << endl;
+
+  system(cur_string());
+}
+
+void cAnalyze::CommandInteractive(cString cur_string)
+{
+  // No Args needed...
+  (void) cur_string;
+
+  cout << "Entering interactive mode..." << endl;
+
+  char text_input[2048];
+  while (true) {
+    cout << ">> ";
+    cout.flush();
+    cin.getline(text_input, 2048);
+    cString cur_input(text_input);
+    cString command = cur_input.PopWord();
+    command.ToUpper();
+
+    cAnalyzeCommand * cur_command;
+    cAnalyzeCommandDefBase * command_def = FindAnalyzeCommandDef(command);
+    if (command == "") {
+      // Don't worry about blank lines...
+      continue;
+    }
+    else if (command == "END" || command == "QUIT" || command == "EXIT") {
+      // We are done with interactive mode...
+      break;
+    }
+    else if (command_def != NULL && command_def->IsFlowCommand() == true) {
+      // This code has a body to it... fill it out!
+      cur_command = new cAnalyzeFlowCommand(command, cur_input);
+      InteractiveLoadCommandList(*(cur_command->GetCommandList()));
+    }
+    else {
+      // This is a normal command...
+      cur_command = new cAnalyzeCommand(command, cur_input);
+    }
+
+    cString args = cur_command->GetArgs();
+    PreProcessArgs(args);
+
+    cAnalyzeCommandDefBase * command_fun = FindAnalyzeCommandDef(command);
+
+    // First check for built-in functions...
+    if (command_fun != NULL) command_fun->Run(this, args, *cur_command);
+
+    // Then for user defined functions
+    else if (FunctionRun(command, args) == true) { }
+
+    // Otherwise, give an error.
+    else cerr << "Error: Unknown command '" << command << "'." << endl;
+  }
+}
+
+
+void cAnalyze::FunctionCreate(cString cur_string,
+			      tList<cAnalyzeCommand> & clist)
+{
+  int num_args = cur_string.CountNumWords();
+  if (num_args < 1) {
+    cerr << "Error: Must provide function name when creating function.";
+    exit(1);
+  }
+
+  cString fun_name = cur_string.PopWord();
+  fun_name.ToUpper();
+
+  if (FindAnalyzeCommandDef(fun_name) != NULL) {
+    cerr << "Error: Cannot create function '" << fun_name
+	 << "'; already exists." << endl;
+    exit(1);
+  }
+
+  if (verbose) cout << "Creating function: " << fun_name << endl;
+
+  // Create the new function...
+  cAnalyzeFunction * new_function = new cAnalyzeFunction(fun_name);
+  while (clist.GetSize() > 0) {
+    new_function->GetCommandList()->PushRear(clist.Pop());
+  }
+
+  // Save the function on the new list...
+  function_list.PushRear(new_function);
+}
+
+bool cAnalyze::FunctionRun(const cString & fun_name, cString args)
+{
+  if (verbose) {
+    cout << "Running function: " << fun_name << endl;
+    // << " with args: " << args << endl;
+  }
+
+  // Find the function we're about to run...
+  cAnalyzeFunction * found_function = NULL;
+  tListIterator<cAnalyzeFunction> function_it(function_list);
+  while (function_it.Next() != NULL) {
+    if (function_it.Get()->GetName() == fun_name) {
+      found_function = function_it.Get();
+      break;
+    }
+  }
+
+  // If we were unable to find the command we're looking for, return false.
+  if (found_function == NULL) return false;
+
+  // Back up the local variables
+  cString backup_arg_vars[10];
+  cString backup_local_vars[26];
+  for (int i = 0; i < 10; i++) backup_arg_vars[i] = arg_variables[i];
+  for (int i = 0; i < 26; i++) backup_local_vars[i] = local_variables[i];
+
+  // Set the arg variables to the passed-in args...
+  arg_variables[0] = fun_name;
+  for (int i = 1; i < 10; i++) arg_variables[i] = args.PopWord();
+  for (int i = 0; i < 26; i++) local_variables[i] = "";
+
+  ProcessCommands(*(found_function->GetCommandList()));
+
+  // Restore the local variables
+  for (int i = 0; i < 10; i++) arg_variables[i] = backup_arg_vars[i];
+  for (int i = 0; i < 26; i++) local_variables[i] = backup_local_vars[i];
+
+  return true;
+}
+
+
+int cAnalyze::BatchUtil_GetMaxLength(int batch_id)
+{
+  if (batch_id < 0) batch_id = cur_batch;
+
+  int max_length = 0;
+
+  tListIterator<cAnalyzeGenotype> batch_it(batch[batch_id].List());
+  cAnalyzeGenotype * genotype = NULL;
+  while ((genotype = batch_it.Next()) != NULL) {
+    if (genotype->GetLength() > max_length) max_length = genotype->GetLength();
+  }
+  
+  return max_length;
+}
+
+
+void cAnalyze::CommandForeach(cString cur_string,
+			      tList<cAnalyzeCommand> & clist)
+{
+  if (verbose) cout << "Initiating Foreach loop..." << endl;
+
+  cString var = cur_string.PopWord();
+  int num_args = cur_string.CountNumWords();
+
+  cString & cur_variable = GetVariable(var);
+
+  for (int i = 0; i < num_args; i++) {
+    cur_variable = cur_string.PopWord();
+
+    if (verbose == true) {
+      cout << "Foreach: setting " << var << " to " << cur_variable << endl;
+    }
+    ProcessCommands(clist);
+  }
+
+  if (verbose == true) {
+    cout << "Ending Foreach on " << var << endl;
+  }
+}
+
+
+void cAnalyze::CommandForRange(cString cur_string,
+			      tList<cAnalyzeCommand> & clist)
+{
+  if (verbose) cout << "Initiating FORRANGE loop..." << endl;
+
+  int num_args = cur_string.CountNumWords();
+  if (num_args < 3) {
+    cerr << "  Error: Must give variable, min and max with FORRANGE!"
+	 << endl;
+    exit(1);
+  }
+
+  cString var = cur_string.PopWord();
+  double min_val = cur_string.PopWord().AsDouble();
+  double max_val = cur_string.PopWord().AsDouble();
+  double step_val = 1.0;
+  if (num_args >=4 ) step_val = cur_string.PopWord().AsDouble();
+
+  cString & cur_variable = GetVariable(var);
+
+  // Seperate out all ints from not all ints...
+  if (min_val == (double) ((int) min_val) &&
+      max_val == (double) ((int) max_val) &&
+      step_val == (double) ((int) step_val)) {
+    for (int i = (int) min_val; i <= (int) max_val; i += (int) step_val) {
+      cur_variable.Set("%d", i);
+
+      if (verbose == true) {
+	cout << "FORRANGE: setting " << var << " to " << cur_variable << endl;
+      }
+      ProcessCommands(clist);
+    }
+  } else {
+    for (double i = min_val; i <= max_val; i += step_val) {
+      cur_variable.Set("%f", i);
+
+      if (verbose == true) {
+	cout << "FORRANGE: setting " << var << " to " << cur_variable << endl;
+      }
+      ProcessCommands(clist);
+    }
+  }
+
+  if (verbose == true) {
+    cout << "Ending FORRANGE on " << var << endl;
+  }
+}
+
+
+///////////////////  Private Methods ///////////////////////////
+
+cString cAnalyze::PopDirectory(cString & in_string,
+			       const cString & default_dir)
+{
+  // Determing the directory name
+  cString directory(default_dir);
+  if (in_string.GetSize() != 0) directory = in_string.PopWord();
+
+  // Make sure the directory ends in a slash.  If not, add one.
+  int last_pos = directory.GetSize() - 1;
+  if (directory[last_pos] != '/' && directory[last_pos] != '\\') {
+    directory += '/';
+  }
+
+  // Make sure the directory exists.
+  FILE *fp = fopen ( directory(), "r" );
+  if ( fp == 0 ){
+    if ( errno == ENOENT ){
+      cerr << "Directory '" << directory
+	   << "' does not exist.  Creating..." << endl;
+      if ( mkdir( directory(), (S_IRWXU|S_IRWXG|S_IRWXO) ) )
+	cerr << " Error creating '" << directory << "'" << endl;
+    }
+    else cerr << " Error opening '" << directory << "'" << endl;
+  }
+
+  return directory;
+}
+
+int cAnalyze::PopBatch(const cString & in_string)
+{
+  int batch = cur_batch;
+  if (in_string.GetSize() != 0 && in_string != "current") {
+    batch = in_string.AsInt();
+  }
+
+  return batch;
+}
+
+cAnalyzeGenotype * cAnalyze::PopGenotype(cString gen_desc, int batch_id)
+{
+  if (batch_id == -1) batch_id = cur_batch;
+  tList<cAnalyzeGenotype> & gen_list = batch[batch_id].List();
+  gen_desc.ToLower();
+
+  cAnalyzeGenotype * found_gen = NULL;
+  if (gen_desc == "num_cpus")
+    found_gen = gen_list.PopIntMax(&cAnalyzeGenotype::GetNumCPUs);
+  else if (gen_desc == "total_cpus")
+    found_gen = gen_list.PopIntMax(&cAnalyzeGenotype::GetTotalCPUs);
+  else if (gen_desc == "merit")
+    found_gen = gen_list.PopDoubleMax(&cAnalyzeGenotype::GetMerit);
+  else if (gen_desc == "fitness")
+    found_gen = gen_list.PopDoubleMax(&cAnalyzeGenotype::GetFitness);
+  else if (gen_desc.IsNumeric(0))
+    found_gen = gen_list.PopIntValue(&cAnalyzeGenotype::GetID,
+				     gen_desc.AsInt());
+  else {
+    cout << "  Error: unknown type " << gen_desc << endl;
+    exit(1);
+  }
+
+  return found_gen;
+}
+
+
+cString & cAnalyze::GetVariable(const cString & var)
+{
+  if (var.GetSize() != 1 ||
+      (var.IsLetter(0) == false && var.IsNumeric(0) == false)) {
+    cerr << "Error: Illegal variable " << var << " being used." << endl;
+    exit(1);
+  }
+
+  if (var.IsLowerLetter(0) == true) {
+    int var_id = (int) (var[0] - 'a');
+    return variables[var_id];
+  }
+  else if (var.IsUpperLetter(0) == true) {
+    int var_id = (int) (var[0] - 'A');
+    return local_variables[var_id];
+  }
+  // Otherwise it must be a number...
+  int var_id = (int) (var[0] - '0');
+  return arg_variables[var_id];
+}
+
+
+void cAnalyze::LoadCommandList(cInitFile & init_file,
+			       tList<cAnalyzeCommand> & clist)
+{
+  while (init_file.GetLineNum() < init_file.GetNumLines()) {
+    cString cur_string = init_file.GetNextLine();
+    cString command = cur_string.PopWord();
+    command.ToUpper();
+
+    cAnalyzeCommand * cur_command;
+    cAnalyzeCommandDefBase * command_def = FindAnalyzeCommandDef(command);
+    if (command == "END") {
+      // We are done with this section of code; break out...
+      break;
+    }
+    else if (command_def != NULL && command_def->IsFlowCommand() == true) {
+      // This code has a body to it... fill it out!
+      cur_command = new cAnalyzeFlowCommand(command, cur_string);
+      LoadCommandList( init_file, *(cur_command->GetCommandList()) );
+    }
+    else {
+      // This is a normal command...
+      cur_command = new cAnalyzeCommand(command, cur_string);
+    }
+
+    clist.PushRear(cur_command);
+  }
+}
+
+void cAnalyze::InteractiveLoadCommandList(tList<cAnalyzeCommand> & clist)
+{
+  interactive_depth++;
+  char text_input[2048];
+  while (true) {
+    for (int i = 0; i <= interactive_depth; i++) {
+      cout << ">>";
+    }
+    cout << " ";
+    cout.flush();
+    cin.getline(text_input, 2048);
+    cString cur_input(text_input);
+    cString command = cur_input.PopWord();
+    command.ToUpper();
+
+    cAnalyzeCommand * cur_command;
+    cAnalyzeCommandDefBase * command_def = FindAnalyzeCommandDef(command);
+    if (command == "END") {
+      // We are done with this section of code; break out...
+      break;
+    }
+    else if (command_def != NULL && command_def->IsFlowCommand() == true) {
+      // This code has a body to it... fill it out!
+      cur_command = new cAnalyzeFlowCommand(command, cur_input);
+      InteractiveLoadCommandList(*(cur_command->GetCommandList()));
+    }
+    else {
+      // This is a normal command...
+      cur_command = new cAnalyzeCommand(command, cur_input);
+    }
+
+    clist.PushRear(cur_command);
+  }
+  interactive_depth--;
+}
+
+void cAnalyze::PreProcessArgs(cString & args)
+{
+  int pos = 0;
+  int search_start = 0;
+  while ((pos = args.Find('$', search_start)) != -1) {
+    // Setup the variable name that was found...
+    char varlet = args[pos+1];
+    cString varname("$");
+    varname += varlet;
+
+    // Determine the variable and act on it.
+    int varsize = 0;
+    if (varlet == '$') {
+      args.Clip(pos+1, 1);
+      varsize = 1;
+    }
+    else if (varlet >= 'a' && varlet <= 'z') {
+      int var_id = (int) (varlet - 'a');
+      args.Replace(varname, variables[var_id], pos);
+      varsize = variables[var_id].GetSize();
+    }
+    else if (varlet >= 'A' && varlet <= 'Z') {
+      int var_id = (int) (varlet - 'A');
+      args.Replace(varname, local_variables[var_id], pos);
+      varsize = local_variables[var_id].GetSize();
+    }
+    else if (varlet >= '0' && varlet <= '9') {
+      int var_id = (int) (varlet - '0');
+      args.Replace(varname, arg_variables[var_id], pos);
+      varsize = arg_variables[var_id].GetSize();
+    }
+    search_start = pos + varsize;
+  }
+}
+
+void cAnalyze::ProcessCommands(tList<cAnalyzeCommand> & clist)
+{
+  // Process the command list...
+  tListIterator<cAnalyzeCommand> command_it(clist);
+  command_it.Reset();
+  cAnalyzeCommand * cur_command = NULL;
+  while ((cur_command = command_it.Next()) != NULL) {
+    cString command = cur_command->GetCommand();
+    cString args = cur_command->GetArgs();
+    PreProcessArgs(args);
+
+    cAnalyzeCommandDefBase * command_fun = FindAnalyzeCommandDef(command);
+    if (command_fun != NULL) command_fun->Run(this, args, *cur_command);
+    else if (FunctionRun(command, args) == true) {
+      // Found a defined function by this name.
+    }
+    else {
+      cerr << "Error: Unknown analysis keyword '" << command << "'." << endl;
+      exit(1);
+    }
+
+  }
+}
+
+void cAnalyze::SetupGenotypeDataList()
+{
+  if (genotype_data_list.GetSize() != 0) return; // List already setup.
+
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, bool>
+       ("viable",      "Is Viable (0/1)", &cAnalyzeGenotype::GetViable,
+	&cAnalyzeGenotype::SetViable));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, int>
+       ("id",          "Genome ID",       &cAnalyzeGenotype::GetID,
+	&cAnalyzeGenotype::SetID));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, const cString &>
+       ("tag",         "Genotype Tag",    &cAnalyzeGenotype::GetTag,
+	&cAnalyzeGenotype::SetTag,
+	&cAnalyzeGenotype::CompareNULL, "(none)", ""));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, int>
+       ("parent_id",   "Parent ID",       &cAnalyzeGenotype::GetParentID,
+	&cAnalyzeGenotype::SetParentID));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, int>
+       ("parent_dist", "Parent Distance", &cAnalyzeGenotype::GetParentDist,
+	&cAnalyzeGenotype::SetParentDist));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, int>
+       ("ancestor_dist","Ancestor Distance",&cAnalyzeGenotype::GetAncestorDist,
+	&cAnalyzeGenotype::SetAncestorDist));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, int>
+       ("num_cpus",    "Number of CPUs",  &cAnalyzeGenotype::GetNumCPUs,
+	&cAnalyzeGenotype::SetNumCPUs));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, int>
+       ("total_cpus",  "Total CPUs Ever", &cAnalyzeGenotype::GetTotalCPUs,
+	&cAnalyzeGenotype::SetTotalCPUs));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, int>
+       ("length",      "Genome Length",   &cAnalyzeGenotype::GetLength,
+	&cAnalyzeGenotype::SetLength, &cAnalyzeGenotype::CompareLength));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, int>
+       ("copy_length", "Copied Length",   &cAnalyzeGenotype::GetCopyLength,
+	&cAnalyzeGenotype::SetCopyLength));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, int>
+       ("exe_length",  "Executed Length", &cAnalyzeGenotype::GetExeLength,
+	&cAnalyzeGenotype::SetExeLength));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, double>
+       ("merit",       "Merit",           &cAnalyzeGenotype::GetMerit,
+	&cAnalyzeGenotype::SetMerit, &cAnalyzeGenotype::CompareMerit));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, double>
+       ("comp_merit",  "Computational Merit", &cAnalyzeGenotype::GetCompMerit,
+	(void (cAnalyzeGenotype::*)(double)) NULL, &cAnalyzeGenotype::CompareCompMerit));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, double>
+       ("comp_merit_ratio", "Computational Merit Ratio",
+	&cAnalyzeGenotype::GetCompMeritRatio,
+	(void (cAnalyzeGenotype::*)(double)) NULL,
+	&cAnalyzeGenotype::CompareCompMerit));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, int>
+       ("gest_time",   "Gestation Time",  &cAnalyzeGenotype::GetGestTime,
+	&cAnalyzeGenotype::SetGestTime,
+	&cAnalyzeGenotype::CompareGestTime, "Inf."));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, double>
+       ("efficiency",  "Rep. Efficiency", &cAnalyzeGenotype::GetEfficiency,
+	(void (cAnalyzeGenotype::*)(double)) NULL,
+	&cAnalyzeGenotype::CompareEfficiency));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, double>
+       ("efficiency_ratio", "Rep. Efficiency Ratio",
+	&cAnalyzeGenotype::GetEfficiencyRatio,
+	(void (cAnalyzeGenotype::*)(double)) NULL,
+	&cAnalyzeGenotype::CompareEfficiency));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, double>
+       ("fitness",     "Fitness",         &cAnalyzeGenotype::GetFitness,
+	&cAnalyzeGenotype::SetFitness, &cAnalyzeGenotype::CompareFitness));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, double>
+       ("div_type",     "Divide Type",         &cAnalyzeGenotype::GetDivType,
+	&cAnalyzeGenotype::SetDivType));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, double>
+       ("fitness_ratio", "Fitness Ratio", &cAnalyzeGenotype::GetFitnessRatio,
+	(void (cAnalyzeGenotype::*)(double)) NULL,
+	&cAnalyzeGenotype::CompareFitness));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, int>
+       ("update_born", "Update Born",     &cAnalyzeGenotype::GetUpdateBorn,
+	&cAnalyzeGenotype::SetUpdateBorn));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, int>
+       ("update_dead", "Update Dead",     &cAnalyzeGenotype::GetUpdateDead,
+	&cAnalyzeGenotype::SetUpdateDead));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, int>
+       ("depth",       "Tree Depth",      &cAnalyzeGenotype::GetDepth,
+	&cAnalyzeGenotype::SetDepth));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, double>
+       ("frac_dead",   "Fraction Mutations Lethal",
+	&cAnalyzeGenotype::GetFracDead,
+	(void (cAnalyzeGenotype::*)(double)) NULL));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, double>
+       ("frac_neg",   "Fraction Mutations Detrimental",
+	&cAnalyzeGenotype::GetFracNeg,
+	(void (cAnalyzeGenotype::*)(double)) NULL));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, double>
+       ("frac_neut",   "Fraction Mutations Neutral",
+	&cAnalyzeGenotype::GetFracNeut,
+	(void (cAnalyzeGenotype::*)(double)) NULL));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, double>
+       ("frac_pos",   "Fraction Mutations Beneficial",
+	&cAnalyzeGenotype::GetFracPos,
+	(void (cAnalyzeGenotype::*)(double)) NULL));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, const cString &>
+       ("parent_muts", "Mutations from Parent",
+	&cAnalyzeGenotype::GetParentMuts, &cAnalyzeGenotype::SetParentMuts,
+	&cAnalyzeGenotype::CompareNULL, "(none)", ""));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, const cString &>
+       ("task_order", "Task Performance Order",
+	&cAnalyzeGenotype::GetTaskOrder, &cAnalyzeGenotype::SetTaskOrder,
+	&cAnalyzeGenotype::CompareNULL, "(none)", ""));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, cString>
+       ("sequence",    "Genome Sequence",
+	&cAnalyzeGenotype::GetSequence, &cAnalyzeGenotype::SetSequence, 
+	&cAnalyzeGenotype::CompareNULL, "(N/A)", ""));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, const cString &>
+       ("alignment",   "Aligned Sequence",
+	&cAnalyzeGenotype::GetAlignedSequence,
+	&cAnalyzeGenotype::SetAlignedSequence,
+	&cAnalyzeGenotype::CompareNULL, "(N/A)", ""));
+
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, cString>
+       ("task_list",    "List of all tasks performed",
+	&cAnalyzeGenotype::GetTaskList,
+	(void (cAnalyzeGenotype::*)(cString)) NULL,
+	&cAnalyzeGenotype::CompareNULL, "(N/A)", ""));
+
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, cString>
+       ("link.tasksites", "Phenotype Map", &cAnalyzeGenotype::GetMapLink,
+	(void (cAnalyzeGenotype::*)(cString)) NULL));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, cString>
+       ("html.sequence",  "Genome Sequence",
+	&cAnalyzeGenotype::GetHTMLSequence,
+	(void (cAnalyzeGenotype::*)(cString)) NULL,
+	&cAnalyzeGenotype::CompareNULL, "(N/A)", ""));
+
+  const cTaskLib & task_lib = cTestCPU::GetEnvironment()->GetTaskLib();
+  for (int i = 0; i < task_lib.GetSize(); i++) {
+    cString t_name, t_desc;
+    t_name.Set("task.%d", i);
+    t_desc = task_lib.GetTask(i).GetDesc();
+    genotype_data_list.PushRear(new tArgDataEntry<cAnalyzeGenotype, int, int>
+	(t_name, t_desc, &cAnalyzeGenotype::GetTaskCount, i,
+	 &cAnalyzeGenotype::CompareTaskCount));
+  }
+
+  // The remaining values should actually go in a seperate list called
+  // "population_data_list", but for the moment we're going to put them
+  // here so that we only need to worry about a single system to load and
+  // save genotype information.
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, int>
+       ("update",       "Update Output",
+	&cAnalyzeGenotype::GetUpdateDead, &cAnalyzeGenotype::SetUpdateDead));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, int>
+       ("dom_num_cpus", "Number of Dominant Organisms",
+	&cAnalyzeGenotype::GetNumCPUs, &cAnalyzeGenotype::SetNumCPUs));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, int>
+       ("dom_depth",    "Tree Depth of Dominant Genotype",
+	&cAnalyzeGenotype::GetDepth, &cAnalyzeGenotype::SetDepth));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, int>
+       ("dom_id",       "Dominant Genotype ID",
+	&cAnalyzeGenotype::GetID, &cAnalyzeGenotype::SetID));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, cString>
+       ("dom_sequence", "Dominant Genotype Sequence",
+	&cAnalyzeGenotype::GetSequence, &cAnalyzeGenotype::SetSequence, 
+	&cAnalyzeGenotype::CompareNULL, "(N/A)", ""));
+}
+
+
+// Pass in the arguments for a command and fill out the entries in list
+// format....
+
+void cAnalyze::LoadGenotypeDataList(cStringList arg_list,
+       tList< tDataEntryCommand<cAnalyzeGenotype> > & output_list)
+{
+  // For the moment, just put everything into the output list.
+  SetupGenotypeDataList();
+
+  // If no args were given, load all of the stats.
+  if (arg_list.GetSize() == 0) {
+    tListIterator< tDataEntryBase<cAnalyzeGenotype> >
+      genotype_data_it(genotype_data_list);
+    while (genotype_data_it.Next() != (void *) NULL) {
+      tDataEntryCommand<cAnalyzeGenotype> * entry_command =
+	new tDataEntryCommand<cAnalyzeGenotype>(genotype_data_it.Get());
+      output_list.PushRear(entry_command);
+    }
+  }
+  // Otherwise, load only those listed.
+  else {
+    while (arg_list.GetSize() != 0) {
+      // Setup the next entry
+      cString cur_args = arg_list.Pop();
+      cString cur_entry = cur_args.Pop(':');
+      bool found_entry = false;
+
+      // Scan the genotype data list for the current entry
+      tListIterator< tDataEntryBase<cAnalyzeGenotype> >
+	genotype_data_it(genotype_data_list);
+
+      while (genotype_data_it.Next() != (void *) NULL) {
+	if (genotype_data_it.Get()->GetName() == cur_entry) {
+	  tDataEntryCommand<cAnalyzeGenotype> * entry_command =
+	    new tDataEntryCommand<cAnalyzeGenotype>
+	    (genotype_data_it.Get(), cur_args);
+	  output_list.PushRear(entry_command);
+	  found_entry = true;
+	  break;
+	}
+      }
+
+      // If the entry was not found, give a warning.
+      if (found_entry == false) {
+	int best_match = 1000;
+	cString best_entry;
+
+	genotype_data_it.Reset();
+	while (genotype_data_it.Next() != (void *) NULL) {
+	  const cString & test_str = genotype_data_it.Get()->GetName();
+	  const int test_dist = cStringUtil::EditDistance(test_str, cur_entry);
+	  if (test_dist < best_match) {
+	    best_match = test_dist;
+	    best_entry = test_str;
+	  }
+	}	
+
+	cerr << "Warning: Format entry \"" << cur_entry
+	     << "\" not found.  Best match is \""
+	     << best_entry << "\"." << endl;
+      }
+
+    }
+  }
+}
+
+
+void cAnalyze::AddLibraryDef(const cString & name,
+			     void (cAnalyze::*_fun)(cString))
+{
+  command_lib.PushRear(new cAnalyzeCommandDef(name, _fun));
+}
+
+void cAnalyze::AddLibraryDef(const cString & name,
+	  void (cAnalyze::*_fun)(cString, tList<cAnalyzeCommand> &))
+{
+  command_lib.PushRear(new cAnalyzeFlowCommandDef(name, _fun));
+}
+
+void cAnalyze::SetupCommandDefLibrary()
+{
+  if (command_lib.GetSize() != 0) return; // Library already setup.
+
+  AddLibraryDef("LOAD_ORGANISM", &cAnalyze::LoadOrganism);
+  AddLibraryDef("LOAD_BASE_DUMP", &cAnalyze::LoadBasicDump);
+  AddLibraryDef("LOAD_DETAIL_DUMP", &cAnalyze::LoadDetailDump);
+  AddLibraryDef("LOAD_SEQUENCE", &cAnalyze::LoadSequence);
+  AddLibraryDef("LOAD_DOMINANT", &cAnalyze::LoadDominant);
+  AddLibraryDef("LOAD", &cAnalyze::LoadFile);
+
+    // Reduction commands...
+  AddLibraryDef("FIND_GENOTYPE", &cAnalyze::FindGenotype);
+  AddLibraryDef("FIND_LINEAGE", &cAnalyze::FindLineage);
+  AddLibraryDef("FIND_CLADE", &cAnalyze::FindClade);
+  AddLibraryDef("SAMPLE_ORGANISMS", &cAnalyze::SampleOrganisms);
+  AddLibraryDef("SAMPLE_GENOTYPES", &cAnalyze::SampleGenotypes);
+  AddLibraryDef("KEEP_TOP", &cAnalyze::KeepTopGenotypes);
+
+  // Direct output commands...
+  AddLibraryDef("PRINT", &cAnalyze::CommandPrint);
+  AddLibraryDef("TRACE", &cAnalyze::CommandTrace);
+  AddLibraryDef("PRINT_TASKS", &cAnalyze::CommandPrintTasks);
+  AddLibraryDef("DETAIL", &cAnalyze::CommandDetail);
+  AddLibraryDef("DETAIL_TIMELINE", &cAnalyze::CommandDetailTimeline);
+  AddLibraryDef("DETAIL_BATCHES", &cAnalyze::CommandDetailBatches);
+  AddLibraryDef("DETAIL_INDEX", &cAnalyze::CommandDetailIndex);
+
+  // Population analysis commands...
+  AddLibraryDef("PRINT_PHENOTYPES", &cAnalyze::CommandPrintPhenotypes);
+  AddLibraryDef("PRINT_DIVERSITY", &cAnalyze::CommandPrintDiversity);
+
+  // Individual organism analysis...
+  AddLibraryDef("LANDSCAPE", &cAnalyze::CommandLandscape);
+  AddLibraryDef("FITNESS_MATRIX", &cAnalyze::CommandFitnessMatrix);
+  AddLibraryDef("MAP", &cAnalyze::CommandMapTasks);  // Deprecated...
+  AddLibraryDef("MAP_TASKS", &cAnalyze::CommandMapTasks);
+  AddLibraryDef("AVERAGE_MODULARITY", &cAnalyze::CommandAverageModularity);
+  AddLibraryDef("MAP_MUTATIONS", &cAnalyze::CommandMapMutations);
+  AddLibraryDef("ANALYZE_COMPLEXITY", &cAnalyze::AnalyzeComplexity);
+  AddLibraryDef("ANALYZE_POP_COMPLEXITY", &cAnalyze::AnalyzePopComplexity);
+
+  // Population comparison commands...
+  AddLibraryDef("HAMMING", &cAnalyze::CommandHamming);
+  AddLibraryDef("LEVENSTEIN", &cAnalyze::CommandLevenstein);
+  AddLibraryDef("SPECIES", &cAnalyze::CommandSpecies);
+
+  // Lineage analysis commands...
+  AddLibraryDef("ALIGN", &cAnalyze::CommandAlign);
+
+  // Build input files for avida...
+  AddLibraryDef("WRITE_CLONE", &cAnalyze::WriteClone);
+  AddLibraryDef("WRITE_INJECT_EVENTS", &cAnalyze::WriteInjectEvents);
+
+  // Automated analysis
+  AddLibraryDef("ANALYZE_MUTS", &cAnalyze::AnalyzeMuts);
+  AddLibraryDef("ANALYZE_INSTRUCTIONS", &cAnalyze::AnalyzeInstructions);
+  AddLibraryDef("ANALYZE_BRANCHING", &cAnalyze::AnalyzeBranching);
+  AddLibraryDef("ANALYZE_MUTATION_TRACEBACK",
+		&cAnalyze::AnalyzeMutationTraceback);
+
+  // Environment manipulation
+  AddLibraryDef("ENVIRONMENT", &cAnalyze::EnvironmentSetup);
+
+  // Documantation...
+  AddLibraryDef("HELPFILE", &cAnalyze::CommandHelpfile);
+
+  // Control commands...
+  AddLibraryDef("SET", &cAnalyze::VarSet);
+  AddLibraryDef("SET_BATCH", &cAnalyze::BatchSet);
+  AddLibraryDef("NAME_BATCH", &cAnalyze::BatchName);
+  AddLibraryDef("TAG_BATCH", &cAnalyze::BatchTag);
+  AddLibraryDef("PURGE_BATCH", &cAnalyze::BatchPurge);
+  AddLibraryDef("DUPLICATE", &cAnalyze::BatchDuplicate);
+  AddLibraryDef("RECALCULATE", &cAnalyze::BatchRecalculate);
+  AddLibraryDef("RENAME", &cAnalyze::BatchRename);
+  AddLibraryDef("STATUS", &cAnalyze::PrintStatus);
+  AddLibraryDef("DEBUG", &cAnalyze::PrintDebug);
+  AddLibraryDef("VERBOSE", &cAnalyze::ToggleVerbose);
+  AddLibraryDef("INCLUDE", &cAnalyze::IncludeFile);
+  AddLibraryDef("SYSTEM", &cAnalyze::CommandSystem);
+  AddLibraryDef("INTERACTIVE", &cAnalyze::CommandInteractive);
+
+    // Functions...
+  AddLibraryDef("FUNCTION", &cAnalyze::FunctionCreate);
+
+    // Flow commands...
+  AddLibraryDef("FOREACH", &cAnalyze::CommandForeach);
+  AddLibraryDef("FORRANGE", &cAnalyze::CommandForRange);
+}
+
+cAnalyzeCommandDefBase * cAnalyze::FindAnalyzeCommandDef(const cString & name)
+{
+  SetupCommandDefLibrary();
+
+  tListIterator<cAnalyzeCommandDefBase> lib_it(command_lib);
+  while (lib_it.Next() != (void *) NULL) {
+    if (lib_it.Get()->GetName() == name) break;
+  }
+
+  return lib_it.Get();
+}
Index: avida/current/source/main/analyze.hh
diff -u /dev/null avida/current/source/main/analyze.hh:1.50
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/analyze.hh	Tue Nov 25 09:37:56 2003
@@ -0,0 +1,197 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef ANALYZE_HH
+#define ANALYZE_HH
+
+#ifndef DATA_FILE_MANAGER_HH
+#include "data_file_manager.hh"
+#endif
+#ifndef GENOTYPE_BATCH_HH
+#include "genotype_batch.hh"
+#endif
+#ifndef RANDOM_HH
+#include "random.hh"
+#endif
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+#ifndef STRING_LIST_HH
+#include "string_list.hh"
+#endif
+#ifndef TLIST_HH
+#include "tList.hh"
+#endif
+
+#define MAX_BATCHES 200
+
+// cAnalyze            : The master analyze object.
+
+class cGenotypeBatch; // array
+template <class T> class tList; // aggregate
+class cAnalyzeCommand;
+class cAnalyzeFunction;
+class cAnalyzeCommandDefBase;
+class cString; // aggregate
+class cDataFileManager; // aggregate
+template <class T> class tDataEntryBase;
+class cInstSet;
+class cRandom; // aggregate
+class cString; // aggregate
+class cAnalyzeGenotype;
+class cInitFile;
+class cStringList; // aggregate
+template <class T> class tDataEntryCommand;
+template <class T> class tListIterator;
+
+class cAnalyze {
+private:
+  int cur_batch;
+  cGenotypeBatch batch[MAX_BATCHES];
+  tList<cAnalyzeCommand> command_list;
+  tList<cAnalyzeFunction> function_list;
+  tList<cAnalyzeCommandDefBase> command_lib;
+  cString variables[26];
+  cString local_variables[26];
+  cString arg_variables[10];
+
+  bool verbose;            // Should details be output to command line?
+  int interactive_depth;   // How nested are we if in interactive mode?
+
+  cDataFileManager data_file_manager;
+  tList< tDataEntryBase<cAnalyzeGenotype> > genotype_data_list;
+
+  cInstSet & inst_set;
+  cRandom random;
+
+private:
+  // Pop specific types of arguments from an arg list.
+  cString PopDirectory(cString & in_string, const cString & default_dir);
+  int PopBatch(const cString & in_string);
+  cAnalyzeGenotype * PopGenotype(cString gen_desc, int batch_id=-1);
+  cString & GetVariable(const cString & varname);
+
+  // Other arg-list methods
+  void LoadCommandList(cInitFile & init_file, tList<cAnalyzeCommand> & clist);
+  void InteractiveLoadCommandList(tList<cAnalyzeCommand> & clist);
+  void PreProcessArgs(cString & args);
+  void ProcessCommands(tList<cAnalyzeCommand> & clist);
+
+  void SetupGenotypeDataList();	
+  void LoadGenotypeDataList(cStringList arg_list,
+	    tList< tDataEntryCommand<cAnalyzeGenotype> > & output_list);
+		      
+  void AddLibraryDef(const cString & name, void (cAnalyze::*_fun)(cString));
+  void AddLibraryDef(const cString & name,
+	     void (cAnalyze::*_fun)(cString, tList<cAnalyzeCommand> &));
+  cAnalyzeCommandDefBase * FindAnalyzeCommandDef(const cString & name);
+  void SetupCommandDefLibrary();
+  bool FunctionRun(const cString & fun_name, cString args);
+
+  // Batch management...
+  int BatchUtil_GetMaxLength(int batch_id=-1);
+
+  // Comamnd helpers...
+  void CommandDetail_Header(std::ostream & fp, int format_type,
+            tListIterator< tDataEntryCommand<cAnalyzeGenotype> > & output_it,
+            int time_step=-1);
+  void CommandDetail_Body(std::ostream & fp, int format_type,
+            tListIterator< tDataEntryCommand<cAnalyzeGenotype> > & output_it,
+            int time_step=-1, int max_time=1);
+private:
+  // Loading methods...
+  void LoadOrganism(cString cur_string);
+  void LoadBasicDump(cString cur_string);
+  void LoadDetailDump(cString cur_string);
+  void LoadSequence(cString cur_string);
+  void LoadDominant(cString cur_string);
+  void LoadFile(cString cur_string);
+
+  // Reduction
+  void FindGenotype(cString cur_string);
+  void FindLineage(cString cur_string);
+  void FindClade(cString cur_string);
+  void SampleOrganisms(cString cur_string);
+  void SampleGenotypes(cString cur_string);
+  void KeepTopGenotypes(cString cur_string);
+
+  // Direct Output Commands...
+  void CommandPrint(cString cur_string);
+  void CommandTrace(cString cur_string);
+  void CommandPrintTasks(cString cur_string);
+  void CommandDetail(cString cur_string);
+  void CommandDetailTimeline(cString cur_string);
+  void CommandDetailBatches(cString cur_string);
+  void CommandDetailIndex(cString cur_string);
+
+  // Population Analysis Commands...
+  void CommandPrintPhenotypes(cString cur_string);
+  void CommandPrintDiversity(cString cur_string);
+
+  // Individual Organism Analysis...
+  void CommandLandscape(cString cur_string);
+  void CommandFitnessMatrix(cString cur_string);
+  void CommandMapTasks(cString cur_string);
+  void CommandAverageModularity(cString cur_string);
+  void CommandMapMutations(cString cur_string);
+
+  // Population Comparison Commands...
+  void CommandHamming(cString cur_string);
+  void CommandLevenstein(cString cur_string);
+  void CommandSpecies(cString cur_string);
+
+  // Lineage Analysis Commands...
+  void CommandAlign(cString cur_string);
+
+  // Build Input Files for Avida
+  void WriteClone(cString cur_string);
+  void WriteInjectEvents(cString cur_string);
+
+  // Automated analysis...
+  void AnalyzeMuts(cString cur_string);
+  void AnalyzeInstructions(cString cur_string);
+  void AnalyzeBranching(cString cur_string);
+  void AnalyzeMutationTraceback(cString cur_string);
+  void AnalyzeComplexity(cString cur_string);
+  void AnalyzePopComplexity(cString cur_string);
+
+  // Environment Manipulation
+  void EnvironmentSetup(cString cur_string);
+
+  // Documentation...
+  void CommandHelpfile(cString cur_string);
+  void CommandDocfile(cString cur_string);
+
+  // Control...
+  void VarSet(cString cur_string);
+  void BatchSet(cString cur_string);
+  void BatchName(cString cur_string);
+  void BatchTag(cString cur_string);
+  void BatchPurge(cString cur_string);
+  void BatchDuplicate(cString cur_string);
+  void BatchRecalculate(cString cur_string);
+  void BatchRename(cString cur_string);
+  void PrintStatus(cString cur_string);
+  void PrintDebug(cString cur_string);
+  void ToggleVerbose(cString cur_string);
+  void IncludeFile(cString cur_string);
+  void CommandSystem(cString cur_string);
+  void CommandInteractive(cString cur_string);
+
+  // Functions...
+  void FunctionCreate(cString cur_string, tList<cAnalyzeCommand> & clist);
+
+  // Flow Control...
+  void CommandForeach(cString cur_string, tList<cAnalyzeCommand> & clist);
+  void CommandForRange(cString cur_string, tList<cAnalyzeCommand> & clist);
+
+public:
+  cAnalyze(cString filename);
+  ~cAnalyze();
+};
+
+#endif
Index: avida/current/source/main/analyze_util.cc
diff -u /dev/null avida/current/source/main/analyze_util.cc:1.12
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/analyze_util.cc	Tue Nov 25 09:37:56 2003
@@ -0,0 +1,975 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef ANALYZE_UTIL_HH
+#include "analyze_util.hh"
+#endif
+
+#ifndef CONFIG_HH
+#include "config.hh"
+#endif
+#ifndef DEFS_HH
+#include "defs.hh"
+#endif
+#ifndef ENVIRONMENT_HH
+#include "environment.hh"
+#endif
+#ifndef GENEBANK_HH
+#include "genebank.hh"
+#endif
+#ifndef GENOME_HH
+#include "genome.hh"
+#endif
+#ifndef GENOME_UTIL_HH
+#include "genome_util.hh"
+#endif
+#ifndef GENOTYPE_HH
+#include "genotype.hh"
+#endif
+#ifndef HARDWARE_BASE_HH
+#include "hardware_base.hh"
+#endif
+#ifndef HISTOGRAM_HH
+#include "histogram.hh"
+#endif
+#ifndef INST_SET_HH
+#include "inst_set.hh"
+#endif
+#ifndef INST_UTIL_HH
+#include "inst_util.hh"
+#endif
+#ifndef LANDSCAPE_HH
+#include "landscape.hh"
+#endif
+#ifndef ORGANISM_HH
+#include "organism.hh"
+#endif
+#ifndef PHENOTYPE_HH
+#include "phenotype.hh"
+#endif
+#ifndef POPULATION_HH
+#include "population.hh"
+#endif
+#ifndef POPULATION_CELL_HH
+#include "population_cell.hh"
+#endif
+#ifndef SPECIES_HH
+#include "species.hh"
+#endif
+#ifndef STATS_HH
+#include "stats.hh"
+#endif
+#ifndef TEST_CPU_HH
+#include "test_cpu.hh"
+#endif
+#ifndef TEST_UTIL_HH
+#include "test_util.hh"
+#endif
+#ifndef TOOLS_HH
+#include "tools.hh"
+#endif
+
+#include <vector>
+
+using namespace std;
+
+void cAnalyzeUtil::TestGenome(const cGenome & genome, cInstSet & inst_set,
+			      ofstream & fp, int update)
+{
+  cCPUTestInfo test_info;
+  cTestCPU::TestGenome(test_info, genome);
+
+  cPhenotype &colony_phenotype = test_info.GetColonyOrganism()->GetPhenotype();
+  fp << update << " "                                //  1
+     << colony_phenotype.GetMerit().GetDouble() << " "            //  2
+     << colony_phenotype.GetGestationTime() << " "             //  3
+     << colony_phenotype.GetFitness() << " "                      //  4
+     << 1.0 / (0.1  + colony_phenotype.GetGestationTime()) << " " //  5
+     << genome.GetSize() << " "                                   //  6
+     << colony_phenotype.GetCopiedSize() << " "                   //  7
+     << colony_phenotype.GetExecutedSize() << endl;               //  8
+}
+
+
+
+void cAnalyzeUtil::TestInsSizeChangeRobustness(ofstream & fp,
+		    const cInstSet & inst_set, const cGenome & in_genome,
+		    int num_trials, int update)
+{
+  cCPUTestInfo test_info;
+  const cInstruction inst_none = inst_set.GetInst("instruction_none");
+
+  // Stats
+  int num_viable = 0;
+  int num_new_size = 0;
+  int num_parent_size = 0;
+
+  for (int i = 0; i < num_trials; i++) {
+    cCPUMemory genome(in_genome);
+    // Should check to only insert infront of an instruction (not a Nop)
+    int ins_pos = -1;
+    while (ins_pos < 0) {
+      ins_pos = g_random.GetUInt(genome.GetSize());
+      if( inst_set.IsNop(genome[ins_pos]) )  ins_pos = -1;
+    }
+
+    // Insert some "instruction_none" into the genome
+    const int num_nops = g_random.GetUInt(5) + 5;
+    for (int j = 0; j < num_nops; j++)  genome.Insert(ins_pos, inst_none);
+
+    // Test the genome and output stats
+    if ( cTestCPU::TestGenome(test_info, genome) ){ // Daughter viable...
+      num_viable++;
+      const double child_size =
+	test_info.GetColonyOrganism()->GetGenome().GetSize();
+
+      if (child_size == (double) in_genome.GetSize()) num_parent_size++;
+      else if (child_size == (double) genome.GetSize()) num_new_size++;
+    }
+  } // for num_trials
+
+  fp << update << " "
+     << (double) num_viable / num_trials << " "
+     << (double) num_new_size / num_trials << " "
+     << (double) num_parent_size / num_trials << " "
+     << endl;
+}
+
+
+
+// Returns the genome of maximal fitness.
+cGenome cAnalyzeUtil::CalcLandscape(int dist, const cGenome & genome,
+				    cInstSet & inst_set)
+{
+  cLandscape landscape(genome, inst_set);
+  landscape.Process(dist);
+  double peak_fitness = landscape.GetPeakFitness();
+  cGenome peak_genome = landscape.GetPeakGenome();
+
+  // Print the results.
+
+  static ofstream fp("landscape.dat");
+  static ofstream fp_entropy("land-entropy.dat");
+  static ofstream fp_count("land-sitecount.dat");
+
+  landscape.PrintStats(fp);
+  landscape.PrintEntropy(fp_entropy);
+  landscape.PrintSiteCount(fp_count);
+
+  // Repeat for Insertions...
+  landscape.Reset(genome);
+  landscape.ProcessInsert();
+  static ofstream fp_ins("landscape-ins.dat");
+  static ofstream fp_ins_count("land-ins-sitecount.dat");
+  landscape.PrintStats(fp_ins);
+  landscape.PrintSiteCount(fp_ins_count);
+  if (landscape.GetPeakFitness() > peak_fitness) {
+    peak_fitness = landscape.GetPeakFitness();
+    peak_genome = landscape.GetPeakGenome();
+  }
+
+  // And Deletions...
+  landscape.Reset(genome);
+  landscape.ProcessDelete();
+  static ofstream fp_del("landscape-del.dat");
+  static ofstream fp_del_count("land-del-sitecount.dat");
+  landscape.PrintStats(fp_del);
+  landscape.PrintSiteCount(fp_del_count);
+  if (landscape.GetPeakFitness() > peak_fitness) {
+    peak_fitness = landscape.GetPeakFitness();
+    peak_genome = landscape.GetPeakGenome();
+  }
+
+  return peak_genome;
+}
+
+
+void cAnalyzeUtil::AnalyzeLandscape(const cGenome & genome, cInstSet &inst_set,
+	       int sample_size, int min_found, int max_sample_size, int update)
+{
+  cLandscape landscape(genome, inst_set);
+
+  static ofstream fp("land_analyze.dat");
+
+  int num_found = 0;
+  for (int dist = 1; dist <= 10; dist++) {
+    landscape.Reset(genome);
+    if (dist == 1) {
+      landscape.Process(dist);
+      num_found = genome.GetSize() * (inst_set.GetSize() - 1);
+    } else {
+      num_found =
+	landscape.RandomProcess(sample_size, dist, min_found, max_sample_size);
+    }
+
+    fp << update                       << " "  // 1
+       << dist                         << " "  // 2
+       << landscape.GetProbDead()      << " "  // 3
+       << landscape.GetProbNeg()       << " "  // 4
+       << landscape.GetProbNeut()      << " "  // 5
+       << landscape.GetProbPos()       << " "  // 6
+       << landscape.GetNumTrials()     << " "  // 7
+       << num_found                    << " "  // 8
+       << landscape.GetAveFitness()    << " "  // 9
+       << landscape.GetAveSqrFitness() << " "  // 10
+       << endl;
+
+    if ((dist > 1) && (num_found < min_found)) break;
+  }
+}
+
+
+void cAnalyzeUtil::PairTestLandscape(const cGenome &genome, cInstSet &inst_set,
+				     int sample_size, int update)
+{
+  cLandscape landscape(genome, inst_set);
+
+  cString filename;
+  filename.Set("pairtest.%d.dat", update);
+  ofstream fp(filename());
+
+  if (sample_size != 0) landscape.TestPairs(sample_size, fp);
+  else landscape.TestAllPairs(fp);
+}
+
+
+void cAnalyzeUtil::CalcConsensus(cPopulation * population, int lines_saved)
+{
+  const int num_inst = population->GetEnvironment().GetInstSet().GetSize();
+  const int update = population->GetStats().GetUpdate();
+  cGenebank & genebank = population->GetGenebank();
+
+  // Setup the histogtams...
+  cHistogram * inst_hist = new cHistogram[MAX_CREATURE_SIZE];
+  for (int i = 0; i < MAX_CREATURE_SIZE; i++) inst_hist[i].Resize(num_inst,-1);
+
+  // Loop through all of the genotypes adding them to the histograms.
+  cGenotype * cur_genotype = genebank.GetBestGenotype();
+  for (int i = 0; i < genebank.GetSize(); i++) {
+    const int num_organisms = cur_genotype->GetNumOrganisms();
+    const int length = cur_genotype->GetLength();
+    const cGenome & genome = cur_genotype->GetGenome();
+
+    // Place this genotype into the histograms.
+    for (int j = 0; j < length; j++) {
+      assert(genome[j].GetOp() < num_inst);
+      inst_hist[j].Insert(genome[j].GetOp(), num_organisms);
+    }
+
+    // Mark all instructions beyond the length as -1 in histogram...
+    for (int j = length; j < MAX_CREATURE_SIZE; j++) {
+      inst_hist[j].Insert(-1, num_organisms);
+    }
+
+    // ...and advance to the next genotype...
+    cur_genotype = cur_genotype->GetNext();
+  }
+
+  // Now, lets print something!
+  static ofstream fp("consensus.dat");
+  static ofstream fp_abundance("con-abundance.dat");
+  static ofstream fp_var("con-var.dat");
+  static ofstream fp_entropy("con-entropy.dat");
+
+  // Determine the length of the concensus genome
+  int con_length;
+  for (con_length = 0; con_length < MAX_CREATURE_SIZE; con_length++) {
+    if (inst_hist[con_length].GetMode() == -1) break;
+  }
+
+  // Build the concensus genotype...
+  cGenome con_genome(con_length);
+  double total_entropy = 0.0;
+  for (int i = 0; i < MAX_CREATURE_SIZE; i++) {
+    const int mode = inst_hist[i].GetMode();
+    const int count = inst_hist[i].GetCount(mode);
+    const int total = inst_hist[i].GetCount();
+    const double entropy = inst_hist[i].GetNormEntropy();
+    if (i < con_length) total_entropy += entropy;
+
+    // Break out if ALL creatures have a -1 in this area, and we've
+    // finished printing all of the files.
+    if (mode == -1 && count == total) break;
+
+    if ( i < con_length )
+      con_genome[i].SetOp(mode);
+
+    // Print all needed files.
+    if (i < lines_saved) {
+      fp_abundance << count << " ";
+      fp_var << inst_hist[i].GetCountVariance() << " ";
+      fp_entropy << entropy << " ";
+    }
+  }
+
+  // Put end-of-lines on the files.
+  if (lines_saved > 0) {
+    fp_abundance << endl;
+    fp_var       << endl;
+    fp_entropy   << endl;
+  }
+
+  // --- Study the consensus genome ---
+
+  // Loop through genotypes again, and determine the average genetic distance.
+  cur_genotype = genebank.GetBestGenotype();
+  cDoubleSum distance_sum;
+  for (int i = 0; i < genebank.GetSize(); i++) {
+    const int num_organisms = cur_genotype->GetNumOrganisms();
+    const int cur_dist =
+      cGenomeUtil::FindEditDistance(con_genome, cur_genotype->GetGenome());
+    distance_sum.Add(cur_dist, num_organisms);
+
+    // ...and advance to the next genotype...
+    cur_genotype = cur_genotype->GetNext();
+  }
+
+  // Finally, gather last bits of data and print the results.
+  cGenotype * con_genotype = genebank.FindGenotype(con_genome);
+  const int best_dist = cGenomeUtil::FindEditDistance(con_genome,
+			     genebank.GetBestGenotype()->GetGenome());
+
+  const double ave_dist = distance_sum.Average();
+  const double var_dist = distance_sum.Variance();
+  const double complexity_base = (double) con_genome.GetSize() - total_entropy;
+
+  cString con_name;
+  con_name.Set("genebank/%03d-consensus-u%i.gen", con_genome.GetSize(),update);
+  cTestUtil::PrintGenome( con_genome, con_name() );
+
+
+  if (con_genotype) {
+    fp << update                                 << " " //  1
+       << con_genotype->GetMerit()               << " " //  2
+       << con_genotype->GetGestationTime()       << " " //  3
+       << con_genotype->GetFitness()             << " " //  4
+       << con_genotype->GetReproRate()           << " " //  5
+       << con_genotype->GetLength()              << " " //  6
+       << con_genotype->GetCopiedSize()          << " " //  7
+       << con_genotype->GetExecutedSize()        << " " //  8
+       << con_genotype->GetBirths()              << " " //  9
+       << con_genotype->GetBreedTrue()           << " " // 10
+       << con_genotype->GetBreedIn()             << " " // 11
+       << con_genotype->GetNumOrganisms()        << " " // 12
+       << con_genotype->GetDepth()               << " " // 13
+       << con_genotype->GetID()                  << " " // 14
+       << update - con_genotype->GetUpdateBorn() << " " // 15
+       << best_dist                              << " " // 16
+       << ave_dist                               << " " // 17
+       << var_dist                               << " " // 18
+       << total_entropy                          << " " // 19
+       << complexity_base                        << " " // 20
+       << endl;
+  }
+  else {
+    cCPUTestInfo test_info;
+    cTestCPU::TestGenome(test_info, con_genome);
+    cPhenotype & colony_phenotype =
+      test_info.GetColonyOrganism()->GetPhenotype();
+    fp << update                                             << " "   //  1
+       << colony_phenotype.GetMerit()                        << " "  //  2
+       << colony_phenotype.GetGestationTime()                << " "  //  3
+       << colony_phenotype.GetFitness()                      << " "  //  4
+       << 1.0 / (0.1  + colony_phenotype.GetGestationTime()) << " "  //  5
+       << con_genome.GetSize()                               << " "  //  6
+       << colony_phenotype.GetCopiedSize()                   << " "  //  7
+       << colony_phenotype.GetExecutedSize()                 << " "  //  8
+       << 0                                  << " "  // Births       //  9
+       << 0                                  << " "  // Breed True   // 10
+       << 0                                  << " "  // Breed In     // 11
+       << 0                                  << " "  // Num CPUs     // 12
+       << -1                                 << " "  // Depth        // 13
+       << -1                                 << " "  // ID           // 14
+       << 0                                  << " "  // Age          // 15
+       << best_dist                                          << " "  // 16
+       << ave_dist                                           << " "  // 17
+       << var_dist                                           << " "  // 18
+       << total_entropy                                      << " "  // 19
+       << complexity_base                                    << " "  // 20
+       << endl;
+  }
+
+  // Flush the file...
+  fp.flush();
+  
+  delete [] inst_hist;
+}
+
+
+
+/**
+ * This function goes through all creatures in the soup, and saves the
+ * basic landscape data (neutrality, fitness, and so on) into a stream.
+ *
+ * @param fp The stream into which the data should be saved.
+ *
+ * @param sample_prob The probability with which a particular creature should
+ * be analyzed (a value of 1 analyzes all creatures, a value of 0.1 analyzes
+ * 10%, and so on).
+ *
+ * @param landscape A bool that indicates whether the creatures should be
+ * landscaped (calc. neutrality and so on) or not.
+ *
+ * @param save_genotype A bool that indicates whether the creatures should
+ * be saved or not.
+ **/
+
+void cAnalyzeUtil::AnalyzePopulation(cPopulation * pop, ofstream & fp,
+	    double sample_prob, bool landscape, bool save_genotype)
+{
+  fp << "# (1) cell number (2) genotype name (3) length (4) fitness [test-cpu] (5) fitness (actual) (6) merit (7) no of breed trues occurred (8) lineage label (9) neutral metric (10) -... landscape data" << endl;
+
+  const double skip_prob = 1.0 - sample_prob;
+  for (int i = 0; i < pop->GetSize(); i++) {
+    if (pop->GetCell(i).IsOccupied() == false) continue;  // No organism...
+    if (g_random.P(skip_prob)) continue;               // Not sampled...
+
+    cOrganism * organism = pop->GetCell(i).GetOrganism();
+    cGenotype * genotype = organism->GetGenotype();
+    const cGenome & genome = organism->GetGenome();
+
+    cString creature_name;
+    if ( genotype->GetThreshold() ) creature_name = genotype->GetName();
+    else creature_name.Set("%03d-no_name-u%i-c%i", genotype->GetLength(),
+			   pop->GetStats().GetUpdate(), i );
+
+    fp << i                                     << " "  // 1 cell ID
+       << creature_name()                       << " "  // 2 name
+       << genotype->GetLength()                 << " "  // 3 length
+       << genotype->GetTestFitness()            << " "  // 4 fitness (test-cpu)
+       << organism->GetPhenotype().GetFitness() << " "  // 5 fitness (actual)
+       << organism->GetPhenotype().GetMerit()   << " "  // 6 merit
+       << genotype->GetBreedTrue()              << " "  // 7 breed true?
+       << organism->GetLineageLabel()           << " "  // 8 lineage label
+       << organism->GetPhenotype().GetNeutralMetric() << " "; // 9 neut metric
+
+    // create landscape object for this creature
+    if (landscape &&  genotype->GetTestFitness() > 0) {
+      cLandscape landscape( genome, pop->GetEnvironment().GetInstSet());
+      landscape.Process(1);
+      landscape.PrintStats(fp);
+    }
+    else fp << endl;
+    if ( save_genotype ){
+      char filename[40];
+      sprintf( filename, "genebank/%s", creature_name() );
+      cTestUtil::PrintGenome( genome, filename );
+    }
+  }
+}
+
+
+/**
+ * This function prints out fitness data. The main point is that it
+ * calculates the average fitness from info from the testCPU + the actual
+ * merit of the organisms, and assigns zero fitness to those organisms
+ * that will never reproduce.
+ *
+ * The function also determines the maximum fitness genotype, and can
+ * produce fitness histograms.
+ *
+ * @param datafp A stream into which the fitness data should be written.
+ * @param histofp A stream into which the fitness histogram should be
+ * written.
+ * @param histo_testCPU_fp A stream into which the fitness histogram as
+ * determined exclusively from the test-CPU should be written.
+ * @param save_max_f_genotype A bool that determines whether the genotype
+ * with the maximum fitness should be saved into the genebank.
+ * @param print_fitness_histo A bool that determines whether fitness
+ * histograms should be written.
+ * @param hist_fmax The maximum fitness value to be taken into account
+ * for the fitness histograms.
+ * @param hist_fstep The width of the individual bins in the fitness
+ * histograms.
+ **/
+
+void cAnalyzeUtil::PrintDetailedFitnessData(cPopulation *pop, ofstream &datafp,
+   ofstream & hist_fp, ofstream & histo_testCPU_fp, bool save_max_f_genotype,
+   bool print_fitness_histo, double hist_fmax, double hist_fstep)
+{
+  const int update = pop->GetStats().GetUpdate();
+  const double generation = pop->GetStats().SumGeneration().Average();
+
+  // the histogram variables
+  vector<int> histo;
+  vector<int> histo_testCPU;
+  int bins;
+
+  if ( print_fitness_histo ){
+    bins = (int) (hist_fmax / hist_fstep) + 1;
+    histo.resize( bins, 0 ); // resize and clear
+    histo_testCPU.resize( bins, 0 );
+  }
+
+  int n = 0;
+  int nhist_tot = 0;
+  int nhist_tot_testCPU = 0;
+  double fave = 0;
+  double fave_testCPU = 0;
+  double max_fitness = -1; // we set this to -1, so that even 0 is larger...
+  cGenotype * max_f_genotype = NULL;
+
+  for (int i = 0; i < pop->GetSize(); i++) {
+    if (pop->GetCell(i).IsOccupied() == false) continue;  // One use organisms.
+
+    cOrganism * organism = pop->GetCell(i).GetOrganism();
+    cGenotype * genotype = organism->GetGenotype();
+
+    cCPUTestInfo test_info;
+    cTestCPU::TestGenome( test_info, genotype->GetGenome() );
+    // We calculate the fitness based on the current merit,
+    // but with the true gestation time. Also, we set the fitness
+    // to zero if the creature is not viable.
+    const double f = ( test_info.IsViable() ) ? organism->GetPhenotype().GetMerit().CalcFitness(test_info.GetTestOrganism()->GetPhenotype().GetGestationTime()) : 0;
+    const double f_testCPU = test_info.GetColonyFitness();
+
+    // Get the maximum fitness in the population
+    // Here, we want to count only organisms that can truly replicate,
+    // to avoid complications
+    if ( f_testCPU > max_fitness &&
+	 test_info.GetTestOrganism()->GetPhenotype().CopyTrue() ){
+      max_fitness = f_testCPU;
+      max_f_genotype = genotype;
+    }
+
+    fave += f;
+    fave_testCPU += f_testCPU;
+    n += 1;
+
+
+    // histogram
+    if ( print_fitness_histo && f < hist_fmax ){
+      histo[(int) (f / hist_fstep)] += 1;
+      nhist_tot += 1;
+    }
+
+    if ( print_fitness_histo && f_testCPU < hist_fmax ){
+      histo_testCPU[(int) (f_testCPU / hist_fstep)] += 1;
+      nhist_tot_testCPU += 1;
+    }
+  }
+
+  // determine the name of the maximum fitness genotype
+  cString max_f_name;
+  if ( max_f_genotype->GetThreshold() )
+    max_f_name = max_f_genotype->GetName();
+  else // we put the current update into the name, so that it becomes unique.
+     max_f_name.Set("%03d-no_name-u%i", max_f_genotype->GetLength(),
+		    update );
+
+  datafp << update                    << " "  // 1 update
+	 << generation                << " "  // 2 generation
+	 << fave/ (double) n          << " "  // 3 average fitness
+	 << fave_testCPU/ (double) n  << " "  // 4 average test fitness
+	 << n 	                      << " "  // 5 organism total
+	 << max_fitness               << " "  // 6 maximum fitness
+	 << max_f_name()	      << " "  // 7 maxfit genotype name
+	 << endl;
+
+  if (save_max_f_genotype) {
+    char filename[40];
+    sprintf( filename, "genebank/%s", max_f_name() );
+    cTestUtil::PrintGenome( max_f_genotype->GetGenome(), filename );
+  }
+
+  if (print_fitness_histo) {
+    hist_fp << update            << " "  // 1 update
+	    << generation        << " "  // 2 generation
+	    << fave/ (double) n  << " "; // 3 average fitness
+
+    // now output the fitness histo
+    vector<int>::const_iterator it = histo.begin();
+    for ( ; it != histo.end(); it++ )
+      hist_fp << (double) (*it) / (double) nhist_tot << " ";
+    hist_fp << endl;
+
+    histo_testCPU_fp << update                    << " "  // 1 update
+		     << generation                << " "  // 2 generation
+		     << fave_testCPU/ (double) n  << " "; // 3 average fitness
+
+    // now output the fitness histo
+    it = histo_testCPU.begin();
+    for ( ; it != histo_testCPU.end(); it++ )
+      histo_testCPU_fp << (double) (*it) / (double) nhist_tot_testCPU << " ";
+    histo_testCPU_fp << endl;
+  }
+}
+
+
+/**
+ * This function goes through all genotypes currently present in the soup,
+ * and writes into an output file the average Hamming distance between the
+ * creatures in the population and a given reference genome.
+ *
+ * @param fp The stream into which the data should be saved.
+ * @param reference_genome The reference genome.
+ * @param save_creatures A bool that indicates whether creatures should be
+ * saved into the genebank or not.
+ **/
+
+void cAnalyzeUtil::PrintGeneticDistanceData(cPopulation * pop, ofstream & fp,
+					    const char * creature_name)
+{
+  double hamming_m1 = 0;
+  double hamming_m2 = 0;
+  int count = 0;
+  int dom_dist = 0;
+
+  // load the reference genome
+  cGenome reference_genome(cInstUtil::LoadGenome(creature_name,
+					 pop->GetEnvironment().GetInstSet()));
+
+  // get the info for the dominant genotype
+  cGenotype * cur_genotype = pop->GetGenebank().GetBestGenotype();
+  cGenome genome = cur_genotype->GetGenome();
+  dom_dist = cGenomeUtil::FindHammingDistance( reference_genome, genome );
+  hamming_m1 += dom_dist;
+  hamming_m2 += dom_dist*dom_dist;
+  count += cur_genotype->GetNumOrganisms();
+  // now cycle over the remaining genotypes
+  for (int i = 1; i < pop->GetGenebank().GetSize(); i++) {
+    cur_genotype = cur_genotype->GetNext();
+    cGenome genome = cur_genotype->GetGenome();
+
+    int dist = cGenomeUtil::FindHammingDistance( reference_genome, genome );
+    hamming_m1 += dist;
+    hamming_m2 += dist*dist;
+    count += cur_genotype->GetNumOrganisms();
+  }
+
+  hamming_m1 /= (double) count;
+  hamming_m2 /= (double) count;
+
+  fp << pop->GetStats().GetUpdate()          << " "  // 1 update
+     << hamming_m1 			     << " "  // ave. Hamming dist
+     << sqrt( ( hamming_m2 - hamming_m1*hamming_m1 ) / (double) count )
+                                             << " "  // std. error
+     << cGenomeUtil::FindHammingDistance( reference_genome,
+	      pop->GetGenebank().GetBestGenotype()->GetGenome() ) << " "
+     << endl;
+}
+
+
+/**
+ * This function goes through all genotypes currently present in the soup,
+ * and writes into an output file the names of the genotypes, the fitness
+ * as determined in the test cpu, and the genetic distance to a reference
+ * genome.
+ *
+ * @param fp The stream into which the data should be saved.
+ * @param reference_genome The reference genome.
+ * @param save_creatures A bool that indicates whether creatures should be
+ * saved into the genebank or not.
+ **/
+
+void cAnalyzeUtil::GeneticDistancePopDump(cPopulation * pop, ofstream & fp,
+			 const char * creature_name, bool save_creatures)
+{
+  double sum_fitness = 0;
+  int sum_num_organisms = 0;
+
+  // load the reference genome
+  cGenome reference_genome( cInstUtil::LoadGenome(creature_name,
+				  pop->GetEnvironment().GetInstSet()) );
+
+  // first, print out some documentation...
+  fp << "# (1) genotype name (2) fitness [test-cpu] (3) abundance (4) Hamming distance to reference (5) Levenstein distance to reference" << endl;
+  fp << "# reference genome is the START_CREATURE" << endl;
+
+  // cycle over all genotypes
+  cGenotype * cur_genotype = pop->GetGenebank().GetBestGenotype();
+  for (int i = 0; i < pop->GetGenebank().GetSize(); i++) {
+    const cGenome & genome = cur_genotype->GetGenome();
+    const int num_orgs = cur_genotype->GetNumOrganisms();
+
+    // now output
+
+    sum_fitness += cur_genotype->GetTestFitness() * num_orgs;
+    sum_num_organisms += num_orgs;
+
+    fp << cur_genotype->GetName()()       << " "  // 1 name
+       << cur_genotype->GetTestFitness()  << " "  // 2 fitness
+       << num_orgs                        << " "  // 3 abundance
+       << cGenomeUtil::FindHammingDistance(reference_genome, genome) << " "
+       << cGenomeUtil::FindEditDistance(reference_genome, genome) << " "  // 5
+       << genome.AsString()()             << " "  // 6 genome
+       << endl;
+
+    // save into genebank
+    if (save_creatures) {
+      char filename[40];
+      sprintf( filename, "genebank/%s", cur_genotype->GetName()() );
+      cTestUtil::PrintGenome( genome, filename );
+    }
+
+    // ...and advance to the next genotype...
+    cur_genotype = cur_genotype->GetNext();
+  }
+  fp << "# ave fitness from Test CPU's: "
+     << sum_fitness/sum_num_organisms << endl;
+}
+
+
+/**
+ * This function goes through all creatures in the soup, and writes out
+ * how many tasks the different creatures have done up to now. It counts
+ * every task only once, i.e., if a creature does 'put' three times, that
+ * will increase its count only by one.
+ *
+ * @param fp The file into which the result should be written.
+ **/
+
+void cAnalyzeUtil::TaskSnapshot(cPopulation * pop, ofstream & fp)
+{
+  fp << "# (1) cell number\n# (2) number of rewarded tasks done so far\n# (3) total number of tasks done so far\n# (4) same as 2, but right before divide\n# (5) same as 3, but right before divide\n# (6) same as 2, but for parent\n# (7) same as 3, but for parent\n# (8) genotype fitness\n# (9) genotype name" << endl;
+
+  for (int i = 0; i < pop->GetSize(); i++) {
+    if (pop->GetCell(i).IsOccupied() == false) continue;
+    cOrganism * organism = pop->GetCell(i).GetOrganism();
+
+    // create a test-cpu for the current creature
+    cCPUTestInfo test_info;
+    cTestCPU::TestGenome( test_info, organism->GetGenome() );
+    cPhenotype & test_phenotype = test_info.GetTestOrganism()->GetPhenotype();
+    cPhenotype & phenotype = organism->GetPhenotype();
+
+    int num_tasks = phenotype.GetEnvironment().GetTaskLib().GetSize();
+    int sum_tasks_all = 0;
+    int sum_tasks_rewarded = 0;
+    int divide_sum_tasks_all = 0;
+    int divide_sum_tasks_rewarded = 0;
+    int parent_sum_tasks_all = 0;
+    int parent_sum_tasks_rewarded = 0;
+
+    for (int j = 0; j < num_tasks; j++) {
+      // get the number of bonuses for this task
+      int bonuses = 1; //phenotype.GetTaskLib().GetTaskNumBonus(j);
+      int task_count = ( phenotype.GetCurTaskCount()[j] == 0 ) ? 0 : 1;
+      int divide_tasks_count = (test_phenotype.GetLastTaskCount()[j] == 0)?0:1;
+      int parent_task_count = (phenotype.GetLastTaskCount()[j] == 0) ? 0 : 1;
+
+      // If only one bonus, this task is not rewarded, as last bonus is + 0.
+      if (bonuses > 1) {
+	sum_tasks_rewarded += task_count;
+	divide_sum_tasks_rewarded += divide_tasks_count;
+	parent_sum_tasks_rewarded += parent_task_count;
+      }
+      sum_tasks_all += task_count;
+      divide_sum_tasks_all += divide_tasks_count;
+      parent_sum_tasks_all += parent_task_count;
+    }
+
+    fp << i                          << " " // 1 cell number
+       << sum_tasks_rewarded         << " " // 2 number of tasks rewarded
+       << sum_tasks_all              << " " // 3 total number of tasks done
+       << divide_sum_tasks_rewarded  << " " // 4 num rewarded tasks on divide
+       << divide_sum_tasks_all       << " " // 5 num total tasks on divide
+       << parent_sum_tasks_rewarded  << " " // 6 parent number of tasks rewared
+       << parent_sum_tasks_all       << " " // 7 parent total num tasks done
+       << test_info.GetColonyFitness()         << " " // 8 genotype fitness
+       << organism->GetGenotype()->GetName()() << " " // 9 genotype name
+       << endl;
+  }
+}
+
+
+/**
+ * This function prints all the tasks that viable creatures have performed
+ * so far (compare with the event 'print_task_data', which prints all tasks.
+ **/
+
+void cAnalyzeUtil::PrintViableTasksData(cPopulation * pop, ofstream & fp)
+{
+  const int num_tasks = cConfig::GetNumTasks();
+
+  static vector<int> tasks(num_tasks);
+  vector<int>::iterator it;
+
+  // clear task vector
+  for (it = tasks.begin(); it != tasks.end(); it++)  (*it) = 0;
+
+  for (int i = 0; i < pop->GetSize(); i++) {
+    if (pop->GetCell(i).IsOccupied() == false) continue;
+    if (pop->GetCell(i).GetOrganism()->GetGenotype()->GetTestFitness() > 0.0) {
+      cPhenotype & phenotype = pop->GetCell(i).GetOrganism()->GetPhenotype();
+      for (int j = 0; j < num_tasks; j++) {
+	if (phenotype.GetCurTaskCount()[j] > 0)  tasks[j] += 1;
+      }
+    }
+  }
+
+  fp << pop->GetStats().GetUpdate();
+  for (it = tasks.begin(); it != tasks.end(); it++)  fp << " " << (*it);
+  fp<<endl;
+}
+
+
+void cAnalyzeUtil::PrintTreeDepths(cPopulation * pop, ofstream & fp)
+{
+  // cycle over all genotypes
+  cGenotype * genotype = pop->GetGenebank().GetBestGenotype();
+  for (int i = 0; i < pop->GetGenebank().GetSize(); i++) {
+    fp << genotype->GetID() << " "             // 1
+       << genotype->GetTestFitness() << " "    // 2
+       << genotype->GetNumOrganisms() << " "   // 3
+       << genotype->GetDepth() << " "          // 4
+       << endl;
+
+    // ...and advance to the next genotype...
+    genotype = genotype->GetNext();
+  }
+}
+
+
+void cAnalyzeUtil::PrintDepthHistogram(ofstream & fp, cPopulation * pop)
+{
+  // Output format:    update  min  max  histogram_values...
+  int min = INT_MAX;
+  int max = 0;
+  assert(fp.good());
+
+  // Two pass method
+
+  // Loop through all genotypes getting min and max values
+  cGenebank & genebank = pop->GetGenebank();
+  cGenotype * cur_genotype = genebank.GetBestGenotype();
+  for (int i = 0; i < genebank.GetSize(); i++) {
+    if (cur_genotype->GetDepth() < min) min = cur_genotype->GetDepth();
+    if (cur_genotype->GetDepth() > max) max = cur_genotype->GetDepth();
+    cur_genotype = cur_genotype->GetNext();
+  }
+  assert(max >= min);
+
+  // Allocate the array for the bins (& zero)
+  int * n = new int[max - min + 1];
+  for (int i = 0; i < max - min + 1; i++) n[i] = 0;
+
+  // Loop through all genotypes binning the values
+  cur_genotype = genebank.GetBestGenotype();
+  for (int i = 0; i < genebank.GetSize(); i++) {
+    n[cur_genotype->GetDepth() - min] += cur_genotype->GetNumOrganisms();
+    cur_genotype = cur_genotype->GetNext();
+  }
+
+  // Actual output
+  fp << pop->GetStats().GetUpdate() << " "
+     << min << " "
+     << max;
+
+  for (int i = 0; i < max - min + 1; i++)  fp << " " << n[i];
+  fp<<endl;
+}
+
+
+void cAnalyzeUtil::PrintGenotypeAbundanceHistogram(ofstream & fp,
+						   cPopulation * pop)
+{
+  assert(fp.good());
+
+  // Allocate array for the histogram & zero it
+  tArray <int> hist(pop->GetGenebank().GetBestGenotype()->GetNumOrganisms());
+  for (int i = 0; i < hist.GetSize(); i++) hist[i] = 0;
+
+  // Loop through all genotypes binning the values
+  cGenotype * cur_genotype = pop->GetGenebank().GetBestGenotype();
+  for (int i = 0; i < pop->GetGenebank().GetSize(); i++) {
+    assert( cur_genotype->GetNumOrganisms() - 1 >= 0 );
+    assert( cur_genotype->GetNumOrganisms() - 1 < hist.GetSize() );
+    hist[cur_genotype->GetNumOrganisms() - 1]++;
+    cur_genotype = cur_genotype->GetNext();
+  }
+
+  // Actual output
+  fp << pop->GetStats().GetUpdate() << " ";
+  for (int i = 0; i < hist.GetSize(); i++)  fp<<hist[i]<<" ";
+  fp << endl;
+}
+
+
+void cAnalyzeUtil::PrintSpeciesAbundanceHistogram(ofstream & fp,
+						  cPopulation * pop)
+{
+  int max = 0;
+  assert(fp.good());
+
+  // Find max species abundance...
+  cGenebank & genebank = pop->GetGenebank();
+  cSpecies * cur_species = genebank.GetFirstSpecies();
+  for (int i = 0; i < genebank.GetNumSpecies(); i++) {
+    if (max < cur_species->GetNumOrganisms()) {
+      max = cur_species->GetNumOrganisms();
+    }
+    cur_species = cur_species->GetNext();
+  }
+
+  // Allocate array for the histogram & zero it
+  tArray <int> hist(max);
+  for (int i = 0; i < hist.GetSize(); i++)  hist[i] = 0;
+
+  // Loop through all species binning the values
+  cur_species = genebank.GetFirstSpecies();
+  for (int i = 0; i < genebank.GetNumSpecies(); i++) {
+    assert( cur_species->GetNumOrganisms() - 1 >= 0 );
+    assert( cur_species->GetNumOrganisms() - 1 < hist.GetSize() );
+    hist[cur_species->GetNumOrganisms() -1]++;
+    cur_species = cur_species->GetNext();
+  }
+
+  // Actual output
+  fp << pop->GetStats().GetUpdate() << " ";
+  for (int i = 0; i < hist.GetSize(); i++)  fp<<hist[i]<<" ";
+  fp<<endl;
+}
+
+
+// this adds support for evan dorn's InstructionHistogramEvent.  -- kgn
+/**
+ * Count the number of each instruction present in the population.  Output
+ * this info to a log file
+ **/
+void cAnalyzeUtil::PrintInstructionAbundanceHistogram(ofstream & fp,
+                  cPopulation * pop)
+{ int i,x,y;
+  int num_inst=0;
+  int mem_size=0;
+  int * inst_counts;
+  cCPUMemory cpu_mem; // cCPUMemory is a subclass of cGenome
+  cPopulationCell cell;
+  assert(fp.good());
+
+  // ----- number of instructions available?
+  num_inst=pop->GetEnvironment().GetInstSet().GetSize();
+  inst_counts= new int[num_inst];
+
+  // ----- create and initialize counting array
+  inst_counts  = new int[num_inst];
+  for (i=0;i<num_inst;i++)
+    { inst_counts[i]=0;
+    }
+  
+  int num_cells = pop->GetSize();
+  //looping through all CPUs counting up instructions
+  for( x=0; x<num_cells; x++ )
+    { cell=pop->GetCell(x);
+      if (cell.IsOccupied())
+      {
+      // access this CPU's code block
+        cpu_mem=cell.GetOrganism()->GetHardware().GetMemory();
+        mem_size=cpu_mem.GetSize();
+        for (y=0; y<mem_size ; y++)
+    { inst_counts[(cpu_mem[y]).GetOp()]++;     
+    }  
+      }
+    }
+  
+  // ----- output instruction counts
+  for(i=0; i<num_inst; i++)
+    { fp<<inst_counts[i]<<" ";
+    }
+  fp<<endl;
+}
+
Index: avida/current/source/main/analyze_util.hh
diff -u /dev/null avida/current/source/main/analyze_util.hh:1.8
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/analyze_util.hh	Tue Nov 25 09:37:56 2003
@@ -0,0 +1,70 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef ANALYZE_UTIL_HH
+#define ANALYZE_UTIL_HH
+
+#include <fstream>
+
+class cGenome;
+class cInstSet;
+class cPopulation;
+
+// This is a static class used to do various forms of complex analysis
+// on genomes.
+
+class cAnalyzeUtil {
+private:
+public:
+  // Generic test-CPU analysis
+  static void TestGenome(const cGenome & genome, cInstSet & inst_set,
+			 std::ofstream & fp, int update);
+
+  static void TestInsSizeChangeRobustness(std::ofstream & fp,
+                 const cInstSet & inst_set, const cGenome & in_genome,
+                 int num_trials, int update);
+
+
+  // Landscape-based analysis
+  static cGenome CalcLandscape(int dist, const cGenome & genome,
+			       cInstSet & inst_set);
+  static void AnalyzeLandscape(const cGenome & genome, cInstSet & inst_set,
+			       int sample_size=1000, int min_found=0,
+			       int max_sample_size=0, int update=-1);
+  static void PairTestLandscape(const cGenome & genome, cInstSet & inst_set,
+				int sample_size=0, int update=-1);
+
+
+  // Population-wide analysis
+  static void CalcConsensus(cPopulation * population, int lines_saved);
+
+  static void AnalyzePopulation(cPopulation * pop, std::ofstream & fp,
+				double sample_prob=1, bool landscape=false,
+				bool save_genotype=false);
+
+  static void PrintDetailedFitnessData(cPopulation * pop, std::ofstream & datafp,
+    std::ofstream & histofp, std::ofstream & histo_testCPU_fp, bool save_max_f_genotype,
+    bool print_fitness_histo, double hist_fmax, double hist_fstep);
+
+  static void PrintGeneticDistanceData(cPopulation * pop, std::ofstream & fp,
+				const char *creature_name );
+  static void GeneticDistancePopDump(cPopulation * pop, std::ofstream & fp,
+		    const char * creature_name, bool save_creatures=false);
+
+  static void TaskSnapshot(cPopulation * pop, std::ofstream & fp);
+  static void PrintViableTasksData(cPopulation *pop, std::ofstream &fp);
+  static void PrintTreeDepths(cPopulation * pop, std::ofstream & fp);
+
+  static void PrintDepthHistogram(std::ofstream &fp, cPopulation * pop);
+  static void PrintGenotypeAbundanceHistogram(std::ofstream &fp, cPopulation * pop);
+  static void PrintSpeciesAbundanceHistogram(std::ofstream &fp, cPopulation * pop);
+
+  // this adds support for evan dorn's InstructionHistogramEvent.  -- kgn
+  static void PrintInstructionAbundanceHistogram(std::ofstream &fp, cPopulation * pop);
+  // -- kgn
+};
+#endif
Index: avida/current/source/main/avida.cc
diff -u /dev/null avida/current/source/main/avida.cc:1.48
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/avida.cc	Tue Nov 25 09:37:56 2003
@@ -0,0 +1,115 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef AVIDA_HH
+#include "avida.hh"
+#endif
+
+#ifndef AVIDA_DRIVER_BASE_HH
+#include "avida_driver_base.hh"
+#endif
+#ifndef CALLBACK_UTIL_HH
+#include "callback_util.hh"
+#endif
+#ifndef CONFIG_HH
+#include "config.hh"
+#endif
+#ifndef DEFS_HH
+#include "defs.hh"
+#endif
+#ifndef ENVIRONMENT_HH
+#include "environment.hh"
+#endif
+#ifndef HARDWARE_4STACK_HH
+#include "hardware_4stack.hh"
+#endif
+#ifndef HARDWARE_UTIL_HH
+#include "hardware_util.hh"
+#endif
+#ifndef HARDWARE_CPU_HH
+#include "hardware_cpu.hh"
+#endif
+#ifndef POPULATION_INTERFACE_HH
+#include "population_interface.hh"
+#endif
+#ifndef TEST_CPU_HH
+#include "test_cpu.hh"
+#endif
+
+#include <signal.h>
+#include <stdio.h>
+
+using namespace std;
+
+
+void ExitAvida(int exit_code)
+{
+  signal(SIGINT, SIG_IGN);          // Ignore all future interupts.
+  delete cAvidaDriver_Base::main_driver;
+  exit(exit_code);
+}
+
+
+void SetupAvida(int argc, char * argv[],
+		cEnvironment &environment,
+		cPopulationInterface &test_interface )
+{
+  // Catch Interrupt making sure to close appropriately
+  signal(SIGINT, ExitAvida);
+
+  // output copyright message
+  printf( "Avida version %s\nCopyright (C) 1993-2003 California Institute of Technology.\n\n", AVIDA_VERSION );
+  printf( "Avida comes with ABSOLUTELY NO WARRANTY.\n" );
+  printf( "This is free software, and you are welcome to redistribute it\nunder certain conditions. See file COPYING for details.\n\n" );
+
+  // Initialize the configuration data...
+  cConfig::Setup(argc, argv);
+  cConfig::SetupMS();
+
+  // Initialize the default environment...
+  if (environment.Load(cConfig::GetEnvironmentFilename()) == false) {
+    cerr << "Unable to load environment... aborting!" << endl;
+    ExitAvida(-1);
+  }
+
+  
+  if (cConfig::GetHardwareType() == HARDWARE_TYPE_CPU_ORIGINAL) {
+    environment.GetInstSet().SetInstLib(cHardwareCPU::GetInstLib());
+    cHardwareUtil::LoadInstSet_CPUOriginal(cConfig::GetInstFilename(),
+					   environment.GetInstSet());
+  }
+  else if (cConfig::GetHardwareType() == HARDWARE_TYPE_CPU_4STACK) {
+    environment.GetInstSet().SetInstLib(cHardware4Stack::GetInstLib());
+    cHardwareUtil::LoadInstSet_CPU4Stack(cConfig::GetInstFilename(),
+					   environment.GetInstSet());
+  }
+
+
+  cConfig::SetNumInstructions(environment.GetInstSet().GetSize());
+  cConfig::SetNumTasks(environment.GetTaskLib().GetSize());
+  cConfig::SetNumReactions(environment.GetReactionLib().GetSize());
+  cConfig::SetNumResources(environment.GetResourceLib().GetSize());
+
+  // Build a test population interface.
+  test_interface.SetFun_NewHardware(&cCallbackUtil::CB_NewHardware);
+  test_interface.SetFun_Recycle(&cCallbackUtil::CB_RecycleHardware);
+  test_interface.SetFun_Divide(&cCallbackUtil::CB_TestDivide);
+  test_interface.SetFun_GetInput(&cCallbackUtil::CB_GetInput);
+  test_interface.SetFun_GetInputAt(&cCallbackUtil::CB_GetInputAt);
+  test_interface.SetFun_GetResources(&cCallbackUtil::CB_GetResources);
+  test_interface.SetFun_UpdateResources(&cCallbackUtil::CB_UpdateResources);
+
+  // Setup the test CPUs.
+  cTestCPU::Setup( &(environment.GetInstSet()), &environment, test_interface );
+}
+
+
+
+
+
+
+
Index: avida/current/source/main/avida.hh
diff -u /dev/null avida/current/source/main/avida.hh:1.20
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/avida.hh	Tue Nov 25 09:37:56 2003
@@ -0,0 +1,32 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef AVIDA_HH
+#define AVIDA_HH
+
+class cEnvironment;
+class cPopulationInterface;
+
+/**
+ * This function properly shuts down the Avida program.
+ **/
+void ExitAvida(int exit_code);
+
+/**
+ * This function does all the command line parsing etc., sets everything
+ * up, and returns a reference to the environment that should be used.
+ *
+ * Besides the command line parameters, this function needs two more
+ * variables. One is the environment the Avida run should use (the
+ * environment is read in from disk and initialized in SetupAvida), the
+ * other is the test population interface (also initialized in SetupAvida).
+ **/
+void SetupAvida(int argc, char * argv[],
+		cEnvironment &environment,
+		cPopulationInterface &test_interface );
+
+#endif
Index: avida/current/source/main/birth_chamber.cc
diff -u /dev/null avida/current/source/main/birth_chamber.cc:1.9
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/birth_chamber.cc	Tue Nov 25 09:37:56 2003
@@ -0,0 +1,153 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BIRTH_CHAMBER_HH
+#include "birth_chamber.hh"
+#endif
+
+#ifndef GENOME_HH
+#include "genome.hh"
+#endif
+#ifndef GENOME_UTIL_HH
+#include "genome_util.hh"
+#endif
+#ifndef FUNCTIONS_HH
+#include "functions.hh"
+#endif
+#ifndef ORGANISM_HH
+#include "organism.hh"
+#endif
+#ifndef TOOLS_HH
+#include "tools.hh"
+#endif
+
+using namespace std;
+
+cBirthChamber::cBirthChamber() : genome_waiting(false)
+{
+}
+
+cBirthChamber::~cBirthChamber()
+{
+}
+
+bool cBirthChamber::SubmitOffspring(const cGenome & child_genome,
+				    const cOrganism & parent,
+				    tArray<cOrganism *> & child_array,
+				    tArray<cMerit> & merit_array)
+{
+  // Collect some info for building the child.
+  const cPopulationInterface & pop_interface = parent.PopInterface();
+  const cEnvironment & environment =
+    parent.GetPhenotype().GetEnvironment();
+  
+  if (parent.GetPhenotype().DivideSex() == false) {
+    // This is asexual who doesn't need to wait in the birth chamber
+    // just build the child and return.
+    child_array.Resize(1);
+    child_array[0] = new cOrganism(child_genome, pop_interface, environment);
+    merit_array.Resize(1);
+    merit_array[0] = parent.GetPhenotype().GetMerit();
+    return true;
+  }
+
+  // If we make it this far, it must be a sexual or a waiting, 
+  // non-recombining  asexual   
+  // See if there is anything for it to mate with.
+  if (genome_waiting == false) {
+    // There is nothing waiting!
+    wait_entry.genome = child_genome;
+    wait_entry.merit = parent.GetPhenotype().GetMerit();
+    genome_waiting = true;
+    return false;
+  }
+
+  // There is already someone in the birth chamber
+  // We must now do a crossover between the two 
+
+  genome_waiting = false;
+
+  // How many crossovers should be do? For now, 0 or 1
+  if (parent.GetPhenotype().CrossNum() ==0) {
+    child_array.Resize(2);
+    child_array[0] = new cOrganism(wait_entry.genome, pop_interface,
+				   environment);
+    child_array[1] = new cOrganism(child_genome, pop_interface, environment);
+    merit_array.Resize(2);
+    merit_array[0] = wait_entry.merit;
+    merit_array[1] = parent.GetPhenotype().GetMerit();
+    return true;
+  }
+  else {
+    cCPUMemory genome0 = wait_entry.genome;
+    cCPUMemory genome1 = child_genome;
+
+    // Crossover...
+    // get (for now) one region to cross
+    
+    double start_frac = g_random.GetDouble();
+    double end_frac = g_random.GetDouble();
+
+    if (start_frac > end_frac) Swap(start_frac, end_frac);
+
+    int start0 = (int) (start_frac * genome0.GetSize());
+    int end0   = (int) (end_frac * genome0.GetSize());
+    int start1 = (int) (start_frac * genome1.GetSize());
+    int end1   = (int) (end_frac * genome1.GetSize());
+
+    assert( start0 >= 0  &&  start0 < genome0.GetSize() );
+    assert( end0   >= 0  &&  end0   < genome0.GetSize() ); 
+    assert( start1 >= 0  &&  start1 < genome1.GetSize() );
+    assert( end1   >= 0  &&  end1   < genome1.GetSize() );
+  
+    // Calculate size of sections crossing over...
+    int size0 = end0 - start0;
+    int size1 = end1 - start1;
+  
+    int new_size0 = genome0.GetSize() - size0 + size1;
+    int new_size1 = genome1.GetSize() - size1 + size0;
+  
+    // Don't Crossover if offspring will be illegal!!!
+    if( new_size0 < MIN_CREATURE_SIZE || new_size0 > MAX_CREATURE_SIZE ||
+        new_size1 < MIN_CREATURE_SIZE || new_size1 > MAX_CREATURE_SIZE ){
+      return false;
+    }
+
+    if (size0 > 0 && size1 > 0) {
+      cGenome cross0 = cGenomeUtil::Crop(genome0, start0, end0);
+      cGenome cross1 = cGenomeUtil::Crop(genome1, start1, end1);
+      genome0.Replace(start0, size0, cross1);
+      genome1.Replace(start1, size1, cross0);
+    }
+    else if (size0 > 0) {
+      cGenome cross0 = cGenomeUtil::Crop(genome0, start0, end0);
+      genome1.Replace(start1, size1, cross0);
+    }
+    else if (size1 > 0) {
+      cGenome cross1 = cGenomeUtil::Crop(genome1, start1, end1);
+      genome0.Replace(start0, size0, cross1);
+    }
+
+    // Build the two organisms.
+    child_array.Resize(2);
+    child_array[0] = new cOrganism(genome0, pop_interface, environment);
+    child_array[1] = new cOrganism(genome1, pop_interface, environment);
+
+    double cut_frac = end_frac - start_frac;
+    double stay_frac = 1.0 - cut_frac;
+
+    double merit0 = wait_entry.merit.GetDouble();
+    double merit1 = parent.GetPhenotype().GetMerit().GetDouble();
+    merit_array.Resize(2);
+
+    merit_array[0] = stay_frac * merit0 + cut_frac * merit1;
+    merit_array[1] = stay_frac * merit1 + cut_frac * merit0;
+
+    return true;
+  }
+}
+
Index: avida/current/source/main/birth_chamber.hh
diff -u /dev/null avida/current/source/main/birth_chamber.hh:1.7
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/birth_chamber.hh	Tue Nov 25 09:37:56 2003
@@ -0,0 +1,56 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BIRTH_CHAMBER_HH
+#define BIRTH_CHAMBER_HH
+
+#ifndef CPU_MEMORY_HH
+#include "cpu_memory.hh"
+#endif
+#ifndef MERIT_HH
+#include "merit.hh"
+#endif
+
+/**
+ * All genome-based organisms must go through the birth chamber, which will
+ * handle any special modifications during the birth process, such as divide
+ * mutations reversions, sterilization, and crossover for sex.  If sex is
+ * turned on, this class will hold organisms that are waiting to be crossed
+ * over before they are born.
+ **/
+
+class cCPUMemory; // aggregate
+class cMerit; // aggregate
+class cGenome;
+class cOrganism;
+template <class T> class tArray;
+
+class cBirthChamber {
+private:
+  class cBirthEntry {
+  public:
+    cCPUMemory genome;
+    cMerit merit;
+  };
+
+  cBirthEntry wait_entry;
+
+  // For the moment, the following variable is the only one being used.
+  bool genome_waiting;  // Is there are genome waiting to be born?
+  
+public:
+  cBirthChamber();
+  ~cBirthChamber();
+
+  // Handle manipulations & tests of genome.  Return false if divide process
+  // should halt.  Place offspring in child_array.
+  bool SubmitOffspring(const cGenome & child_genome, const cOrganism & parent,
+		       tArray<cOrganism *> & child_array,
+		       tArray<cMerit> & merit_array);
+};
+
+#endif
Index: avida/current/source/main/callback_util.cc
diff -u /dev/null avida/current/source/main/callback_util.cc:1.26
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/callback_util.cc	Tue Nov 25 09:37:56 2003
@@ -0,0 +1,246 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef CALLBACK_UTIL_HH
+#include "callback_util.hh"
+#endif
+
+#ifndef AVIDA_HH
+#include "avida.hh"
+#endif
+#ifndef AVIDA_DRIVER_BASE_HH
+#include "avida_driver_base.hh"
+#endif
+#ifndef BIRTH_CHAMBER_HH
+#include "birth_chamber.hh"
+#endif
+#ifndef CONFIG_HH
+#include "config.hh"
+#endif
+#ifndef ENVIRONMENT_HH
+#include "environment.hh"
+#endif
+#ifndef GENOTYPE_HH
+#include "genotype.hh"
+#endif
+#ifndef HARDWARE_BASE_HH
+#include "hardware_base.hh"
+#endif
+#ifndef HARDWARE_FACTORY_HH
+#include "hardware_factory.hh"
+#endif
+#ifndef ORG_MESSAGE_HH
+#include "org_message.hh"
+#endif
+#ifndef ORGANISM_HH
+#include "organism.hh"
+#endif
+#ifndef POPULATION_HH
+#include "population.hh"
+#endif
+#ifndef POPULATION_CELL_HH
+#include "population_cell.hh"
+#endif
+#ifndef POPULATION_INTERFACE_HH
+#include "population_interface.hh"
+#endif
+#ifndef TEST_CPU_HH
+#include "test_cpu.hh"
+#endif
+
+
+using namespace std;
+
+
+cHardwareBase * cCallbackUtil::CB_NewHardware(cPopulation * pop,
+					      cOrganism * owner)
+{
+  cInstSet * inst_set;
+
+  // Determine which inst_set we should be using...
+  // If we're in a population, setup the inst_set properly.
+  if (pop != NULL) inst_set = &(pop->GetEnvironment().GetInstSet());
+
+  // Otherwise, use the test inst lib...
+  else inst_set = cTestCPU::GetInstSet();
+
+  // For the moment, we only have one hardware type...
+  assert(inst_set != NULL && inst_set->OK());
+  cHardwareBase * new_hardware =
+    cHardwareFactory::Create(owner, inst_set, cConfig::GetHardwareType());
+
+  return new_hardware;
+}
+
+
+void cCallbackUtil::CB_RecycleHardware(cHardwareBase * out_hardware)
+{
+  cHardwareFactory::Recycle(out_hardware);
+}
+
+
+// Callback for a divide inside of a population.  Return parent alive.
+bool cCallbackUtil::CB_Divide(cPopulation * pop, int cell_id,
+			      cOrganism * parent, cGenome & child_genome)
+{
+  assert(pop != NULL);
+  assert(parent != NULL);
+  assert(pop->GetCell(cell_id).GetOrganism() == parent);
+
+  return pop->ActivateOffspring(child_genome, *parent);
+}
+
+
+// Callback for a divide outside of a population
+bool cCallbackUtil::CB_TestDivide(cPopulation * pop, int cell_id,
+				  cOrganism * parent, cGenome & child_genome)
+{
+  assert(pop == NULL);  // Must not be in a population...
+
+  // Reset the parent from the divide
+  parent->GetPhenotype().TestDivideReset(parent->GetGenome().GetSize());
+
+  // @CAO in the future, we probably want to pass this child the test_cpu!
+
+  return true;
+}
+
+// Callback to find out if we need to run a test CPU on all divides...
+bool cCallbackUtil::CB_TestOnDivide(cPopulation * pop, int cell_id)
+{
+  assert(pop != NULL); // Must be in a population...
+  return cConfig::GetTestOnDivide();
+}
+
+cOrganism * cCallbackUtil::CB_GetNeighbor(cPopulation * pop, int cell_id)
+{
+  assert(pop != NULL);
+  cPopulationCell & cell = pop->GetCell(cell_id);
+  assert(cell.IsOccupied());
+
+  return cell.ConnectionList().GetFirst()->GetOrganism();
+}
+
+
+int cCallbackUtil::CB_GetNumNeighbors(cPopulation * pop, int cell_id)
+{
+  assert(pop != NULL);
+  cPopulationCell & cell = pop->GetCell(cell_id);
+  assert(cell.IsOccupied());
+
+  return cell.ConnectionList().GetSize();
+}
+
+
+void cCallbackUtil::CB_Rotate(cPopulation * pop, int cell_id,
+				    int direction)
+{
+  assert(pop != NULL);
+  cPopulationCell & cell = pop->GetCell(cell_id);
+  assert(cell.IsOccupied());
+
+  if (direction >= 0) cell.ConnectionList().CircNext();
+  else cell.ConnectionList().CircPrev();
+}
+
+
+void cCallbackUtil::CB_Breakpoint()
+{
+  cAvidaDriver_Base::main_driver->SignalBreakpoint();
+}
+
+
+double cCallbackUtil::CB_TestFitness(cPopulation * pop, int cell_id)
+{
+  assert(pop != NULL);
+  cPopulationCell & cell = pop->GetCell(cell_id);
+  assert(cell.IsOccupied());
+
+  return cell.GetOrganism()->GetGenotype()->GetTestFitness();
+}
+
+
+int cCallbackUtil::CB_GetInput(cPopulation * pop, int cell_id)
+{
+  if (pop == NULL) return cTestCPU::GetInput();
+  cPopulationCell & cell = pop->GetCell(cell_id);
+  assert(cell.IsOccupied());
+  return cell.GetInput();
+}
+
+int cCallbackUtil::CB_GetInputAt(cPopulation * pop, int cell_id, int & input_pointer)
+{
+  if (pop == NULL) return cTestCPU::GetInputAt(input_pointer);
+  cPopulationCell & cell = pop->GetCell(cell_id);
+  assert(cell.IsOccupied());
+  return cell.GetInputAt(input_pointer);
+}
+
+int cCallbackUtil::CB_Debug(cPopulation * pop, int cell_id)
+{
+  if (pop == NULL) return -1;
+  cPopulationCell & cell = pop->GetCell(cell_id);
+  assert(cell.IsOccupied());
+  return cell.GetOrganism()->GetGenotype()->GetID();
+}
+
+
+const tArray<double> &
+cCallbackUtil::CB_GetResources(cPopulation * pop, int cell_id)
+{
+  if (pop == NULL) return cTestCPU::GetResources();
+
+  // @CAO for the moment, ignore the possibility of local resources...
+  return pop->GetCellResources(cell_id);
+}
+
+
+void cCallbackUtil::CB_UpdateResources(cPopulation * pop, int cell_id,
+				       const tArray<double> & res_change)
+{
+  if (pop == NULL) return cTestCPU::UpdateResources(res_change);
+
+  // @CAO for the moment, ignore the possibility of local resources...
+  return pop->UpdateCellResources(res_change, cell_id);
+}
+
+
+void cCallbackUtil::CB_KillCell(cPopulation * pop, int death_id)
+{
+  assert(pop != NULL);
+  cPopulationCell & death_cell = pop->GetCell(death_id);
+  pop->KillOrganism(death_cell);
+}
+
+void cCallbackUtil::CB_KillSurroundCell(cPopulation * pop, int commie_id)
+{
+	assert (pop != NULL);
+	cPopulationCell & death_cell = pop->GetCell(commie_id);
+	pop->Kaboom(death_cell);
+}
+
+bool cCallbackUtil::CB_SendMessage(cPopulation * pop, int cell_id, cOrgMessage & mess)
+{
+  mess.SetSenderID(cell_id);
+  mess.SetTime(pop->GetUpdate());
+  cPopulationCell & cell = pop->GetCell(cell_id);
+  if(cell.ConnectionList().GetFirst() == NULL)
+    return false;
+  mess.SetRecipientID(cell.ConnectionList().GetFirst()->GetID());
+  return cell.ConnectionList().GetFirst()->GetOrganism()->ReceiveMessage(mess);
+}
+
+bool cCallbackUtil::CB_InjectParasite(cPopulation * pop, int cell_id, cOrganism * parent,
+				      const cGenome & injected_code)
+{
+  assert(pop != NULL);
+  assert(parent != NULL);
+  assert(pop->GetCell(cell_id).GetOrganism() == parent);
+
+  return pop->ActivateInject(*parent, injected_code);
+}
+
Index: avida/current/source/main/callback_util.hh
diff -u /dev/null avida/current/source/main/callback_util.hh:1.16
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/callback_util.hh	Tue Nov 25 09:37:56 2003
@@ -0,0 +1,48 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef CALLBACK_UTIL_HH
+#define CALLBACK_UTIL_HH
+
+class cGenome;
+class cHardwareBase;
+class cOrganism;
+class cPopulation;
+class cPopulationInterface;
+class cOrgMessage;
+class cCodeLabel;
+template <class T> class tArray;
+
+class cCallbackUtil {
+public:
+  // Callbacks from organism...
+  static cHardwareBase * CB_NewHardware(cPopulation * pop, cOrganism * owner);
+  static void CB_RecycleHardware(cHardwareBase * out_hardware);
+  static bool CB_Divide(cPopulation * pop, int cell_id,
+			cOrganism * parent, cGenome & child_genome);
+  static bool CB_TestDivide(cPopulation * pop, int cell_id,
+			    cOrganism * parent, cGenome & child_genome);
+  static bool CB_TestOnDivide(cPopulation * pop, int cell_id);
+  static cOrganism * CB_GetNeighbor(cPopulation * pop, int cell_id);
+  static int CB_GetNumNeighbors(cPopulation * pop, int cell_id);
+  static void CB_Rotate(cPopulation * pop, int cell_id, int direction);
+  static void CB_Breakpoint();
+  static double CB_TestFitness(cPopulation * pop, int cell_id);
+  static int CB_GetInput(cPopulation * pop, int cell_id);
+  static int CB_GetInputAt(cPopulation * pop, int cell_id, int & input_pointer);
+  static int CB_Debug(cPopulation * pop, int cell_id);
+  static const tArray<double>& CB_GetResources(cPopulation * pop, int cell_id);
+  static void CB_UpdateResources(cPopulation  * pop, int cell_id,
+				 const tArray<double> & res_change);
+  static void CB_KillCell(cPopulation * pop, int death_id);
+  static void CB_KillSurroundCell(cPopulation * pop, int commie_id);
+  static bool CB_SendMessage(cPopulation * pop, int cell_id, cOrgMessage & mess);
+  static bool CB_InjectParasite(cPopulation * pop, int cell_id, cOrganism * parent,
+				const cGenome & injected_code);
+};
+
+#endif
Index: avida/current/source/main/config.cc
diff -u /dev/null avida/current/source/main/config.cc:1.65
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/config.cc	Tue Nov 25 09:37:56 2003
@@ -0,0 +1,634 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef CONFIG_HH
+#include "config.hh"
+#endif
+
+#ifndef DEFS_HH
+#include "defs.hh"
+#endif
+#ifndef GENESIS_HH
+#include "genesis.hh"
+#endif
+#ifndef TOOLS_HH
+#include "tools.hh"
+#endif
+
+#ifndef POPULATION_DESCR_HI
+#include "cPopulation_descr.hi" // declarations and definitions
+#endif
+#ifndef POPULATION_DESCR_CI
+#include "cPopulation_descr.ci" // for event documentation
+#endif
+
+using namespace std;
+
+tList<cConfig::cConfigGroup> cConfig::group_list;
+bool cConfig::analyze_mode;
+bool cConfig::primitive_mode;
+cString cConfig::default_dir;
+cString cConfig::genesis_filename;
+cString cConfig::inst_filename;
+cString cConfig::event_filename;
+cString cConfig::analyze_filename;
+cString cConfig::env_filename;
+cString cConfig::start_creature;
+cString cConfig::clone_filename;
+cString cConfig::load_pop_filename;
+int cConfig::max_updates;
+int cConfig::max_generations;
+int cConfig::end_condition_mode;
+int cConfig::world_x;
+int cConfig::world_y;
+int cConfig::world_geometry;
+int cConfig::rand_seed;
+double cConfig::point_mut_prob;
+double cConfig::copy_mut_prob;
+double cConfig::ins_mut_prob;
+double cConfig::del_mut_prob;
+double cConfig::div_mut_prob;
+double cConfig::divide_mut_prob;
+double cConfig::divide_ins_prob;
+double cConfig::divide_del_prob;
+double cConfig::parent_mut_prob;
+int cConfig::special_mut_line;
+int cConfig::num_instructions;
+int cConfig::hardware_type;
+int cConfig::max_cpu_threads;
+double cConfig::thread_slicing_method;
+int cConfig::size_merit_method;
+int cConfig::base_size_merit;
+int cConfig::task_merit_method;
+int cConfig::max_label_exe_size;
+int cConfig::merit_time;
+int cConfig::num_tasks;
+int cConfig::num_reactions;
+int cConfig::num_resources;
+int cConfig::slicing_method;
+int cConfig::birth_method;
+int cConfig::death_method;
+int cConfig::alloc_method;
+int cConfig::divide_method;
+int cConfig::required_task;
+int cConfig::lineage_creation_method;
+int cConfig::generation_inc_method;
+int cConfig::age_limit;
+double cConfig::age_deviation;
+double cConfig::child_size_range;
+double cConfig::min_copied_lines;
+double cConfig::min_exe_lines;
+int cConfig::require_allocate;
+bool cConfig::test_on_divide;
+bool cConfig::test_sterilize;
+double cConfig::revert_fatal;
+double cConfig::revert_neg;
+double cConfig::revert_neut;
+double cConfig::revert_pos;
+double cConfig::sterilize_fatal;
+double cConfig::sterilize_neg;
+double cConfig::sterilize_neut;
+double cConfig::sterilize_pos;
+int cConfig::fail_implicit;
+int cConfig::ave_time_slice;
+int cConfig::species_threshold;
+int cConfig::threshold;
+int cConfig::genotype_print;
+int cConfig::species_print;
+int cConfig::species_recording;
+int cConfig::genotype_print_dom;
+int cConfig::test_cpu_time_mod;
+int cConfig::track_main_lineage;
+bool cConfig::log_threshold_only;
+bool cConfig::log_creatures;
+bool cConfig::log_genotypes;
+bool cConfig::log_threshold;
+bool cConfig::log_species;
+bool cConfig::log_landscape;
+bool cConfig::log_lineages;
+int cConfig::debug_level;
+int cConfig::view_mode;
+
+
+
+void cConfig::Setup(int argc, char * argv[])
+{
+  // Start with the Architecture variables...
+  cConfigGroup * arch_group = new cConfigGroup("Architecture Variables");
+  group_list.PushRear(arch_group);
+  
+  arch_group->Add(max_updates, "-1", "MAX_UPDATES",
+		  "Maximum updates to run experiment (-1 = no limit)");
+  arch_group->Add(max_generations, "-1", "MAX_GENERATIONS",
+		  "Maximum generations to run experiment (-1 = no limit)");
+  arch_group->Add(end_condition_mode, "0", "END_CONDITION_MODE",
+		  "End run when ...\n0 = MAX_UPDATES _OR_ MAX_GENERATIONS is reached\n1 = MAX_UPDATES _AND_ MAX_GENERATIONS is reached");
+  arch_group->Add(world_x, "100", "WORLD-X",
+		  "Width of the Avida world");
+  arch_group->Add(world_y, "100", "WORLD-Y",
+		  "Height of the Avida world");
+  arch_group->Add(world_geometry, "2", "WORLD_GEOMETRY",
+		  "1 = Bounded Grid\n2 = Torus");
+  arch_group->Add(rand_seed, "0", "RANDOM_SEED",
+		  "Random number seed (0 for based on time)");
+  arch_group->Add(hardware_type, "0", "HARDWARE_TYPE",
+		  "0 = Original CPUs\n1 = New, Stack-based CPUs");
+
+  // Configuration file group.
+  cConfigGroup * file_group = new cConfigGroup("Configuration Files");
+  group_list.PushRear(file_group);
+  
+  file_group->Add(default_dir, DEFAULT_DIR, "DEFAULT_DIR",
+		  "Directory in which config files are found");
+  file_group->Add(inst_filename, "inst_set.default", "INST_SET",
+		  "File containing instruction set");
+  file_group->Add(event_filename, "events.cfg", "EVENT_FILE",
+		  "File containing list of events during run");
+  file_group->Add(analyze_filename, "analyze.cfg", "ANALYZE_FILE",
+		  "File used for analysis mode");
+  file_group->Add(env_filename, "environment.cfg", "ENVIRONMENT_FILE",
+		  "File that describes the environment");
+  file_group->Add(start_creature, "organism.default", "START_CREATURE",
+		  "Organism to seed the soup");
+
+  // Reproduction group.
+  cConfigGroup * repro_group = new cConfigGroup("Birth and Death");
+  group_list.PushRear(repro_group);
+  
+  repro_group->Add(birth_method, "4", "BIRTH_METHOD",
+		   "0 = Replace random organism in neighborhood\n1 = Replace oldest organism in neighborhood\n2 = Replace largest Age/Merit in neighborhood\n3 = Place only in empty cells in neighborhood\n4 = Replace random from population (Mass Action)\n5 = Replace oldest in entire population (like Tierra)");
+  repro_group->Add(death_method, "0", "DEATH_METHOD",
+		   "0 = Never die of old age.\n1 = Die when inst executed = AGE_LIMIT (+deviation)\n2 = Die when inst executed = length*AGE_LIMIT (+dev)");
+  repro_group->Add(age_limit, "5000", "AGE_LIMIT",
+		   "Modifies DEATH_METHOD");
+  repro_group->Add(age_deviation, "0", "AGE_DEVIATION",
+		   "Creates a distribution around AGE_LIMIT");
+  repro_group->Add(alloc_method, "0", "ALLOC_METHOD",
+		   "0 = Allocated space is set to default instruction.\n1 = Set to section of dead genome (Necrophilia)\n2 = Allocated space is set to random instruction.");
+  repro_group->Add(divide_method, "1", "DIVIDE_METHOD",
+		   "0 = Divide leaves state of mother untouched.\n1 = Divide resets state of mother (after the divide, we have 2 children)\n2 = Divide resets state of current thread only(does not touch possible parasite threads)");
+  repro_group->Add(generation_inc_method, "1", "GENERATION_INC_METHOD",
+		   "0 = Only the generation of the child is\n    increased on divide.\n1 = Both the generation of the mother and child are\n    increased on divide (good with DIVIDE_METHOD 1).");
+
+
+  // Divide Restrictions Group.
+  cConfigGroup * div_group = new cConfigGroup("Divide Restrictions");
+  group_list.PushRear(div_group);
+  
+  div_group->Add(child_size_range, "2.0", "CHILD_SIZE_RANGE",
+		 "Maximal differential between child and parent sizes.");
+  div_group->Add(min_copied_lines, "0.5", "MIN_COPIED_LINES",
+		 "Code fraction which must be copied before divide.");
+  div_group->Add(min_exe_lines, "0.5", "MIN_EXE_LINES",
+		 "Code fraction which must be executed before divide.");
+  div_group->Add(require_allocate, "1", "REQUIRE_ALLOCATE",
+		 "Is a an allocate required before a divide? (0/1)");
+  div_group->Add(required_task, "-1", "REQUIRED_TASK",
+		 "Task ID required for successful divide.");
+
+
+  // Mutations Group
+  cConfigGroup * muts_group = new cConfigGroup("Mutations");
+  group_list.PushRear(muts_group);
+
+  muts_group->Add(point_mut_prob, "0.0", "POINT_MUT_PROB",
+		  "Mutation rate (per-location per update)");
+  muts_group->Add(copy_mut_prob, "0.0075", "COPY_MUT_PROB",
+		  "Mutation rate (per copy)");
+  muts_group->Add(ins_mut_prob, "0.0", "INS_MUT_PROB",
+		  "Insertion rate (per site, applied on divide)");
+  muts_group->Add(del_mut_prob, "0.0", "DEL_MUT_PROB",
+		  "Deletion rate (per site, applied on divide)");
+  muts_group->Add(div_mut_prob, "0.0", "DIV_MUT_PROB",
+		  "Mutation rate (per site, applied on divide)");
+  muts_group->Add(divide_mut_prob, "0.0", "DIVIDE_MUT_PROB",
+		  "Mutation rate (per divide)");
+  muts_group->Add(divide_ins_prob, "0.05", "DIVIDE_INS_PROB",
+		  "Insertion rate (per divide)");
+  muts_group->Add(divide_del_prob, "0.05", "DIVIDE_DEL_PROB",
+		  "Deletion rate (per divide)");
+  muts_group->Add(parent_mut_prob, "0.0", "PARENT_MUT_PROB",
+		  "Per-site, in parent, on divide");
+  muts_group->Add(special_mut_line, "-1", "SPECIAL_MUT_LINE",
+		  "If this is >= 0, ONLY this line is mutated");
+
+  
+  // Mutation reversions group
+  cConfigGroup * rev_group = new cConfigGroup("Mutation Reversion");
+  rev_group->SetComment("These slow down avida a lot, and should be set to 0.0 normally.");
+  group_list.PushRear(rev_group);
+
+  rev_group->Add(revert_fatal, "0.0", "REVERT_FATAL",
+		 "Should any mutations be reverted on birth?");
+  rev_group->Add(revert_neg, "0.0", "REVERT_DETRIMENTAL",
+		 "  0.0 to 1.0; Probability of reversion.");
+  rev_group->Add(revert_neut, "0.0", "REVERT_NEUTRAL",
+		 "");
+  rev_group->Add(revert_pos, "0.0", "REVERT_BENEFICIAL",
+		 "");
+  rev_group->Add(sterilize_fatal, "0.0", "STERILIZE_FATAL",
+		 "Should any mutations clear (kill) the organism?");
+  rev_group->Add(sterilize_neg, "0.0", "STERILIZE_DETRIMENTAL",
+		 "  0.0 to 1.0; Probability of reset.");
+  rev_group->Add(sterilize_neut, "0.0", "STERILIZE_NEUTRAL",
+		 "");
+  rev_group->Add(sterilize_pos, "0.0", "STERILIZE_BENEFICIAL",
+		 "");
+  rev_group->Add(fail_implicit, "0", "FAIL_IMPLICIT",
+		 "Should copies that failed *not* due to mutations\nbe eliminated?");
+
+
+  // Time slicing group
+  cConfigGroup * time_group = new cConfigGroup("Time Slicing");
+  group_list.PushRear(time_group);
+
+  time_group->Add(ave_time_slice, "30", "AVE_TIME_SLICE",
+		  "Ave number of insts per org per update");
+  time_group->Add(slicing_method, "2", "SLICING_METHOD",
+		  "0 = CONSTANT: all organisms get default...\n1 = PROBABILISTIC: Run _prob_ proportional to merit.\n2 = INTEGRATED: Perfectly integrated deterministic.");
+  time_group->Add(size_merit_method, "0", "SIZE_MERIT_METHOD",
+		  "0 = off (merit is independent of size)\n1 = Merit proportional to copied size\n2 = Merit prop. to executed size\n3 = Merit prop. to full size\n4 = Merit prop. to min of executed or copied size\n5 = Merit prop. to sqrt of the minimum size");
+  time_group->Add(task_merit_method, "1", "TASK_MERIT_METHOD",
+		  "0 = No task bonuses\n1 = Bonus just equals the task bonus");
+  time_group->Add(max_cpu_threads, "1", "MAX_CPU_THREADS",
+		  "Number of Threads a CPU can spawn");
+  time_group->Add(thread_slicing_method, "0", "THREAD_SLICING_METHOD",
+		  "Formula for and organism's thread slicing -> 1 + (num_organism_threads-1) * THREAD_SLICING_METHOD.\n0 = One thread executed per time slice.\n1 = All threads executed each time slice.\n");
+  time_group->Add(max_label_exe_size, "1", "MAX_LABEL_EXE_SIZE",
+		  "Max nops marked as executed when labels are used");
+  time_group->Add(base_size_merit, "0", "BASE_SIZE_MERIT",
+		  "Base merit when size is *not* used");
+  time_group->Add(merit_time, "0", "MERIT_TIME",
+		  "0 = Merit Calculated when task completed\n1 = Merit Calculated on Divide");
+
+
+  // Geneology group
+  cConfigGroup * gen_group = new cConfigGroup("Geneology");
+  group_list.PushRear(gen_group);
+
+  gen_group->Add(track_main_lineage, "0", "TRACK_MAIN_LINEAGE",
+		 "Track primary lineage leading to final population?");
+  gen_group->Add(threshold, "3", "THRESHOLD",
+		 "Number of organisms in a genotype needed for it\n  to be considered viable.");
+  gen_group->Add(genotype_print, "0", "GENOTYPE_PRINT",
+		 "0/1 (off/on) Print out all threshold genotypes?");
+  gen_group->Add(genotype_print_dom, "0", "GENOTYPE_PRINT_DOM",
+		 "Print out a genotype if it stays dominant for\n  this many updates. (0 = off)");
+  gen_group->Add(species_threshold, "2", "SPECIES_THRESHOLD",
+		 "max failure count for organisms to be same species");
+  gen_group->Add(species_recording, "0", "SPECIES_RECORDING",
+		 "1 = full, 2 = limited search (parent only)");
+  gen_group->Add(species_print, "0", "SPECIES_PRINT",
+		 "0/1 (off/on) Print out all species?");
+  gen_group->Add(test_cpu_time_mod, "20", "TEST_CPU_TIME_MOD",
+		 "Time allocated in test CPUs (multiple of length)");
+  
+
+  // Log Files group
+  cConfigGroup * log_group = new cConfigGroup("Log Files");
+  group_list.PushRear(log_group);
+
+  log_group->Add(log_creatures, "0", "LOG_CREATURES",
+		 "0/1 (off/on) toggle to print file.");
+  log_group->Add(log_genotypes, "0", "LOG_GENOTYPES",
+		 "0 = off, 1 = print ALL, 2 = print threshold ONLY.");
+  log_group->Add(log_threshold, "0", "LOG_THRESHOLD",
+		 "0/1 (off/on) toggle to print file.");
+  log_group->Add(log_species, "0", "LOG_SPECIES",
+		 "0/1 (off/on) toggle to print file.");
+  log_group->Add(log_landscape, "0", "LOG_LANDSCAPE",
+		 "0/1 (off/on) toggle to print file.");
+
+
+  // Viewer group
+  cConfigGroup * view_group = new cConfigGroup("Viewer Settings");
+  group_list.PushRear(view_group);
+
+  view_group->Add(view_mode, "0", "VIEW_MODE",
+		  "Initial viewer screen");
+
+  // Lineages group
+  cConfigGroup * lin_group = new cConfigGroup("Lineage");
+  lin_group->SetComment("NOTE: This should probably be called \"Clade\"\nThis one can slow down avida a lot. It is used to get an idea of how\noften an advantageous mutation arises, and where it goes afterwards.\nLineage creation options are.  Works only when LOG_LINEAGES is set to 1.\n  0 = manual creation (on inject, use successive integers as lineage labels).\n  1 = when a child's (potential) fitness is higher than that of its parent.\n  2 = when a child's (potential) fitness is higher than max in population.\n  3 = when a child's (potential) fitness is higher than max in dom. lineage\n*and* the child is in the dominant lineage, or (2)\n  4 = when a child's (potential) fitness is higher than max in dom. lineage\n(and that of its own lineage)\n  5 = same as child's (potential) fitness is higher than that of the\n      currently dominant organism, and also than that of any organism\n      currently in the same lineage.\n  6 = when a child's (potential) fitness is higher than any organism\n      currently in the same lineage.\n  7 = when a child's (potential) fitness is higher than that of any\n      organism in its line of descent");
+
+  group_list.PushRear(lin_group);
+
+  lin_group->Add(log_lineages, "0", "LOG_LINEAGES",
+		 "");
+  lin_group->Add(lineage_creation_method, "0", "LINEAGE_CREATION_METHOD",
+		 "");
+
+  /***
+   * Load all of the variables from genesis.
+   ***/
+
+  default_dir = DEFAULT_DIR;
+
+  cGenesis genesis;
+  genesis.SetVerbose();
+  ProcessConfiguration(argc, argv, genesis);
+  
+  tListIterator<cConfigGroup> group_it(group_list);
+  cConfigGroup * cur_group;
+  while ((cur_group = group_it.Next()) != NULL) {
+    cur_group->LoadValues(genesis);
+  }
+
+  /***
+   * Handle any special modifications to any of the variables now that
+   * they've been loaded.
+   ***/
+
+  // The default directory should end in a '/'.
+  char dir_tail = default_dir[default_dir.GetSize() - 1];
+  if (dir_tail != '\\' && dir_tail != '/') default_dir += "/";
+
+  // Determine if any variables were set that require test CPUs to be run
+  // at every divide.
+  test_on_divide = false;
+  if ((revert_fatal > 0.0) || (revert_neg > 0.0) || (revert_neut > 0.0) ||
+      (revert_pos > 0.0) || (fail_implicit > 0)) {
+    test_on_divide = true;
+  }
+
+  test_sterilize = false;
+  if ((sterilize_fatal > 0.0) || (sterilize_neg > 0.0) ||
+      (sterilize_neut > 0.0) || (sterilize_pos > 0.0)) {
+    test_sterilize = true;
+  }
+
+  // Determine if we are only logging threshold genotypes...
+  log_threshold_only = false;
+  if (log_genotypes > 1) log_threshold_only = true;
+
+  // Warn if there are settings in the genesis file that have not been read.
+  genesis.WarnUnused();
+
+  // Test printing... @CAO
+  //  PrintGenesis("genesis.test");
+}
+
+void cConfig::SetupMS()
+{
+#ifdef PLATFORM_WINDOWS
+  OSVERSIONINFO	osVersion;
+
+  SetFileApisToOEM();             // use console character set for files
+  memset (&osVersion, 0, sizeof (osVersion));
+  osVersion.dwOSVersionInfoSize = sizeof (osVersion);
+  GetVersionEx (&osVersion);
+  if (osVersion.dwPlatformId == VER_PLATFORM_WIN32_NT) {
+    // Only need to set Code Pages for NT. Default console on Win95 is OEM.
+    // In fact, these APIs fail on Win95 w/ rc = 120 (API only works in NT
+    //  mode).
+    if (!SetConsoleCP (GetOEMCP()))        // and for Console input
+      cerr << "WARNING: Unable to set input character set, rc="
+	   << GetLastError() << endl;
+    if (!SetConsoleOutputCP (GetOEMCP()))  // and for Console output
+      cerr << "WARNING: Unable to set output character set, rc="
+	   << GetLastError() << endl;
+  }
+#endif
+}
+
+void cConfig::PrintGenesis(const cString & filename)
+{
+  ofstream fp(filename);
+
+  // Print out the generic header, including the version ID.
+  fp << "#############################################################################" << endl
+     << "# This file includes all the basic run-time defines for avida." << endl
+     << "# For more information, see doc/genesis.html" << endl
+     << "#############################################################################" << endl
+     << endl
+     << "VERSION_ID " << AVIDA_VERSION << "   # Do not change this value."
+     << endl;
+
+  // Loop through the groups, and print out all of the variables.
+  
+  tListIterator<cConfigGroup> group_it(group_list);
+  cConfigGroup * cur_group;
+  while ((cur_group = group_it.Next()) != NULL) {
+    // Print out the group name...
+    fp << endl;
+    fp << "### " << cur_group->GetName() << " ###" << endl;
+
+    // If we have a comment about the current group, include it.
+    for (int i = 0; i < cur_group->GetComment().GetSize(); i++) {
+      fp << "# " << cur_group->GetComment().GetLine(i) << endl;
+    }
+
+    // Print out everything for this group...
+    tListIterator<cConfigEntryBase> entry_it(cur_group->GetEntries());
+    cConfigEntryBase * cur_entry;
+
+    // First, figure out the widest entry so we know where to put comments.
+    int max_width = 0;
+    while ((cur_entry = entry_it.Next()) != NULL) {
+      int cur_width = cur_entry->GetTag().GetSize() +
+	cur_entry->GetDefault().GetSize() + 1;
+      if (cur_width > max_width) max_width = cur_width;
+    }
+
+    // Now, make a second pass printing everything.
+    entry_it.Reset();
+    while ((cur_entry = entry_it.Next()) != NULL) {
+      int cur_width = cur_entry->GetTag().GetSize() +
+ 	cur_entry->GetDefault().GetSize() + 1;
+      // Print the variable and its setting...
+      fp << cur_entry->GetTag() << " " << cur_entry->GetDefault();
+
+      // Print some spaces before the description.
+      for (int i = cur_width; i < max_width; i++) fp << " ";
+
+      // Print the first line of the description.
+      if (cur_entry->GetDesc().GetSize() == 0) {
+	fp << "  # " << endl;
+      } else {
+	fp << "  # " << cur_entry->GetDesc().GetLine(0) << endl;
+      }
+
+      // Print the remaining lines of a description.
+      for (int i = 1; i < cur_entry->GetDesc().GetSize(); i++) {
+	for (int j = 0; j < max_width; j++) fp << " ";
+	fp << "  # " << cur_entry->GetDesc().GetLine(i) << endl;
+      }
+    }
+  }
+}
+
+//  void cConfig::PerturbTaskSet(double max_factor)
+//  {
+//    default_task_lib->Perturb(max_factor);
+//  }
+
+//  void cConfig::ChangeTaskSet(double prob_change, double min_bonus,
+//  			    double max_bonus)
+//  {
+//    default_task_lib->Change(prob_change, min_bonus, max_bonus);
+//  }
+
+
+// This function takes in the genesis file and the input arguments, and puts
+// out a pointer to a built-up cGenesis object.
+
+// @COW This function depends on the inclusion of the file
+// 'vent/cPopulation_descr.ci' for the automatic event documentation.
+// If you move the function away from here, move this include as well.
+
+
+void cConfig::ProcessConfiguration(int argc, char * argv[], cGenesis & genesis)
+{
+  const cString default_filename = "genesis";
+  genesis_filename = default_filename;
+
+  int arg_num = 1;              // Argument number being looked at.
+  analyze_mode = false;         // Initialize analyze_mode tp be off.
+  primitive_mode = false;       // Initialize primitive_mode tp be off.
+
+  // Load all of the args into string objects for ease of access.
+  cString * args = new cString[argc];
+  for (int i = 0; i < argc; i++) args[i] = argv[i];
+
+
+  // -genesis option
+
+  if (argc > 1 && (args[1] == "-g" || args[1] == "-genesis")) {
+    if (argc < 3) {
+      cerr << "Need filename for genesis file used." << endl;
+      exit(0);
+    }
+    genesis_filename = args[2];
+    arg_num += 2;
+  }
+
+
+  // Open and verify the genesis file.
+
+  genesis.Open(genesis_filename);
+
+  // If we failed to open the genesis file, and we are using the default,
+  // try creating it.
+  if (genesis.IsOpen() == false && genesis_filename == default_filename) {
+    cerr << "Warning: Unable to find file '" << genesis_filename
+ 	 << "'.  Creating." << endl;
+    PrintGenesis(genesis_filename);
+    genesis.Open(genesis_filename);
+  }
+  
+  cString version_id = genesis.ReadString("VERSION_ID", "Unknown");
+  if (genesis.IsOpen() == true && version_id != AVIDA_VERSION) {
+    cerr << "/  WARNING   WARNING   WARNING   WARNING   WARNING  \\" << endl
+	 << "|   Using incorrect genesis file.                   |" << endl
+	 << "|   Version needed = \"" << AVIDA_VERSION
+	 << "\".  Version used = \"" << version_id() << "\"   |" << endl
+	 << "\\  WARNING   WARNING   WARNING   WARNING   WARNING  /" << endl
+	 << endl;
+  }
+
+  // Then scan through and process the rest of the args.
+
+  while (arg_num < argc || genesis.IsOpen() == false) {
+    cString cur_arg = genesis.IsOpen() ? static_cast<cString>( args[arg_num] )
+		      : static_cast<cString>( "--help" );
+
+    // Test against the possible inputs.
+    if (cur_arg == "-events" || cur_arg == "-e") {
+      cout << "Known events:" << endl;
+      for ( int i=0; i<cEventDescrs::num_of_events; i++ ){
+	cout << "-----  "
+	     << cEventDescrs::entries[i].GetName()
+	     << "  -----" << endl;
+	cout << cEventDescrs::entries[i].GetDescription() << endl;
+      }
+      exit(0);
+    }
+    else if (cur_arg == "--help" || cur_arg == "-help" ||
+	cur_arg == "-h"     || genesis.IsOpen() == false) {
+      cout << "Options:"<<endl
+	   << "  -g[enesis] <filename> Set genesis file to be <filename>"<<endl
+	   << "  -h[elp]               Help on options (this listing)"<<endl
+	   << "  -e[vents]             Print a list of all known events"<< endl
+	   << "  -s[eed] <value>       Set random seed to <value>"<<endl
+	   << "  -viewer <value>       Sets Viewer to <value>"<<endl
+	   << "  -v[ersion]            Prints the version number"<<endl
+	   << "  -set <name> <value>   Overide the genesis file"<<endl
+	   << "  -l[oad] <filename>    Load a clone file"<<endl
+	   << "  -loadpop <filename>   Load a saved population file (precedence over load)"<<endl
+	   << "  -a[nalyze]            Process analyze.cfg instead of normal run."<<endl
+	// <<"  -p[rimitive]          Overide viewer to be primitive."<<endl
+	   << endl;
+	
+      exit(0);
+    }
+    else if (cur_arg == "-seed" || cur_arg == "-s") {
+      int in_seed = 0;
+      if (arg_num + 1 == argc || args[arg_num + 1][0] == '-') {
+	cerr<<"Must include a number as the random seed!"<<endl;
+	exit(0);
+      } else {
+	arg_num++;  if (arg_num < argc) cur_arg = args[arg_num];
+	in_seed = cur_arg.AsInt();
+      }
+      genesis.AddInput("RANDOM_SEED", in_seed);
+    } else if (cur_arg == "-analyze" || cur_arg == "-a") {
+      analyze_mode = true;
+    } else if (cur_arg == "-primitive" || cur_arg == "-p") {
+      primitive_mode = true;
+    } else if (cur_arg == "-load" || cur_arg == "-l") {
+      if (arg_num + 1 == argc || args[arg_num + 1][0] == '-') {
+	cerr<<"Must include a filename to load from"<<endl;
+	exit(0);
+      } else {
+	arg_num++;  if (arg_num < argc) cur_arg = args[arg_num];
+	clone_filename = cur_arg;
+      }
+    } else if (cur_arg == "-loadpop" || cur_arg == "-lp") {
+      if (arg_num + 1 == argc || args[arg_num + 1][0] == '-') {
+	cerr<<"Must include a filename to load from"<<endl;
+	exit(0);
+      } else {
+	arg_num++;  if (arg_num < argc) cur_arg = args[arg_num];
+	load_pop_filename = cur_arg;
+      }
+    } else if (cur_arg == "-version" || cur_arg == "-v") {
+      cout << " by Charles Ofria" << endl;
+      cout << " designed by Charles Ofria, Chris Adami, Travis Collier, C. Titus Brown, and Claus Wilke" << endl;
+      cout << " For more information, see: http://dllab.caltech.edu/avida/" << endl;
+      exit(0);
+    } else if (cur_arg == "-set") {
+      if (arg_num + 1 == argc || arg_num + 2 == argc) {
+	cerr << "'-set' option must be followed by name and value" << endl;
+	exit(0);
+      }
+      arg_num++;  if (arg_num < argc) cur_arg = args[arg_num];
+      cString name(cur_arg);
+      arg_num++;  if (arg_num < argc) cur_arg = args[arg_num];
+      cString value(cur_arg);
+      cout << "SET " << name() << " = " << value() << endl;
+      genesis.AddInput(name(), value());
+
+    } else if (cur_arg == "-g" || cur_arg == "-genesis") {
+      cerr << "Error: -g[enesis] option must be listed first." << endl;
+      exit(0);
+    } else {
+      cerr << "Unknown Option: " << argv[arg_num] << endl
+	   << "Type: \"" << argv[0] << " -h\" for a full option list." << endl;
+      exit(0);
+    }
+
+    arg_num++;  if (arg_num < argc) cur_arg = args[arg_num];
+  }
+
+  rand_seed = genesis.ReadInt("RANDOM_SEED");
+  cout << "Random Seed: " << rand_seed;
+  g_random.ResetSeed(rand_seed);
+  if( rand_seed != g_random.GetSeed() ) cout << " -> " << g_random.GetSeed();
+  cout << endl;
+
+  delete [] args;
+}
Index: avida/current/source/main/config.hh
diff -u /dev/null avida/current/source/main/config.hh:1.58
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/config.hh	Tue Nov 25 09:37:56 2003
@@ -0,0 +1,455 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef CONFIG_HH
+#define CONFIG_HH
+
+#ifndef STRING_LIST_HH
+#include "string_list.hh"
+#endif
+#ifndef TLIST_HH
+#include "tList.hh"
+#endif
+
+#define SLICE_CONSTANT         0
+#define SLICE_PROB_MERIT       1
+#define SLICE_INTEGRATED_MERIT 2
+
+#define POSITION_CHILD_RANDOM           0
+#define POSITION_CHILD_AGE              1
+#define POSITION_CHILD_MERIT            2
+#define POSITION_CHILD_EMPTY            3
+#define NUM_LOCAL_POSITION_CHILD        4
+
+#define POSITION_CHILD_FULL_SOUP_RANDOM 4
+#define POSITION_CHILD_FULL_SOUP_ELDEST 5
+
+#define DEATH_METHOD_OFF       0
+#define DEATH_METHOD_CONST     1
+#define DEATH_METHOD_MULTIPLE  2
+
+#define ALLOC_METHOD_DEFAULT   0
+#define ALLOC_METHOD_NECRO     1
+#define ALLOC_METHOD_RANDOM    2
+
+#define DIVIDE_METHOD_OFFSPRING 0
+#define DIVIDE_METHOD_SPLIT     1
+#define DIVIDE_METHOD_BIRTH     2
+
+#define GENERATION_INC_OFFSPRING 0
+#define GENERATION_INC_BOTH      1
+
+#define TASK_MERIT_OFF         0
+#define TASK_MERIT_EXPONENTIAL 1
+#define TASK_MERIT_LINEAR      2
+
+#define SIZE_MERIT_OFF         0
+#define SIZE_MERIT_COPIED      1
+#define SIZE_MERIT_EXECUTED    2
+#define SIZE_MERIT_FULL        3
+#define SIZE_MERIT_LEAST       4
+#define SIZE_MERIT_SQRT_LEAST  5
+
+#define GEOMETRY_GLOBAL 0
+#define GEOMETRY_GRID   1
+#define GEOMETRY_TORUS  2
+
+class cString; // aggregate
+class cStringList; // aggregate
+class cGenesis;
+template <class T> class tList; // aggregate
+template <class T> class tListIterator; // aggregate
+
+class cConfig {
+protected:
+  class cConfigEntryBase {
+  protected:
+    const cString genesis_tag;
+    const cString default_value;
+    const cStringList description;
+  public:
+    cConfigEntryBase(const cString & _tag, const cString & _def,
+		     const cString & _desc)
+      : genesis_tag(_tag), default_value(_def), description(_desc, '\n') { ; }
+    virtual ~cConfigEntryBase(){}
+
+    //    virtual ~cConfigEntryBase();
+    const cString & GetTag() { return genesis_tag; }
+    const cString & GetDefault() { return default_value; }
+    const cStringList & GetDesc() { return description; }
+
+    virtual bool LoadValue(cGenesis & genesis) = 0;
+  };
+
+  template <class T> class tConfigEntry : public cConfigEntryBase {
+  private:
+    T & variable;
+  public:
+    tConfigEntry(T & _var, const cString & _def, const cString & _tag,
+		 const cString _desc)
+      : cConfigEntryBase(_tag, _def, _desc), variable(_var)
+    { ; }
+
+    bool LoadValue(cGenesis & genesis) {
+      genesis.Read(variable, genesis_tag, default_value);
+      return true;
+    }
+  };
+
+  class cConfigGroup {
+  private:
+    const cString group_name;
+    cStringList comment;
+    tList<cConfigEntryBase> group_entries;
+  public:
+    cConfigGroup(const cString & _name) : group_name(_name) { ; }
+    ~cConfigGroup() {
+      while (group_entries.GetSize() > 0) delete group_entries.Pop();
+    }
+
+    void SetComment(const cString & _comment) { comment.Load(_comment, '\n'); }
+
+    const cString & GetName() { return group_name; }
+    const cStringList & GetComment() { return comment; }
+    tList<cConfigEntryBase> & GetEntries() { return group_entries; }
+
+    void LoadValues(cGenesis & genesis) {
+      tListIterator<cConfigEntryBase> group_it(group_entries);
+      cConfigEntryBase * cur_entry;
+      while ((cur_entry = group_it.Next()) != NULL) {
+	cur_entry->LoadValue(genesis);
+      }
+    };
+
+    void Add(int & _var, const cString &  _def, const cString & _tag,
+	     const cString & _desc)
+    {
+      group_entries.
+	PushRear(new cConfig::tConfigEntry<int>(_var,_def,_tag,_desc));
+    }
+
+    void Add(double & _var, const cString & _def, const cString & _tag,
+	     const cString & _desc)
+    {
+      group_entries.
+	PushRear(new cConfig::tConfigEntry<double>(_var,_def,_tag,_desc));
+    }
+
+    void Add(cString & _var, const cString & _def, const cString & _tag,
+	     const cString & _desc)
+    {
+      group_entries.
+	PushRear(new cConfig::tConfigEntry<cString>(_var,_def,_tag,_desc));
+    }
+
+    void Add(bool & _var, const cString & _def, const cString & _tag,
+	     const cString & _desc)
+    {
+      group_entries.
+	PushRear(new cConfig::tConfigEntry<bool>(_var,_def,_tag,_desc));
+    }
+  };
+
+  // Collection of genesis groups...
+  static tList<cConfigGroup> group_list;
+
+  // Major Configurations
+  static bool analyze_mode;     // Should avida do only analysis work?
+  static bool primitive_mode;   // Should avida run in primitive mode?
+
+  // Config Filenames
+  static cString default_dir;
+  static cString genesis_filename;
+  static cString inst_filename;
+  static cString event_filename;
+  static cString analyze_filename;
+  static cString env_filename;
+
+  static cString start_creature;
+  static cString clone_filename;
+  static cString load_pop_filename;
+
+  // Archetecture
+  static int max_updates;
+  static int max_generations;
+  static int end_condition_mode;
+  static int world_x;
+  static int world_y;
+  static int world_geometry;
+  static int rand_seed;
+
+  // Mutations
+  static double point_mut_prob;
+  static double copy_mut_prob;
+  static double ins_mut_prob;
+  static double del_mut_prob;
+  static double div_mut_prob;
+  static double divide_mut_prob;
+  static double divide_ins_prob;
+  static double divide_del_prob;
+  static double parent_mut_prob;
+  static int special_mut_line;
+
+  // CPU Configutation
+  static int num_instructions;
+  static int hardware_type;
+  static int max_cpu_threads;
+  static double thread_slicing_method;
+
+  // Merit info
+  static int size_merit_method;
+  static int base_size_merit;
+  static int ave_time_slice;
+
+  // Task info
+  static int num_tasks;
+  static int num_reactions;
+  static int num_resources;
+
+  // Task Merit Method
+  static int task_merit_method;
+
+  static int merit_time;
+
+  // Methodology
+  static int slicing_method;
+  static int birth_method;
+  static int death_method;
+  static int alloc_method;
+  static int divide_method;
+  static int required_task;
+  static int lineage_creation_method;
+  static int generation_inc_method;
+  static int age_limit;
+  static double age_deviation;
+  static double child_size_range;
+  static double min_copied_lines;
+  static double min_exe_lines;
+  static int require_allocate;
+  static int max_label_exe_size;
+
+  // For specialized experiments -- mutation reversion.
+  static bool test_on_divide;
+  static bool test_sterilize;
+  static double revert_fatal;
+  static double revert_neg;
+  static double revert_neut;
+  static double revert_pos;
+  static double sterilize_fatal;
+  static double sterilize_neg;
+  static double sterilize_neut;
+  static double sterilize_pos;
+  static int fail_implicit;
+
+  // Genealogy & Recording
+  static int species_threshold;
+  static int threshold;
+  static int genotype_print;
+  static int species_print;
+  static int species_recording;
+  static int genotype_print_dom;
+  static int test_cpu_time_mod;
+  static int track_main_lineage;
+
+  // Log files...
+  static bool log_threshold_only;
+
+  static bool log_creatures;
+  static bool log_genotypes;
+  static bool log_threshold;
+  static bool log_species;
+  static bool log_landscape;
+  static bool log_mutations;
+  static bool log_lineages;
+
+  // Debugging
+  static int debug_level;
+
+  // Viewer
+  static int view_mode;
+
+  // Other functions...
+  static void ProcessConfiguration(int argc, char* argv[], cGenesis & genesis);
+public:
+  static void Setup(int argc, char * argv[]);
+  static void SetupMS();
+  static void PrintGenesis(const cString & filename);
+
+  // ``Get''
+  static bool GetAnalyzeMode() { return analyze_mode; }
+  static bool GetPrimitiveMode() { return primitive_mode; }
+
+  /*
+  addition to permit access to cConfig::default_dir for use in locating
+  preset_organisms subdirectory (accessed in godbox widget).
+  -- kaben.
+  */
+  static cString & GetDefaultDir() { return default_dir; }
+  /* -- kaben. */
+  
+  static cString & GetGenesisFilename() { return genesis_filename; }
+  static cString & GetInstFilename()  { return inst_filename; }
+  static cString & GetEventFilename() { return event_filename; }
+  static cString & GetAnalyzeFilename() { return analyze_filename; }
+  static cString & GetEnvironmentFilename() { return env_filename; }
+
+  static cString & GetStartCreature() { return start_creature; }
+  static cString & GetCloneFilename() { return clone_filename; }
+  static cString & GetLoadPopFilename() { return load_pop_filename; }
+
+  static int GetMaxUpdates()     { return max_updates; }
+  static int GetMaxGenerations() { return max_generations; }
+  static int GetEndConditionMode() { return end_condition_mode; }
+  static int GetWorldX()         { return world_x; }
+  static int GetWorldY()         { return world_y; }
+  static int GetWorldGeometry()  { return world_geometry; }
+  static int GetRandSeed()       { return rand_seed; }
+
+  static double GetPointMutProb()  { return point_mut_prob; }
+  static double GetCopyMutProb()   { return copy_mut_prob; }
+  static double GetInsMutProb()    { return ins_mut_prob; }
+  static double GetDelMutProb()    { return del_mut_prob; }
+  static double GetDivMutProb()    { return div_mut_prob; }
+  static double GetDivideMutProb() { return divide_mut_prob; }
+  static double GetDivideInsProb() { return divide_ins_prob; }
+  static double GetDivideDelProb() { return divide_del_prob; }
+  static double GetParentMutProb() { return parent_mut_prob; }
+  static int GetSpecialMutLine() { return special_mut_line; }  
+
+  static int GetNumInstructions() { return num_instructions; }
+  static int GetHardwareType() { return hardware_type; }
+  static int GetMaxCPUThreads() { return max_cpu_threads; }
+  static double GetThreadSlicingMethod() { return thread_slicing_method; }
+
+  static int GetSizeMeritMethod() { return size_merit_method; }
+  static int GetBaseSizeMerit()  { return base_size_merit; }
+  static int GetTaskMeritMethod() { return task_merit_method; }
+  static int GetMaxLabelExeSize() { return max_label_exe_size; }
+
+  static int GetMeritTime() { return merit_time; }
+
+  static int GetNumTasks() { return num_tasks; }
+  static int GetNumReactions() { return num_reactions; }
+  static int GetNumResources() { return num_resources; }
+
+  static int GetSlicingMethod() { return slicing_method; }
+  static int GetBirthMethod() { return birth_method; }
+  static int GetDeathMethod() { return death_method; }
+  static int GetAllocMethod() { return alloc_method; }
+  static int GetDivideMethod() { return divide_method; }
+  static int GetRequiredTask() { return required_task; }
+  static int GetLineageCreationMethod() { return lineage_creation_method; }
+  static int GetGenerationIncMethod() { return generation_inc_method; }
+  static int GetAgeLimit() { return age_limit; }
+  static double GetAgeDeviation() { return age_deviation; }
+  static double GetChildSizeRange() { return child_size_range; }
+  static double GetMinCopiedLines() { return min_copied_lines; }
+  static double GetMinExeLines() { return min_exe_lines; }
+  static int GetRequireAllocate() { return require_allocate; }
+
+  static bool GetTestOnDivide() { return test_on_divide; }
+  static bool GetTestSterilize() { return test_sterilize; }
+  static double GetRevertFatal() { return revert_fatal; }
+  static double GetRevertNeg() { return revert_neg; }
+  static double GetRevertNeut() { return revert_neut; }
+  static double GetRevertPos() { return revert_pos; }
+  static double GetSterilizeFatal() { return sterilize_fatal; }
+  static double GetSterilizeNeg() { return sterilize_neg; }
+  static double GetSterilizeNeut() { return sterilize_neut; }
+  static double GetSterilizePos() { return sterilize_pos; }
+  static int GetFailImplicit() { return fail_implicit; }
+
+
+  static int GetAveTimeslice() { return ave_time_slice; }
+  static int GetSpeciesThreshold() { return species_threshold; }
+  static int GetThreshold() { return threshold; }
+  static int GetGenotypePrint() { return genotype_print; }
+  static int GetSpeciesPrint() { return species_print; }
+  static int GetSpeciesRecording() { return species_recording; }
+  static int GetGenotypePrintDom() { return genotype_print_dom; }
+  static int GetTestCPUTimeMod() { return test_cpu_time_mod; }
+  static int GetTrackMainLineage() { return track_main_lineage; }
+
+
+  static bool GetLogThresholdOnly()  { return log_threshold_only; }
+
+  static bool GetLogCreatures() { return log_creatures; }
+  static bool GetLogGenotypes() { return log_genotypes; }
+  static bool GetLogThreshold() { return log_threshold; }
+  static bool GetLogSpecies()   { return log_species; }
+  static bool GetLogLandscape() { return log_landscape; }
+  static bool GetLogLineages()  { return log_lineages; }
+
+  static int GetDebugLevel() { return debug_level; }
+
+  static int GetViewMode() { return view_mode; }
+
+
+  // ``Set''
+  static void SetInstFilename(const cString & in_name)
+    { inst_filename = in_name; }
+  static void SetEventFilename(const cString & in_name)
+    { event_filename = in_name; }
+  static void SetAnalyzeFilename(const cString & in_name)
+    { analyze_filename = in_name; }
+  static void SetEnvironmentFilename(const cString & in_name)
+    { env_filename = in_name; }
+
+  static void SetMaxUpdates(int in_max_updates)
+    { max_updates = in_max_updates; }
+  static void SetMaxGenerations(int _in)
+    { max_generations = _in; }
+  static void SetEndConditionMode(int _in)
+    { end_condition_mode = _in; }
+
+  static void SetCopyMutProb(double _in)  { copy_mut_prob = _in; }
+  static void SetDivMutProb(double _in)  { div_mut_prob = _in; }
+  static void SetPointMutProb(double _in) { point_mut_prob = _in; }
+
+  /*
+  addition to permit tweaking of ins_mut_prob, del_mut_prob from godbox
+  widget.
+  -- kaben.
+  */
+  static void SetInsMutProb(double _in)  { ins_mut_prob = _in; }
+  static void SetDelMutProb(double _in) { del_mut_prob = _in; }
+  /* -- kaben. */
+
+  static void SetNumInstructions(int in_num_instructions)
+    { num_instructions = in_num_instructions; }
+  static void SetHardwareType(int in_htype) { hardware_type = in_htype; }
+  static void SetMaxCPUThreads(int in_threads)
+    { max_cpu_threads = in_threads; }
+
+  static void SetSizeMeritMethod(int in_merit_method)
+    { size_merit_method = in_merit_method; }
+  static void SetBaseSizeMerit(int in_base_size_merit)
+    { base_size_merit = in_base_size_merit; }
+
+  static void SetBirthMethod(int in_birth_method)
+    { birth_method = in_birth_method; }
+  static void SetDeathMethod(int in_death_method)
+    { death_method = in_death_method; }
+  static void SetAllocMethod(int in_alloc_method)
+    { alloc_method = in_alloc_method; }
+  static void SetDivideMethod(int in_divide_method)
+    { divide_method = in_divide_method; }
+  static void SetLineageCreationMethod( int in_lineage_creation_method )
+    { lineage_creation_method = in_lineage_creation_method; }
+  static void SetGenerationIncMethod(int in_generation_inc_method)
+    { generation_inc_method = in_generation_inc_method; }
+  static void SetAgeLimit(int in_age_limit) { age_limit = in_age_limit; }
+  static void SetAgeDeviation(double in_dev) { age_deviation = in_dev; }
+
+  static void SetAveTimeslice(int in_slice) { ave_time_slice = in_slice; }
+
+  static void SetNumTasks(int in_num) { num_tasks = in_num; }
+  static void SetNumReactions(int in_num) { num_reactions = in_num; }
+  static void SetNumResources(int in_num) { num_resources = in_num; }
+};
+
+#endif
Index: avida/current/source/main/environment.cc
diff -u /dev/null avida/current/source/main/environment.cc:1.19
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/environment.cc	Tue Nov 25 09:37:56 2003
@@ -0,0 +1,886 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef ENVIRONMENT_HH
+#include "environment.hh"
+#endif
+
+#ifndef INIT_FILE_HH
+#include "init_file.hh"
+#endif
+#ifndef MUTATION_MACROS_HH
+#include "mutation_macros.hh"
+#endif
+#ifndef RANDOM_HH
+#include "random.hh"
+#endif
+#ifndef REACTION_HH
+#include "reaction.hh"
+#endif
+#ifndef REACTION_MACROS_HH
+#include "reaction_macros.hh"
+#endif
+#ifndef REACTION_PROCESS_HH
+#include "reaction_process.hh"
+#endif
+#ifndef REACTION_REQUISITE_HH
+#include "reaction_requisite.hh"
+#endif
+#ifndef REACTION_RESULT_HH
+#include "reaction_result.hh"
+#endif
+#ifndef RESOURCE_HH
+#include "resource.hh"
+#endif
+#ifndef STRING_UTIL_HH
+#include "string_util.hh"
+#endif
+#ifndef TASK_ENTRY_HH
+#include "task_entry.hh"
+#endif
+#ifndef TOOLS_HH
+#include "tools.hh"
+#endif
+
+using namespace std;
+
+cEnvironment::cEnvironment()
+{
+}
+
+cEnvironment::cEnvironment(const cString & filename)
+{
+  if (Load(filename) == false) {
+    cerr << "Unable to load environment... aborting!" << endl;
+    abort();
+  }
+}
+
+bool cEnvironment::ParseSetting(cString entry, cString & var_name,
+				cString & var_value, const cString & var_type)
+{
+  // Make sure we have an actual entry to parse.
+  if (entry.GetSize() == 0) {
+    cerr << "Error: Empty setting to parse in " << var_type << endl;
+    return false;
+  }
+
+  // Collect the values...
+  var_name = entry.Pop('=');
+  var_value = entry;
+
+  // Make sure we have both a name and a value...
+  if (var_name.GetSize() == 0) {
+    cerr << "Error: No variable povided to set to '" << var_value
+	 << "' in " << var_type << endl;
+    return false;
+  }
+
+  if (var_value.GetSize() == 0) {
+    cerr << "Error: No value given for '" << var_name
+	 << "' in " << var_type << endl;
+    return false;
+  }
+
+  // Make the names case insensitive.
+  var_name.ToLower();
+
+  return true;
+}
+
+bool cEnvironment::AssertInputInt(const cString & input,
+				  const cString & name,
+				  const cString & type)
+{
+  if (input.IsNumeric() == false) {
+    cerr << "Error: In " << type << "," << name << " set to non-integer."
+	 << endl;
+    return false;
+  }
+  return true;
+}
+
+bool cEnvironment::AssertInputDouble(const cString & input,
+				     const cString & name,
+				     const cString & type)
+{
+  if (input.IsNumber() == false) {
+    cerr << "Error: In " << type << "," << name << " set to non-number."
+	 << endl;
+    return false;
+  }
+  return true;
+}
+
+bool cEnvironment::AssertInputBool(const cString & input,
+				  const cString & name,
+				  const cString & type)
+{
+  if (input.IsNumber() == false) {
+    cerr << "Error: In " << type << "," << name << " set to non-number."
+	 << endl;
+    return false;
+  }
+  int value = input.AsInt();
+  if ((value != 1) && (value != 0))  {
+    cerr << "Error: In " << type << "," << name << " set to non-bool."
+	 << endl;
+    return false;
+  }
+  return true;
+}
+
+bool cEnvironment::AssertInputValid(void * input,
+				    const cString & name,
+				    const cString & type,
+				    const cString & value)
+{
+  if (input == NULL) {
+    cerr << "Error: In " << type << ", '" << name << "' setting of '"
+	 << value << "' not found." << endl;
+    return false;
+  }
+  return true;
+}
+
+
+
+bool cEnvironment::LoadReactionProcess(cReaction * reaction, cString desc)
+{
+  //  cerr << "ENV: Loading reaction process '" << desc << "'." << endl;
+
+  cReactionProcess * new_process = reaction->AddProcess();
+
+  // Loop through all entries in description.
+  while (desc.GetSize() > 0) {
+    // Entries are divided by colons.
+    cString var_entry = desc.Pop(':');
+    cString var_name;
+    cString var_value;
+    const cString var_type =
+      cStringUtil::Stringf("reaction '%s' process", reaction->GetName()());
+
+    // Parse this entry.
+    if (!ParseSetting(var_entry, var_name, var_value, var_type)) return false;
+
+    // Now that we know we have a variable name and its value, set it!
+    if (var_name == "resource") {
+      cResource * test_resource = resource_lib.GetResource(var_value);
+      if (!AssertInputValid(test_resource, "resource", var_type, var_value)) {
+	return false;
+      }
+      new_process->SetResource(test_resource);
+    }
+    else if (var_name == "value") {
+      if (!AssertInputDouble(var_value, "value", var_type)) return false;
+      new_process->SetValue(var_value.AsDouble());
+    }
+    else if (var_name == "type") {
+      if (var_value=="add") new_process->SetType(REACTION_PROCTYPE_ADD);
+      else if (var_value=="mult") new_process->SetType(REACTION_PROCTYPE_MULT);
+      else if (var_value=="pow") new_process->SetType(REACTION_PROCTYPE_POW);
+      else {
+	cerr << "Unknown reaction process type '" << var_value
+	     << "' found in '" << reaction->GetName() << "'." << endl;
+	return false;
+      }
+    }
+    else if (var_name == "max") {
+      if (!AssertInputDouble(var_value, "max", var_type)) return false;
+      new_process->SetMaxNumber(var_value.AsDouble());
+    }
+    else if (var_name == "min") {
+      if (!AssertInputDouble(var_value, "min", var_type)) return false;
+      new_process->SetMinNumber(var_value.AsDouble());
+    }
+    else if (var_name == "frac") {
+      if (!AssertInputDouble(var_value, "frac", var_type)) return false;
+      double in_frac = var_value.AsDouble();
+      if (in_frac > 1.0) in_frac = 1.0;
+      new_process->SetMaxFraction(in_frac);
+    }
+    else if (var_name == "product") {
+      cResource * test_resource = resource_lib.GetResource(var_value);
+      if (!AssertInputValid(test_resource, "product", var_type, var_value)) {
+	return false;
+      }
+      new_process->SetProduct(test_resource);
+    }
+    else if (var_name == "conversion") {
+      if (!AssertInputDouble(var_value, "conversion", var_type)) return false;
+      new_process->SetConversion(var_value.AsDouble());
+    }
+    else if (var_name == "lethal") {
+      if (!AssertInputBool(var_value, "lethal", var_type)) 
+	return false;
+      new_process->SetLethal(var_value.AsInt());
+    }
+    else if (var_name == "detect") {
+      cResource * test_resource = resource_lib.GetResource(var_value);
+      if (!AssertInputValid(test_resource, "product", var_type, var_value)) {
+	return false;
+      }
+      new_process->SetDetect(test_resource);
+    }
+    else if (var_name == "threshold") {
+      if (!AssertInputDouble(var_value, "threshold", var_type))
+	return false;
+      new_process->SetDetectionThreshold(var_value.AsDouble());
+    }
+    else if (var_name == "detectionerror") {
+      if (!AssertInputDouble(var_value, "detectionerror", var_type)) 
+	return false;
+      new_process->SetDetectionError(var_value.AsDouble());
+    }
+    else {
+      cerr << "Error: Unknown process variable '" << var_name
+	   << "' in reaction '" << reaction->GetName() << "'" << endl;
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool cEnvironment::LoadReactionRequisite(cReaction * reaction, cString desc)
+{
+  // cerr << "ENV: Loading reaction requisite '" << desc << "'." << endl;
+
+  cReactionRequisite * new_requisite = reaction->AddRequisite();
+
+  // Loop through all entries in description.
+  while (desc.GetSize() > 0) {
+    // Entries are divided by colons.
+    cString var_entry = desc.Pop(':');
+    cString var_name;
+    cString var_value;
+    const cString var_type =
+      cStringUtil::Stringf("reaction '%s' requisite", reaction->GetName()());
+
+    // Parse this entry.
+    if (!ParseSetting(var_entry, var_name, var_value, var_type)) return false;
+
+    // Now that we know we have a variable name and its value, set it!
+    if (var_name == "reaction") {
+      cReaction * test_reaction = reaction_lib.GetReaction(var_value);
+      if (!AssertInputValid(test_reaction, "reaction", var_type, var_value)) {
+	return false;
+      }
+      new_requisite->AddReaction(test_reaction);
+    }
+    else if (var_name == "noreaction") {
+      cReaction * test_reaction = reaction_lib.GetReaction(var_value);
+      if (!AssertInputValid(test_reaction,"noreaction",var_type, var_value)) {
+	return false;
+      }
+      new_requisite->AddNoReaction(test_reaction);
+    }
+    else if (var_name == "min_count") {
+      if (!AssertInputInt(var_value, "min_count", var_type)) return false;
+      new_requisite->SetMinTaskCount(var_value.AsInt());
+    }
+    else if (var_name == "max_count") {
+      if (!AssertInputInt(var_value, "max_count", var_type)) return false;
+      new_requisite->SetMaxTaskCount(var_value.AsInt());
+    }
+    else {
+      cerr << "Error: Unknown requisite variable '" << var_name
+	   << "' in reaction '" << reaction->GetName() << "'" << endl;
+      return false;
+    }
+  }
+
+  return true;
+}
+
+
+bool cEnvironment::LoadResource(cString desc)
+{
+  cerr << "ENV: Loading resource '" << desc << "'." << endl;
+
+  if (desc.GetSize() == 0) {
+    cerr << "Warning: Resource line with no resources listed." << endl;
+    return false;
+  }
+
+  while (desc.GetSize() > 0) {
+    cString cur_resource = desc.PopWord();
+    const cString name = cur_resource.Pop(':');
+    cResource * new_resource = resource_lib.AddResource(name);
+
+    while (cur_resource.GetSize() != 0) {
+      cString var_entry = cur_resource.Pop(':');
+      cString var_name;
+      cString var_value;
+      const cString var_type = cStringUtil::Stringf("resource '%s'", name());
+
+      // Parse this entry.
+      if (!ParseSetting(var_entry, var_name, var_value, var_type)) {
+	return false;
+      }
+
+      if (var_name == "inflow") {
+	if (!AssertInputDouble(var_value, "inflow", var_type)) return false;
+	new_resource->SetInflow( var_value.AsDouble() );
+      }
+      else if (var_name == "outflow") {
+	if (!AssertInputDouble(var_value, "outflow", var_type)) return false;
+	new_resource->SetOutflow( var_value.AsDouble() );
+      }
+      else if (var_name == "initial") {
+	if (!AssertInputDouble(var_value, "initial", var_type)) return false;
+	new_resource->SetInitial( var_value.AsDouble() );
+      }
+      else if (var_name == "geometry") {
+	if (!new_resource->SetGeometry( var_value )) {
+          cerr << "Error: In " << var_type << "," << var_value << 
+	          " unknown geometry" << endl;
+          return false;
+        }
+      }
+      else if (var_name == "inflowx1" || var_name == "inflowx") {
+	if (!AssertInputInt(var_value, "inflowX1", var_type)) return false;
+	new_resource->SetInflowX1( var_value.AsInt() );
+      }
+      else if (var_name == "inflowx2") {
+	if (!AssertInputInt(var_value, "inflowX2", var_type)) return false;
+	new_resource->SetInflowX2( var_value.AsInt() );
+      }
+      else if (var_name == "inflowy1" || var_name == "inflowy") {
+	if (!AssertInputInt(var_value, "inflowY1", var_type)) return false;
+	new_resource->SetInflowY1( var_value.AsInt() );
+      }
+      else if (var_name == "inflowy2") {
+	if (!AssertInputInt(var_value, "inflowY2", var_type)) return false;
+	new_resource->SetInflowY2( var_value.AsInt() );
+      }
+      else if (var_name == "outflowx1" || var_name == "outflowx") {
+	if (!AssertInputInt(var_value, "outflowX1", var_type)) return false;
+	new_resource->SetOutflowX1( var_value.AsInt() );
+      }
+      else if (var_name == "outflowx2") {
+	if (!AssertInputInt(var_value, "outflowX2", var_type)) return false;
+	new_resource->SetOutflowX2( var_value.AsInt() );
+      }
+      else if (var_name == "outflowy1" || var_name == "outflowy") {
+	if (!AssertInputInt(var_value, "outflowY1", var_type)) return false;
+	new_resource->SetOutflowY1( var_value.AsInt() );
+      }
+      else if (var_name == "outflowy2") {
+	if (!AssertInputInt(var_value, "outflowY2", var_type)) return false;
+	new_resource->SetOutflowY2( var_value.AsInt() );
+      }
+      else if (var_name == "xdiffuse") {
+	if (!AssertInputDouble(var_value, "xdiffuse", var_type)) return false;
+	new_resource->SetXDiffuse( var_value.AsDouble() );
+      }
+      else if (var_name == "xgravity") {
+	if (!AssertInputDouble(var_value, "xgravity", var_type)) return false;
+	new_resource->SetXGravity( var_value.AsDouble() );
+      }
+      else if (var_name == "ydiffuse") {
+	if (!AssertInputDouble(var_value, "ydiffuse", var_type)) return false;
+	new_resource->SetYDiffuse( var_value.AsDouble() );
+      }
+      else if (var_name == "ygravity") {
+	if (!AssertInputDouble(var_value, "ygravity", var_type)) return false;
+	new_resource->SetYGravity( var_value.AsDouble() );
+      }
+      else {
+	cerr << "Error: Unknown variable '" << var_name
+	     << "' in resource '" << name << "'" << endl;
+	return false;
+      }
+    }
+
+    // If there are valid values for X/Y1's but not for X/Y2's assume that 
+    // the user is interested only in one point and set the X/Y2's to the
+    // same value as 
+
+    if (new_resource->GetInflowX1()>-99 && new_resource->GetInflowX2()==-99){
+         new_resource->SetInflowX2(new_resource->GetInflowX1());
+    }
+    if (new_resource->GetInflowY1()>-99 && new_resource->GetInflowY2()==-99){
+         new_resource->SetInflowY2(new_resource->GetInflowY1());
+    }
+    if (new_resource->GetOutflowX1()>-99 && new_resource->GetOutflowX2()==-99) {
+         new_resource->SetOutflowX2(new_resource->GetOutflowX1());
+    }
+    if (new_resource->GetOutflowY1()>-99 && new_resource->GetOutflowY2()==-99) {
+         new_resource->SetOutflowY2(new_resource->GetOutflowY1());
+    }
+  }
+
+  return true;
+}
+
+bool cEnvironment::LoadReaction(cString desc)
+{
+  // Make sure this reaction has a description...
+  if (desc.GetSize() == 0) {
+    cerr << "Error: Each reaction must include a name and trigger." << endl;
+    return false;
+  }
+
+  // Load in the reaction name
+  const cString name = desc.PopWord();
+  cReaction * new_reaction = reaction_lib.AddReaction(name);
+
+  // If only a name was present, assume this reaction is a pre-declaration.
+  if (desc.GetSize() == 0) {
+    // cerr << "ENV: Pre-declaring reaction '" << name << "'." << endl;
+    return true;
+  }
+
+  // Make sure this reaction hasn't already been loaded with a different
+  // definition.
+  if (new_reaction->GetTask() != NULL) {
+    cerr << "Error: Re-defining reaction '" << name << "'." << endl;
+    return false;
+  }
+
+  // Finish loading in this reaction.
+  const cString trigger = desc.PopWord();
+  cerr << "ENV: Loading reaction '" << name << "' with trigger '"
+       << trigger << "'." << endl;
+
+  // Load the task trigger
+  cTaskEntry * cur_task = task_lib.AddTask(trigger);
+  if (cur_task == NULL) {
+    cerr << "...failed to find task in cTaskLib..." << endl;
+    return false;
+  }
+  new_reaction->SetTask(cur_task);      // Attack task to reaction.
+
+  while (desc.GetSize()) {
+    cString desc_entry = desc.PopWord();      // Get the next argument
+    cString entry_type = desc_entry.Pop(':'); // Determine argument type
+    entry_type.ToLower();                     // Make case insensitive.
+
+    // Determine the type of each argument and process it.
+    if (entry_type == "process") {
+      if (LoadReactionProcess(new_reaction, desc_entry) == false) {
+	cerr << "...failed in loading reaction-process..." << endl;
+	return false;
+      }
+    }
+    else if (entry_type == "requisite") {
+      if (LoadReactionRequisite(new_reaction, desc_entry) == false) {
+	cerr << "...failed in loading reaction-requisite..." << endl;
+	return false;
+      }
+    }
+    else {
+      cerr << "Unknown entry type '" << entry_type
+  	   << "' in reaction '" << name << "'"
+  	   << endl;
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool cEnvironment::LoadMutation(cString desc)
+{
+  cerr << "ENV: Loading mutation '" << desc << "'." << endl;
+
+  // Make sure this mutation has a description...
+  if (desc.CountNumWords() < 5) {
+    cerr << "Error: Each mutation must include a name, trigger, scope, type, and rate." << endl;
+    return false;
+  }
+
+  // Load in the mutation info
+  const cString name = desc.PopWord().ToLower();
+  const cString trigger = desc.PopWord().ToLower();
+  const cString scope = desc.PopWord().ToLower();
+  const cString type = desc.PopWord().ToLower();
+  const double rate = desc.PopWord().AsDouble();
+
+  int trig_id = -1;
+  int scope_id = -1;
+  int type_id = -1;
+
+  if (trigger == "none") trig_id = MUTATION_TRIGGER_NONE;
+  else if (trigger == "update") trig_id = MUTATION_TRIGGER_UPDATE;
+  else if (trigger == "divide") trig_id = MUTATION_TRIGGER_DIVIDE;
+  else if (trigger == "parent") trig_id = MUTATION_TRIGGER_PARENT;
+  else if (trigger == "write") trig_id = MUTATION_TRIGGER_WRITE;
+  else if (trigger == "read") trig_id = MUTATION_TRIGGER_READ;
+  else if (trigger == "exec") trig_id = MUTATION_TRIGGER_EXEC;
+  else {
+    cerr << "Error: Unknown mutation trigger '" << trigger << "'." << endl;
+    return false;
+  }
+
+  if (scope == "genome") scope_id = MUTATION_SCOPE_GENOME;
+  else if (scope == "local") scope_id = MUTATION_SCOPE_LOCAL;
+  else if (scope == "prop") scope_id = MUTATION_SCOPE_PROP;
+  else if (scope == "global") scope_id = MUTATION_SCOPE_GLOBAL;
+  else if (scope == "spread") scope_id = MUTATION_SCOPE_SPREAD;
+  else {
+    cerr << "Error: Unknown mutation scope '" << scope << "'." << endl;
+    return false;
+  }
+
+  if (type == "point") type_id = MUTATION_TYPE_POINT;
+  else if (type == "insert") type_id = MUTATION_TYPE_INSERT;
+  else if (type == "delete") type_id = MUTATION_TYPE_DELETE;
+  else if (type == "head_inc") type_id = MUTATION_TYPE_HEAD_INC;
+  else if (type == "head_dec") type_id = MUTATION_TYPE_HEAD_DEC;
+  else if (type == "temp") type_id = MUTATION_TYPE_TEMP;
+  else if (type == "kill") type_id = MUTATION_TYPE_KILL;
+  else {
+    cerr << "Error: Unknown mutation type '" << type << "'." << endl;
+    return false;
+  }
+
+  // Lets do a few checks for legal combinations...
+  if (trig_id == MUTATION_TRIGGER_NONE) {
+    cerr << "Warning: Mutations with trigger 'none' will never occur." << endl;
+  }
+
+  if (scope_id == MUTATION_SCOPE_LOCAL || scope_id == MUTATION_SCOPE_PROP) {
+    if (trig_id == MUTATION_TRIGGER_DIVIDE) {
+      cerr << "Error: Offspring after divide have no " << scope
+	   << " for mutations." << endl;
+      return false;
+    }
+    if (trig_id == MUTATION_TRIGGER_UPDATE ||
+	trig_id == MUTATION_TRIGGER_PARENT) {
+      cerr << "Warning: Mutation trigger " << trigger
+	   << "has no natural positions; IP used." << endl;
+    }
+  }
+  else {  // Genome-wide scope
+    if (type_id == MUTATION_TYPE_HEAD_INC ||
+	type_id == MUTATION_TYPE_HEAD_DEC ||
+	type_id == MUTATION_TYPE_TEMP) {
+      cerr << "Error: " << scope << " scope not compatible with type "
+	   << type << "." << endl;
+      return false;
+    }
+  }
+
+  if (type_id == MUTATION_TYPE_TEMP) {
+    if (trig_id == MUTATION_TRIGGER_UPDATE ||
+	trig_id == MUTATION_TRIGGER_DIVIDE ||
+	trig_id == MUTATION_TRIGGER_PARENT ||
+	trig_id == MUTATION_TRIGGER_WRITE) {
+      cerr << "Error: " << trigger << " trigger not meaningful with type "
+	   << type << "." << endl;
+      return false;
+    }
+  }
+
+  // If we made it this far, it should be safe to build the mutation.
+  mutation_lib.AddMutation(name, trig_id, scope_id, type_id, rate);
+
+  return true;
+}
+
+bool cEnvironment::LoadSetActive(cString desc)
+{
+  cString item_type = desc.PopWord(); 
+  item_type.ToUpper();
+
+  cString item_name = desc.PopWord();
+
+  cString item_active = desc.PopWord();
+  item_active.ToUpper();
+
+  bool new_active = true;
+  if (item_active == "0" || item_active == "FALSE") new_active = false;
+
+  if (item_type == "REACTION") {
+    cReaction * cur_reaction = reaction_lib.GetReaction(item_name);
+    if (cur_reaction == NULL) {
+      cerr << "Unknown REACTION: '" << item_name << "'" << endl;
+      return false;
+    }
+    cur_reaction->SetActive(new_active);
+  } else if (item_type == "") {
+    cerr << "Format: SET_ACTIVE <type> <name> <new_status=true>" << endl;
+  } else {
+    cerr << "Error: Cannot deactivate items of type "
+	 << item_type << endl;
+    return false;
+  }
+
+  return true;
+}
+
+bool cEnvironment::LoadLine(cString line) 
+{
+  cString type = line.PopWord();      // Determine type of this entry.
+  type.ToUpper();                     // Make type case insensitive.
+
+  bool load_ok = true;
+  if (type == "RESOURCE") load_ok = LoadResource(line);
+  else if (type == "REACTION") load_ok = LoadReaction(line);
+  else if (type == "MUTATION") load_ok = LoadMutation(line);
+  else if (type == "SET_ACTIVE") load_ok = LoadSetActive(line);
+  else {
+    cerr << "Error: Unknown environment keyword '" << type << "." << endl;
+    return false;
+  }
+  
+  if (load_ok == false) {
+    cerr << "...failed in loading '" << type << "'..." << endl;
+    return false;
+  }
+
+  return true;
+}
+
+bool cEnvironment::Load(const cString & filename)
+{
+  cerr << "ENV: Loading file '" << filename << "'." << endl;
+
+  cInitFile infile(filename);
+  if (infile.Good() == false) {
+    cerr << "Error: Failed to load environment '" << filename << "'." << endl;
+    return false;
+  }
+
+  infile.Load();
+  infile.Close();
+  infile.Compress();
+
+  // cerr << "ENV: found " << infile.GetNumLines() << " commands." << endl;
+
+  for (int line_id = 0; line_id < infile.GetNumLines(); line_id++) {
+    // Load the next line from the file.
+    bool load_ok = LoadLine(infile.GetLine(line_id));
+    if (load_ok == false) return false;
+  }
+
+  // Make sure that all pre-declared reactions have been loaded correctly.
+  for (int i = 0; i < reaction_lib.GetSize(); i++) {
+    if (reaction_lib.GetReaction(i)->GetTask() == NULL) {
+      cerr << "Error: Pre-declared reaction '"
+	   << reaction_lib.GetReaction(i)->GetName()
+	   << "' never defined." << endl;
+      return false;
+    }
+  }
+
+  return true;
+}
+
+
+void cEnvironment::SetupInputs( tArray<int> & input_array ) const
+{
+  input_array.Resize(3);
+
+  // Set the top 8 bits of the input buffer...
+  input_array[0] = 15 << 24;  // 00001111
+  input_array[1] = 51 << 24;  // 00110011
+  input_array[2] = 85 << 24;  // 01010101
+
+  // And randomize the rest...
+  for (int i = 0; i < 3; i++) {
+    input_array[i] += g_random.GetUInt(1 << 24);
+  }
+}
+
+
+bool cEnvironment::TestInput( cReactionResult & result,
+			      const tBuffer<int> & inputs,
+			      const tBuffer<int> & outputs,
+			      const tArray<double> & resource_count ) const
+{
+  // @CAO nothing for the moment...
+  return false;
+}
+
+
+bool cEnvironment::TestOutput( cReactionResult & result,
+			       const tBuffer<int> & inputs,
+			       const tBuffer<int> & outputs,
+			       const tArray<int> & task_count,
+			       const tArray<int> & reaction_count,
+			       const tArray<double> & resource_count ) const
+{
+  // Do setup for reaction tests...
+  task_lib.SetupTests(inputs, outputs);
+
+  // Loop through all reactions to see if any have been triggered...
+  const int num_reactions = reaction_lib.GetSize();
+  for (int i = 0; i < num_reactions; i++) {
+    cReaction * cur_reaction = reaction_lib.GetReaction(i);
+    assert(cur_reaction != NULL);
+
+    // Only use active reactions...
+    if (cur_reaction->GetActive() == false) continue;
+
+    // Examine the task trigger associated with this reaction
+    cTaskEntry * cur_task = cur_reaction->GetTask();
+    assert(cur_task != NULL);
+    const double task_quality = task_lib.TestOutput(*cur_task);
+    const int task_id = cur_task->GetID();
+
+    // 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);
+
+    // Examine requisites on this reaction
+    if (TestRequisites(cur_reaction->GetRequisites(), task_count[task_id],
+		       reaction_count) == false) {
+      continue;
+    }
+
+    // And lets process it!
+    DoProcesses(cur_reaction->GetProcesses(), resource_count,
+		task_quality, result);
+
+    // Mark this reaction as occuring...
+    result.MarkReaction(cur_reaction->GetID());
+  }
+
+  return result.GetActive();
+}
+
+
+bool cEnvironment::TestRequisites(const tList<cReactionRequisite> & req_list,
+		  int task_count, const tArray<int> & reaction_count) const
+{
+  const int num_reqs = req_list.GetSize();
+
+  // If there are no requisites, there is nothing to meet!
+  if (num_reqs == 0) return true;
+
+  tConstListIterator<cReactionRequisite> req_it(req_list);
+  for (int i = 0; i < num_reqs; i++) {
+    // See if this requisite batch can be satisfied.
+    const cReactionRequisite * cur_req = req_it.Next();
+    bool satisfied = true;
+
+    // Have all reactions been met?
+    tConstListIterator<cReaction> reaction_it(cur_req->GetReactions());
+    while (reaction_it.Next() != NULL) {
+      int react_id = reaction_it.Get()->GetID();
+      if (reaction_count[react_id] == 0) {
+	satisfied = false;
+	break;
+      }
+    }
+    if (satisfied == false) continue;
+
+    // Have all no-reactions been met?
+    tConstListIterator<cReaction> noreaction_it(cur_req->GetNoReactions());
+    while (noreaction_it.Next() != NULL) {
+      int react_id = noreaction_it.Get()->GetID();
+      if (reaction_count[react_id] != 0) {
+	satisfied = false;
+	break;
+      }
+    }
+    if (satisfied == false) continue;
+
+    // Have all task counts been met?
+    if (task_count < cur_req->GetMinTaskCount()) continue;
+
+    // Have all reactions been met?
+    if (task_count >= cur_req->GetMaxTaskCount()) continue;
+
+    return true;
+  }
+
+  return false;
+}
+
+
+void cEnvironment::DoProcesses(const tList<cReactionProcess> & process_list,
+			       const tArray<double> & resource_count,
+			       const double task_quality,
+			       cReactionResult & result) const
+{
+  const int num_process = process_list.GetSize();
+
+  tConstListIterator<cReactionProcess> process_it(process_list);
+  for (int i = 0; i < num_process; i++) {
+    // See if this requisite batch can be satisfied.
+    const cReactionProcess * cur_process = process_it.Next();
+    const double max_consumed = cur_process->GetMaxNumber();
+    const double min_consumed = cur_process->GetMinNumber();
+
+    // Determine resource consumption
+    double consumed = 0.0;
+    cResource * in_resource = cur_process->GetResource();
+
+    // Test if infinite resource
+    if (in_resource == NULL) {
+      consumed = max_consumed;
+    }
+
+    // Otherwise we're using a finite resource
+    else {
+      const int res_id = in_resource->GetID();
+
+      consumed = resource_count[res_id] - result.GetConsumed(res_id);
+      consumed *= cur_process->GetMaxFraction();
+
+      // Make sure we're not above the maximum consumption.
+      if (consumed > max_consumed) consumed = max_consumed;
+
+      // Test if we are below the minimum consumption.
+      if (consumed < min_consumed) consumed = 0.0;
+
+      // If we don't actually have any resource to consume stop here.
+      if (consumed == 0.0) continue;
+
+      // Mark in the results the resource consumed.
+      result.Consume(res_id, consumed);
+    }
+
+    // Calculate the bonus
+    double bonus = consumed * cur_process->GetValue() * task_quality;
+
+    switch (cur_process->GetType()) {
+    case REACTION_PROCTYPE_ADD:
+      result.AddBonus(bonus);
+      break;
+    case REACTION_PROCTYPE_MULT:
+      result.MultBonus(bonus);
+      break;
+    case REACTION_PROCTYPE_POW:
+      result.MultBonus( pow(2.0, bonus) );
+      break;
+    default:
+      assert(false);  // Should not get here!
+      break;
+    };
+
+    // Determine detection events
+    cResource * detected = cur_process->GetDetect();
+    if (detected != NULL) {
+      const int detected_id = detected->GetID();
+      const double real_amount = resource_count[detected_id];
+      double estimated_amount =
+	   g_random.GetRandNormal(real_amount, cur_process->GetDetectionError()*real_amount);
+      if (estimated_amount < cur_process->GetDetectionThreshold()) {
+	result.Detect(detected_id, 0.0);		
+      } else {
+        result.Detect(detected_id, estimated_amount);
+      }
+    }
+
+    // Determine byproducts
+    cResource * product = cur_process->GetProduct();
+    if (product != NULL) {
+      int product_id = product->GetID();
+      double product_size = consumed * cur_process->GetConversion();
+      result.Produce(product_id, product_size);
+    }
+
+    result.Lethal(cur_process->GetLethal());
+  }
+}
Index: avida/current/source/main/environment.hh
diff -u /dev/null avida/current/source/main/environment.hh:1.13
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/environment.hh	Tue Nov 25 09:37:56 2003
@@ -0,0 +1,130 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef ENVIRONMENT_HH
+#define ENVIRONMENT_HH
+
+#ifndef INST_SET_HH
+#include "inst_set.hh"
+#endif
+#ifndef MUTATION_LIB_HH
+#include "mutation_lib.hh"
+#endif
+#ifndef MUTATION_RATES_HH
+#include "mutation_rates.hh"
+#endif
+#ifndef REACTION_LIB_HH
+#include "reaction_lib.hh"
+#endif
+#ifndef RESOURCE_LIB_HH
+#include "resource_lib.hh"
+#endif
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+#ifndef TASK_LIB_HH
+#include "task_lib.hh"
+#endif
+#ifndef TLIST_HH
+#include "tList.hh"
+#endif
+
+class cResourceLib; // aggregate
+class cReactionLib; // aggregate
+class cMutationLib; // aggregate
+class cTaskLib; // aggregate
+class cInstSet; // aggregate
+class cMutationRates; // aggregate
+class cString; // aggregate
+class cReaction;
+template <class T> class tList;
+class cReactionRequisite;
+template <class T> class tArray;
+class cReactionProcess;
+class cReactionResult;
+template <class T> class tBuffer;
+
+class cEnvironment {
+private:
+  // Keep libraries of resources, reactions, and tasks.
+  cResourceLib resource_lib;
+  cReactionLib reaction_lib;
+  cMutationLib mutation_lib;
+  cTaskLib task_lib;
+  cInstSet inst_set;
+  cMutationRates mut_rates;
+
+  static bool ParseSetting(cString entry, cString & var_name,
+			   cString & var_value, const cString & var_type);
+  static bool AssertInputInt(const cString & input, const cString & name,
+			     const cString & type);
+  static bool AssertInputDouble(const cString & input, const cString & name,
+				const cString & type);
+  static bool AssertInputBool(const cString & input, const cString & name,
+				const cString & type);
+  static bool AssertInputValid(void * input, const cString & name,
+			       const cString & type, const cString & value);
+
+  bool LoadReactionProcess(cReaction * reaction, cString desc);
+  bool LoadReactionRequisite(cReaction * reaction, cString desc);
+  bool LoadResource(cString desc);
+  bool LoadReaction(cString desc);
+  bool LoadMutation(cString desc);
+
+  bool LoadSetActive(cString desc);
+
+  bool TestRequisites(const tList<cReactionRequisite> & req_list,
+		      int task_count,
+		      const tArray<int> & reaction_count) const;
+  void DoProcesses(const tList<cReactionProcess> & process_list,
+		   const tArray<double> & resource_count,
+		   const double task_quality,
+		   cReactionResult & result) const;
+public:
+  cEnvironment();
+  cEnvironment(const cString & filename);
+  ~cEnvironment() { ; }
+
+  /**
+   * Reads the environment from disk.
+   **/
+  bool Load(const cString & filename);
+
+  /**
+   * Reads in a single environment configuration line
+   **/
+  bool LoadLine(cString line);
+
+  // Interaction with the organisms
+  void SetupInputs( tArray<int> & input_array ) const;
+
+  bool TestInput(  cReactionResult & result,
+		   const tBuffer<int> & inputs,
+		   const tBuffer<int> & outputs,
+		   const tArray<double> & resource_count ) const;
+
+  bool TestOutput(  cReactionResult & result,
+		    const tBuffer<int> & inputs,
+		    const tBuffer<int> & outputs,
+		    const tArray<int> & task_count,
+		    const tArray<int> & reaction_count,
+		    const tArray<double> & resource_count ) const;
+
+  // Accessors
+  const cResourceLib & GetResourceLib() const { return resource_lib; }
+  const cReactionLib & GetReactionLib() const { return reaction_lib; }
+  const cMutationLib & GetMutationLib() const { return mutation_lib; }
+  const cTaskLib & GetTaskLib() const { return task_lib; }
+  const cInstSet & GetInstSet() const { return inst_set; }
+  const cMutationRates & GetMutRates() const { return mut_rates; }
+
+  cResourceLib & GetResourceLib() { return resource_lib; }
+  cInstSet & GetInstSet() { return inst_set; }
+  cMutationRates & GetMutRates() { return mut_rates; }
+};
+
+#endif
Index: avida/current/source/main/fitness_matrix.cc
diff -u /dev/null avida/current/source/main/fitness_matrix.cc:1.21
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/fitness_matrix.cc	Tue Nov 25 09:37:56 2003
@@ -0,0 +1,669 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef FITNESS_MATRIX_HH
+#include "fitness_matrix.hh"
+#endif
+
+#ifndef INST_SET_HH
+#include "inst_set.hh"
+#endif
+
+using namespace std;
+
+
+cFitnessMatrix::cFitnessMatrix( const cGenome & code,  cInstSet * inst_set)
+  :  m_start_genotype(code), m_inst_set( inst_set ), m_DFS_MaxDepth(0),
+     m_DFS_NumRecorded(0)
+{
+  m_start_genotype.SetNumInstructions( m_inst_set->GetSize());
+  m_start_genotype.CalcFitness();
+  m_data_set.insert(m_start_genotype);
+}
+
+cFitnessMatrix::~cFitnessMatrix()
+{
+}
+
+
+
+/*
+  A wrapper routine to call the depth limited search with appropriate
+  exception catching.
+ */
+
+void cFitnessMatrix::CollectData(ofstream& log_file)
+{
+  try
+    {
+
+      log_file << endl << "DOING DEPTH LIMITED SEARCH..." << endl << endl;
+
+      time(&m_search_start_time);
+      DepthLimitedSearch(m_start_genotype, log_file);
+      time(&m_search_end_time);
+    }
+  catch(bad_alloc& alloc_failure)
+    {
+      log_file << "DLS Exception: memory allocation failure" << endl;
+    }
+  catch(exception& std_ex)
+    {
+      log_file << "DLS Exception: " << std_ex.what() <<endl;
+    }
+  catch(...)
+    {
+      log_file << "DLS Exception: " << "unrecognized exception" << endl;
+    }
+
+}
+
+
+/*
+  Statistics collected at each node:
+  ----------------------------------
+
+  numNew = number of mutants alive and above threshold that have not
+  been seen before
+
+  numVisited = number of mutants that have been seen before (alive and
+  above threshold are considered only, because these are the only ones
+  stored in the data set)
+
+  numOK = number of mutants alive and above threshold (and new)
+
+  numBelowthresh = number of mutants alive and below threshold (these
+  could have been seen before because there is no record of them)
+
+  numDead = number of non-reproducing mutants (these could have been
+  seen before because there is no record of dead mutants)
+
+  Consequently, if we sum numOK+numBelowThresh+numDead for all nodes
+  then we will get the number of _unique_ genotypes inspected
+
+*/
+
+void cFitnessMatrix::DepthLimitedSearch(const cMxCodeArray& startNode, ofstream& log_file, int currDepth)
+{
+  if (currDepth == 0)
+    {
+      m_DFSNumDead.clear();
+      m_DFSNumBelowThresh.clear();
+      m_DFSNumOK.clear();
+      m_DFSNumNew.clear();
+      m_DFSNumVisited.clear();
+      m_DFSDepth.clear();
+    }
+
+
+  log_file << "cFitnessMatrix::DepthLimitedSearch, depth = " << currDepth << endl;
+
+  currDepth++;
+  if (currDepth > m_DFS_MaxDepth) m_DFS_MaxDepth = currDepth;
+  m_DFSDepth.push_back(currDepth);
+
+  list<cMxCodeArray> theMutants;
+
+  // statistics
+  short numDead = 0, numBelowThresh = 0, numOK = 0;
+  short numVisited = 0, numNew = 0;
+
+  // get the 1 mutants of the start node
+  startNode.Get1Mutants(theMutants);
+
+  list<cMxCodeArray>::iterator list_iter;
+  vector<cMxCodeArray> deleteMutants;
+  vector<cMxCodeArray>::iterator vect_iter;
+
+  // MyCodeArrayLessThan myLess;
+
+  for (list_iter = theMutants.begin(); list_iter != theMutants.end(); list_iter++)
+    {
+      // check if its already in the data set
+
+      set<cMxCodeArray, MyCodeArrayLessThan >::iterator data_iter;
+      pair< set<cMxCodeArray, MyCodeArrayLessThan >::iterator , bool> insert_result;
+
+      cMxCodeArray test_array = *list_iter;
+
+      data_iter = m_data_set.find(test_array);
+
+      if (data_iter == m_data_set.end())
+	{
+
+	  list_iter->CalcFitness();
+	  double fitness = list_iter->GetFitness();
+	
+	  if (fitness == 0.0)
+	    {
+	      numDead++;
+	      deleteMutants.push_back(*list_iter);
+	    }
+	  else if (MutantOK(fitness))
+	    {
+	      insert_result = m_data_set.insert(*list_iter);
+
+	      numNew++;
+	      numOK++;
+	      m_DFS_NumRecorded++;
+	    }
+	  else
+	    {
+	      numBelowThresh++;
+	      deleteMutants.push_back(*list_iter);
+	    }
+	}
+      // if its already in the data set delete from the list
+      else
+	{
+	  // log_file << "Mutant already in Set!!!!" << endl;
+	  numVisited++;
+	  deleteMutants.push_back(*list_iter);
+	}
+    }
+
+  // delete the ones that are dead or already visited from list
+  for (vect_iter = deleteMutants.begin(); vect_iter != deleteMutants.end(); vect_iter++)
+    {
+      theMutants.remove(*vect_iter);
+    }
+
+  // save statistics of this node
+  m_DFSNumDead.push_back(numDead);
+  m_DFSNumBelowThresh.push_back(numBelowThresh);
+  m_DFSNumOK.push_back(numOK);
+  m_DFSNumNew.push_back(numNew);
+  m_DFSNumVisited.push_back(numVisited);
+
+  // call depth first search on each mutant in the list
+  if (currDepth < m_depth_limit)
+    {
+      for (list_iter = theMutants.begin(); list_iter != theMutants.end(); list_iter++)
+	{
+	  DepthLimitedSearch(*list_iter, log_file, currDepth);
+	}
+    }
+
+}
+
+
+bool cFitnessMatrix::MutantOK(double fitness)
+{
+  return (fitness > m_fitness_threshhold);
+}
+
+
+/*
+  Diagonaliztion via repeated multiplication by a random vector.
+  Based on Claus' diagonalize.pl
+ */
+
+double cFitnessMatrix::Diagonalize(vector<double>& randomVect, int hamDistThresh, double errorRate, ofstream& log_file)
+{
+  // first all genotypes need their transition lists
+  this->MakeTransitionProbabilities(hamDistThresh, errorRate, log_file);
+
+  log_file << endl << "DIAGONALIZING...  (error prob=" << errorRate << ")" << endl << endl;
+
+  // initialize the random vector
+  vector<double> norms;
+  MakeRandomVector(randomVect, m_data_set.size());
+
+  vector<double> result;
+  // do repeated multiplication
+  for (int i = 0; i < m_diag_iters; i++)
+    {
+      /*
+      norms.push_back(VectorNorm(randomVect));
+      VectorDivideBy(randomVect, norms.back());
+      MatrixVectorMultiply(randomVect, result);
+      randomVect = result;
+      */
+
+      MatrixVectorMultiply(randomVect, result);
+      norms.push_back(VectorNorm(result));
+      VectorDivideBy(result, norms.back());
+      randomVect = result;
+
+      log_file << "Vect Norm(" << i << "):" << norms.back() << endl;
+    }
+
+
+  return norms.back();
+}
+
+
+/*
+   Make transition lists for all the genotypes in the data set.  The
+   algorithm for building the transition lists is O(n^2) - for every
+   genotype we have to look at all the other genotypes to make its
+   transition list.
+*/
+
+
+void cFitnessMatrix::MakeTransitionProbabilities(int hamDistThresh, double errorRate, ofstream& log_file)
+{
+
+  set<cMxCodeArray, MyCodeArrayLessThan >::iterator set_iter;
+  int num = 0;
+  int trans = 0;
+
+  log_file << endl << "MAKING TRANSITION PROBABILITIES... (error prob=" << errorRate << ")" << endl << endl;
+
+  for (set_iter = m_data_set.begin(); set_iter != m_data_set.end(); set_iter++, num++)
+    {
+      trans = (*set_iter).MakeTransitionList(m_data_set, hamDistThresh, errorRate);
+      log_file << num << ") " << trans << " transitions for " << (*set_iter).AsString() << endl;
+    }
+
+}
+
+
+void cFitnessMatrix::MakeRandomVector(vector<double>& newVect, int size)
+{
+  cRandom randy(time(NULL));
+
+  /* vector should be the size of the set + 1 - because the matrix
+     also has the "other" column.  So thats why its '<='
+   */
+  for (int i = 0; i <= size; i++)
+    {
+      newVect.push_back(randy.GetDouble());
+    }
+
+}
+
+void cFitnessMatrix::VectorDivideBy(vector<double>& vect, double div)
+{
+  vector<double>::iterator vect_iter;
+
+  for(vect_iter = vect.begin(); vect_iter != vect.end(); vect_iter++)
+    {
+      *vect_iter /= div;
+    }
+}
+
+double cFitnessMatrix::VectorNorm(const vector<double> &vect)
+{
+  double norm = 0.0;
+  vector<double>::const_iterator vect_iter;
+
+  for(vect_iter = vect.begin(); vect_iter != vect.end(); vect_iter++)
+    {
+      norm = norm + (*vect_iter);
+    }
+
+  return norm;
+}
+
+
+/*
+  Perform the matrix vector multiplication using the sparse matrix
+  representation in the 'transition map' of the genotypes.  The
+  transition map has entries for every genotype that it has a non-zero
+  probability of giving birth to.
+
+  This algorithm is iterating through the columns of the matrix and
+  adding each one's contributions to the appropriate rows of the
+  resulting vector.  This is sort of the reverse of the normal row by
+  row dot product way of thinking about matrix-vector multiplication.
+
+  The true transition matrix has a last column of all zeros - the
+  probabilities that a dead genotype will give birth to a live one.
+  This is simply ignored because it doesn't effect the calculation
+  (and because we're using the actual data set to do the calculation
+  there isn't any good way to make a cMxCodeArray to represent dead
+  genotypes...)
+
+ */
+
+void cFitnessMatrix::MatrixVectorMultiply(const vector<double> &vect, vector<double>& result)
+{
+
+  result.clear();
+  result.resize(vect.size(), 0.0);
+
+  set<cMxCodeArray, MyCodeArrayLessThan >::iterator set_iter;
+
+  int column = 0;
+  for (set_iter = m_data_set.begin(); set_iter != m_data_set.end(); set_iter++, column++)
+    {
+      const map<int, double, less<int> > trans_map = (*set_iter).GetTransitionList();
+
+      map<int, double, less<int> >::const_iterator trans_iter;
+      for(trans_iter = trans_map.begin(); trans_iter != trans_map.end(); trans_iter++)
+	{
+	  int row = (*trans_iter).first;
+	  double transition_probability = (*trans_iter).second;
+
+	  result[row] += vect[column] * transition_probability;
+	}
+
+    }
+
+}
+
+void cFitnessMatrix::PrintGenotypes(ostream &fp)
+{
+  int totNumDead=0, totNumBelowThresh=0, totNumOK=0;
+  int totNumNew=0, totNumVisited=0, totDepth=0;
+  int totNumDead2=0, totNumBelowThresh2=0, totNumOK2=0;
+  int totNumNew2=0, totNumVisited2=0, totDepth2=0;
+  int numNodes;
+  float avgNumDead=0.0, avgNumBelowThresh=0.0, avgNumOK=0.0;
+  float avgNumNew=0.0, avgNumVisited=0.0, avgDepth=0.0;
+  float sdNumDead=0.0, sdNumBelowThresh=0.0, sdNumOK=0.0;
+  float sdNumNew=0.0, sdNumVisited=0.0, sdDepth=0.0;
+
+  totNumDead = accumulate(m_DFSNumDead.begin(), m_DFSNumDead.end(), 0);
+  totNumBelowThresh = accumulate(m_DFSNumBelowThresh.begin(), m_DFSNumBelowThresh.end(), 0);
+  totNumOK = accumulate(m_DFSNumOK.begin(), m_DFSNumOK.end(), 0);
+  totNumNew = accumulate(m_DFSNumNew.begin(), m_DFSNumNew.end(), 0);
+  totNumVisited = accumulate(m_DFSNumVisited.begin(), m_DFSNumVisited.end(), 0);
+  totDepth = accumulate(m_DFSDepth.begin(), m_DFSDepth.end(), 0);
+
+  numNodes = m_DFSNumDead.size();
+
+  avgNumDead = ((float)totNumDead)/((float)numNodes);
+  avgNumBelowThresh = ((float)totNumBelowThresh)/((float)numNodes);
+  avgNumOK = ((float)totNumOK)/((float)numNodes);
+  avgNumNew = ((float)totNumNew)/((float)numNodes);
+  avgNumVisited = ((float)totNumVisited)/((float)numNodes);
+  avgDepth = ((float)totDepth)/((float)numNodes);
+
+  for (int i = 0; i < numNodes; i++)
+    {
+      totNumDead2 += m_DFSNumDead[i]*m_DFSNumDead[i];
+      totNumBelowThresh2 += m_DFSNumBelowThresh[i]*m_DFSNumBelowThresh[i];
+      totNumOK2 += m_DFSNumOK[i]*m_DFSNumOK[i];
+      totNumNew2 += m_DFSNumNew[i]*m_DFSNumNew[i];
+      totNumVisited2 += m_DFSNumVisited[i]*m_DFSNumVisited[i];
+      totDepth2 += m_DFSDepth[i]*m_DFSDepth[i];
+    }
+
+  sdNumDead = sqrt( ((float)totNumDead2)/((float)numNodes)
+    - (avgNumDead*avgNumDead));
+  sdNumBelowThresh = sqrt( ((float) totNumBelowThresh2)/((float) numNodes)
+    - (avgNumBelowThresh *avgNumBelowThresh ));
+  sdNumOK =sqrt( ((float) totNumOK2)/((float) numNodes)
+    - ( avgNumOK* avgNumOK)) ;
+  sdNumNew = sqrt( ((float) totNumNew2)/((float) numNodes)
+    - (avgNumNew * avgNumNew) );
+  sdNumVisited = sqrt( ((float) totNumVisited2)/((float) numNodes)
+    - (avgNumVisited * avgNumVisited) );
+  sdDepth = sqrt( ((float) totDepth2)/((float) numNodes)
+    - (avgDepth * avgDepth) );
+
+
+  fp << "#######################################################" << endl;
+  fp << "# DEPTH FIRST SEARCH RESULTS " << endl;
+  fp << "# Depth Limit: " << m_depth_limit << endl;
+  fp << "# Fitness Threshold Ratio: " << m_fitness_threshold_ratio  << endl;
+  fp << "# Start time: " << asctime(localtime(&m_search_start_time));
+  fp << "# End Time: " << asctime(localtime(&m_search_end_time));
+  fp << "#######################################################" << endl;
+  fp << "# Total number of unique nodes checked: ";
+  fp << totNumDead + totNumOK + totNumBelowThresh << endl;
+  fp << "# Total number of unique living genotypes found: ";
+  fp << totNumOK + totNumBelowThresh << endl;
+  fp << "# Total number of unique dead genotypes found: ";
+  fp << totNumDead << endl;
+  fp << "# Total number of unique genotypes alive and below threshold found: " << endl;
+  fp << "# " << totNumBelowThresh << endl;
+  fp << "# Total number of unique genotypes alive and above threshold found: " << endl;
+  fp << "# " << totNumOK << endl;
+  fp << "# Number of Nodes Fully Explored (non-leaf, alive and above threshold): " << endl;
+  fp << "# " << numNodes << endl;
+  fp << "# Maximum Depth Visited: ";
+  fp << m_DFS_MaxDepth << endl;
+  fp << "# Number of 1-Mutants Dead at each node, avg - stand dev" << endl;
+  fp << "# " << avgNumDead << "\t\t" << sdNumDead << endl;
+  fp << "# Number of 1-Mutants Alive but Below Threshold at each node,  avg - stand dev" << endl;
+  fp << "# " << avgNumBelowThresh << "\t\t" << sdNumBelowThresh << endl;
+  fp << "# Number of 1-Mutants  alive and above threshold at each node,  avg - stand dev" << endl;
+  fp << "# " << avgNumOK << "\t\t" << sdNumOK << endl;
+  fp << "# Number of New living, above threshold, 1-Mutants at each Node, avg - stand dev" << endl;
+  fp << "# " << avgNumNew << "\t\t" << sdNumNew << endl;
+  fp << "# Number of Already found living, above threshold 1-Mutants at each Node, avg - stand dev" << endl;
+  fp << "# " << avgNumVisited << "\t\t" << sdNumVisited << endl;
+  fp << "# Depth of Nodes in search, avg - stand dev" << endl;
+  fp << "# " << avgDepth << "\t\t" << sdDepth << endl;
+  fp << "#######################################################" << endl;
+  fp << "# Fitness:" << endl;
+
+  set<cMxCodeArray, MyCodeArrayLessThan >::iterator iter;
+  for(iter = m_data_set.begin(); iter != m_data_set.end(); iter++)
+    {
+      fp << (*iter).AsString() << "\t" <<(*iter).GetFitness() << "\t" << (*iter).GetMerit() << "\t" << (*iter).GetGestationTime() << endl;
+    }
+
+  fp << "#######################################################" << endl;
+
+}
+
+/*
+  PrintTransitionList gets m_data_set.size()+1 because there is the
+  extra row at the end for the "other" category.  We also add an extra
+  row of zeros for the "other" (dead) genotypes so that we're actually
+  writing out a square matrix that can be processed by other programs
+  (Mathematica).
+
+  Note that this is actually printing the transpose of the transition
+  matrix, assuming the matrix rows represent the offspring genotypes
+  and the columns represent the parents and that the norm vector is a
+  column vector.  (as discussed with Claus in March, 2001).  But since
+  we're printing one parent genotype at a time there is just no
+  sensible way to print a column at a time...
+
+  Used for testing the diagonalization - this isn't really useful for
+  real experiments because the matrix will be thousands by thousands
+  big and printing it out is not feasible.
+
+ */
+
+void cFitnessMatrix::PrintTransitionMatrix(ostream &fp, int hamDistThresh, double errorRate, double avg_fitness, bool printMatrix)
+{
+
+  fp << endl << endl;
+  fp << "#######################################################" << endl;
+  fp << "TRANSITION PROBABILITIES" << endl;
+  fp << "#Hamming Distance Threshold" << endl;
+  fp << "# " << hamDistThresh << endl;
+  fp << "#Error Rate" << endl;
+  fp << "# " << errorRate << endl;
+  fp << "#Avg Fitness" << endl;
+  fp << "# " << avg_fitness << endl;
+  fp << "#######################################################" << endl;
+
+
+  if (printMatrix)
+    {
+      set<cMxCodeArray, MyCodeArrayLessThan >::iterator iter;
+      fp << "{" << endl;
+      int index = 0;
+      for(iter = m_data_set.begin(); iter != m_data_set.end(); iter++, index++)
+	{
+	  (*iter).PrintTransitionList(fp, m_data_set.size()+1);
+	  fp << "," << endl;
+	}
+
+
+      /*
+	Add the transition probabilities for "other" (dead) genotypes
+	so that we're actually writing out a square matrix that can be
+	processed by other programs (Mathematica)
+      */
+
+      fp << "{" ;
+      for (index = 0; index <= (int) m_data_set.size(); index++)
+	{
+	  fp << 0.0;
+	  if (index < (int) m_data_set.size())
+	    fp << " , ";
+	}
+      fp << "}" << endl;
+
+      fp << "}";
+    }
+
+}
+
+
+
+void cFitnessMatrix::PrintHammingVector(ostream& fp,const vector<double>& dataVect, double errProb, double avgFit)
+{
+  vector<double> hamVect;
+
+  for (int i = 0; i < m_start_genotype.GetSize(); i++)
+    hamVect.push_back(0.0);
+
+  set<cMxCodeArray, MyCodeArrayLessThan >::iterator data_iter;
+
+  int index = 0;
+
+  for (data_iter = m_data_set.begin(); data_iter != m_data_set.end(); data_iter++, index++)
+    {
+      int dist = m_start_genotype.HammingDistance(*data_iter);
+      hamVect[dist] += dataVect[index];
+    }
+
+
+
+  fp << errProb << "\t";
+  fp << avgFit << "\t";
+
+  vector<double>::const_iterator vect_iter;
+
+  for(vect_iter = hamVect.begin(); vect_iter != hamVect.end(); vect_iter++)
+    {
+      fp << (*vect_iter) << "\t";
+    }
+
+  fp << endl;
+
+}
+
+
+void cFitnessMatrix::PrintFitnessVector(ostream& fp,const vector<double>& dataVect, double errProb, double avgFit, double maxFit, double step)
+{
+  vector<double> fitVect;
+
+  int maxi = (int) (maxFit /step) +1;
+
+  for (int i = 0; i < maxi; i++)
+    fitVect.push_back(0.0);
+
+  set<cMxCodeArray, MyCodeArrayLessThan >::iterator data_iter;
+
+  int index = 0;
+
+  for (data_iter = m_data_set.begin(); data_iter != m_data_set.end(); data_iter++, index++)
+    {
+      double f = (*data_iter).GetFitness();
+      fitVect[(int) (f/step)] += dataVect[index];
+    }
+  // the last contribution is of fitness zero:
+  fitVect[0] += dataVect[index];
+
+
+
+  fp << errProb << "\t";
+  fp << avgFit << "\t";
+
+  vector<double>::const_iterator vect_iter;
+
+  for(vect_iter = fitVect.begin(); vect_iter != fitVect.end(); vect_iter++)
+    {
+      fp << (*vect_iter) << "\t";
+    }
+
+  fp << endl;
+
+}
+
+void cFitnessMatrix::PrintFullVector(ostream& fp,const vector<double>& dataVect, double errProb, double avgFit)
+{
+  fp << errProb << "\t";
+  fp << avgFit << "\t";
+
+  vector<double>::const_iterator vect_iter;
+
+  for(vect_iter = dataVect.begin(); vect_iter != dataVect.end(); vect_iter++)
+    {
+      fp << (*vect_iter) << "\t";
+    }
+
+  fp << endl;
+}
+
+
+
+void cFitnessMatrix::CalcFitnessMatrix( int depth_limit, double fitness_threshold_ratio, int ham_thresh, double error_rate_min, double error_rate_max, double error_rate_step, double output_start, double output_step, int diag_iters, bool write_ham_vector, bool write_full_vector )
+{
+
+  /* set parameters (TODO: read these from event list) */
+
+  m_depth_limit = depth_limit;
+  m_fitness_threshold_ratio = fitness_threshold_ratio;
+  m_ham_thresh = ham_thresh;
+  m_error_rate_min = error_rate_min;
+  m_error_rate_max = error_rate_max;
+  m_error_rate_step = error_rate_step;
+  m_diag_iters = diag_iters;
+
+  m_fitness_threshhold = m_start_genotype.GetFitness() * m_fitness_threshold_ratio;
+
+  /* open files for output */
+
+  ofstream log_file("fitness_matrix.log");
+  ofstream genotype_file("found_genotypes.dat");
+  ofstream fit_vect_file("fitness_vect.dat");
+
+  ofstream ham_vect_file;
+  if (write_ham_vector)
+    ham_vect_file.open("hamming_vect.dat");
+  ofstream full_vect_file;
+  if (write_full_vector)
+    full_vect_file.open("full_vect.dat");
+
+
+  /* do the depth first search */
+
+  CollectData(log_file);
+  PrintGenotypes(genotype_file);
+  genotype_file.close();
+
+
+  /* diagonalize transition matrices at different copy error rates */
+
+  for (double error = m_error_rate_min; error <= m_error_rate_max; error += m_error_rate_step)
+    {
+      vector<double> dataVect;
+
+      double avg_fitness = Diagonalize(dataVect, m_ham_thresh, error, log_file);
+
+      PrintFitnessVector(fit_vect_file, dataVect, error, avg_fitness, output_start, output_step);
+
+      if ( write_ham_vector )
+	PrintHammingVector(ham_vect_file, dataVect, error, avg_fitness);
+
+      if ( write_full_vector )
+	PrintFullVector(full_vect_file, dataVect, error, avg_fitness);
+
+    }
+
+
+  /* close remaining files */
+
+  log_file.close();
+  fit_vect_file.close();
+  if ( write_ham_vector )
+    ham_vect_file.close();
+  if ( write_full_vector )
+    full_vect_file.close();
+}
+
Index: avida/current/source/main/fitness_matrix.hh
diff -u /dev/null avida/current/source/main/fitness_matrix.hh:1.17
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/fitness_matrix.hh	Tue Nov 25 09:37:56 2003
@@ -0,0 +1,151 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef FITNESS_MATRIX_HH
+#define FITNESS_MATRIX_HH
+
+#include <numeric>
+#include <iomanip>
+#include <iostream>
+#include <set>
+#include <vector>
+#include <map>
+#include <list>
+#include <sys/timeb.h>
+
+#ifndef DEFS_HH
+#include "defs.hh"
+#endif
+#ifndef MX_CODE_ARRAY_HH
+#include "mx_code_array.hh"
+#endif
+#ifndef MY_CODE_ARRAY_LESS_THAN_HH
+#include "my_code_array_less_than.hh"
+#endif
+#ifndef ORGANISM_HH
+#include "organism.hh"
+#endif
+#ifndef STATS_HH
+#include "stats.hh"
+#endif
+#ifndef STRING_UTIL_HH
+#include "string_util.hh"
+#endif
+#ifndef TOOLS_HH
+#include "tools.hh"
+#endif
+
+class cGenome;
+class cInstSet;
+class MyCodeArrayLessThan;
+class cFitnessMatrix {
+private:
+
+  /* genome data */
+  cMxCodeArray m_start_genotype;
+  cInstSet *m_inst_set;
+  std::set<cMxCodeArray, MyCodeArrayLessThan > m_data_set;
+  double m_fitness_threshhold;
+
+  /* parameters for search */
+  int m_depth_limit;
+  double m_fitness_threshold_ratio;
+
+  /* parameters for diagonalization */
+  int m_ham_thresh;
+  double m_error_rate_min;
+  double m_error_rate_max;
+  double m_error_rate_step;
+  int m_diag_iters;
+
+
+  /* statistics of search */
+  std::vector<int> m_DFSNumDead;
+  std::vector<int> m_DFSNumBelowThresh;
+  std::vector<int> m_DFSNumOK;
+  std::vector<int> m_DFSNumNew;
+  std::vector<int> m_DFSNumVisited;
+  std::vector<int> m_DFSDepth;
+  int m_DFS_MaxDepth;
+  int m_DFS_NumRecorded;
+  time_t m_search_start_time;
+  time_t m_search_end_time;
+
+
+  /* Methods for Depth-Limited Search of Genotype Space */
+
+  void DepthLimitedSearch(const cMxCodeArray& startNode, std::ofstream& log_file, int currDepth=0);
+  bool MutantOK(double fitness);
+  void CollectData(std::ofstream& log_file);
+
+
+  /* Methods for Diagonalization of Transition Matrix */
+
+  double Diagonalize(std::vector<double>& randomVect, int hamDistThresh,
+                      double errorRate, std::ofstream& logfile);
+  void MakeRandomVector(std::vector<double>& newVect, int size);
+  void VectorDivideBy(std::vector<double>& vect, double div);
+  double VectorNorm(const std::vector<double> &vect);
+  void MatrixVectorMultiply(const std::vector<double>& vect, std::vector<double>& result);
+  void MakeTransitionProbabilities(int hamDistThresh, double errorRate,
+                                      std::ofstream& logfile);
+
+
+  /* Data Output */
+
+  void PrintGenotypes(std::ostream &fp);
+  void PrintTransitionMatrix(std::ostream& fp, int hamDistThresh, double errorRate, double avg_fitness, bool printMatrix=false);
+  void PrintHammingVector(std::ostream& fp,const std::vector<double>& dataVect, double errProb, double avgFit);
+  void PrintFitnessVector(std::ostream& fp,const std::vector<double>& dataVect, double errProb, double avgFit, double maxFit, double step);
+  void PrintFullVector(std::ostream& fp, const std::vector<double>& dataVect, double errProb, double avgFit);
+
+
+public:
+  cFitnessMatrix(const cGenome &, cInstSet * inst_set);
+  ~cFitnessMatrix();
+
+  /**
+   * The main entry function.
+   *
+   * @param depth_limit Limits the depth of the search
+   * (how far should we go out in Hamming distance).
+   *
+   * @param fitness_threshold_ratio Creatures with fitnesses below the
+   * starting fitness times this value are rejected
+   *
+   * @param ham_thresh The threshold for the construction of the matrix
+   * (what transitions are included).
+   *
+   * @param error_rate_min The minimum error rate for which the matrix
+   * should be diagonalized.
+   *
+   * @param error_rate_max The maximum error rate for which the matrix
+   * should be diagonalized.
+   *
+   * @param error_rate_step The interval between two error rates at which
+   * the matrix gets diagonalized.
+   *
+   * @param vect_fmax The maximum fitness to be considered in the output
+   * vector. (We output concentrations of genotypes in bins of given fitness
+   * width. This is the maximum fitness we consider).
+   *
+   * @param vect_fstep The width of the fitness bins for output.
+   *
+   * @param diag_iters The number of iterations for the diagonalization
+   * of the matrix.
+   *
+   * @param write_ham_vector Should we also write a concentration vector
+   * grouped according to Hamming distances?
+   *
+   * @param write_full_vector Should we also write the full concentration
+   * vector?
+   **/
+  void CalcFitnessMatrix( int depth_limit, double fitness_threshold_ratio, int ham_thresh, double error_rate_min, double error_rate_max, double error_rate_step, double vect_fmax, double vect_fstep, int diag_iters, bool write_ham_vector, bool write_full_vector );
+
+};
+
+#endif
Index: avida/current/source/main/genebank.cc
diff -u /dev/null avida/current/source/main/genebank.cc:1.37
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/genebank.cc	Tue Nov 25 09:37:56 2003
@@ -0,0 +1,618 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef GENEBANK_HH
+#include "genebank.hh"
+#endif
+
+#ifndef CONFIG_HH
+#include "config.hh"
+#endif
+#ifndef GENOTYPE_HH
+#include "genotype.hh"
+#endif
+#ifndef SPECIES_HH
+#include "species.hh"
+#endif
+#ifndef STATS_HH
+#include "stats.hh"
+#endif
+#ifndef TEST_UTIL_HH
+#include "test_util.hh"
+#endif
+
+
+using namespace std;
+
+
+///////////////
+//  cGenebank
+///////////////
+
+cGenebank::cGenebank(cStats & _stats)
+  : stats(_stats)
+{
+  for (int i = 0; i < MAX_CREATURE_SIZE; i++) {
+    genotype_count[i] = 0;
+  }
+
+  genotype_control = new cGenotypeControl(*this);
+  species_control  = new cSpeciesControl(*this);
+
+}
+
+cGenebank::~cGenebank()
+{
+  delete genotype_control;
+  delete species_control;
+}
+
+void cGenebank::UpdateReset()
+{
+  static int genotype_dom_time = 0;
+  static int prev_dom = -1;
+
+  cGenotype * best_genotype = GetBestGenotype();
+
+  species_control->Purge(stats);
+  if (best_genotype && best_genotype->GetID() != prev_dom) {
+    genotype_dom_time = 0;
+    prev_dom = best_genotype->GetID();
+  }
+  else {
+    genotype_dom_time++;
+    if (genotype_dom_time == cConfig::GetGenotypePrintDom()) {
+      cString filename;
+      filename.Set("genebank/%s", best_genotype->GetName()());
+      cTestUtil::PrintGenome(best_genotype->GetGenome(), 
+			     filename, best_genotype, stats.GetUpdate());
+    }
+  }
+
+//   tArray<int> hist_array(15);
+//   hist_array.SetAll(0);
+//   int total_gens = 0;
+  
+//   for (int i = 0; i < GENOTYPE_HASH_SIZE; i++) {
+//     int cur_val = active_genotypes[i].GetSize();
+//     total_gens += cur_val;
+//     if (cur_val < 15) hist_array[cur_val]++;
+//     else cout << cur_val << " ";
+//   }
+//   cout << endl;
+//   for (int i = 0; i < 15; i++) {
+//     cout << i << " : " << hist_array[i] << endl;
+//   }
+//   cout << "Total genotypes: " << total_gens << endl;
+}
+
+cString cGenebank::GetLabel(int in_size, int in_num)
+{
+  char alpha[6];
+  char full_name[12];
+  int i;
+
+  for (i = 4; i >= 0; i--) {
+    alpha[i] = (in_num % 26) + 'a';
+    in_num /= 26;
+  }
+  alpha[5] = '\0';
+
+  sprintf(full_name, "%03d-%s", in_size, alpha);
+
+  return full_name;
+}
+
+
+void cGenebank::AddGenotype(cGenotype * in_genotype, int list_num)
+{
+  assert( in_genotype != 0 );
+  
+  if (list_num < 0) list_num = FindCRC(in_genotype->GetGenome());
+  
+  active_genotypes[list_num].Push(in_genotype);
+  genotype_control->Insert(*in_genotype);
+  stats.AddGenotype(in_genotype->GetID());
+
+  // Speciation... If we are creating a new genotype here, we must
+  // initilize it to the species of its parent genotype.
+
+  cSpecies * parent_species = NULL;
+  if ( in_genotype->GetParentGenotype() != NULL) {
+    parent_species = in_genotype->GetParentGenotype()->GetSpecies();
+  }
+
+  in_genotype->SetSpecies(parent_species);
+  if (parent_species != NULL) parent_species->AddGenotype();
+}
+
+
+cGenotype * cGenebank::AddGenotype(const cGenome & in_genome,
+				   cGenotype * parent_genotype)
+{
+  int list_num = FindCRC(in_genome);
+  cGenotype * found_genotype = FindGenotype(in_genome, list_num);
+
+  if (!found_genotype) {
+    found_genotype = new cGenotype(stats.GetUpdate());
+    found_genotype->SetGenome(in_genome);
+    found_genotype->SetParent(parent_genotype);
+    
+    AddGenotype(found_genotype, list_num);
+  }
+
+  return found_genotype;
+}
+
+const cGenotype * cGenebank::FindGenotype(const cGenome & in_genome,
+				    int list_num) const
+{
+  if (list_num < 0) list_num = FindCRC(in_genome);
+
+  tConstListIterator<cGenotype> list_it(active_genotypes[list_num]);
+  while (list_it.Next() != NULL) {
+    if (list_it.GetConst()->GetGenome() == in_genome) break;
+  }
+  return list_it.GetConst();
+}
+
+cGenotype * cGenebank::FindGenotype(const cGenome & in_genome,
+				    int list_num)
+{
+  if (list_num < 0) list_num = FindCRC(in_genome);
+
+  tListIterator<cGenotype> list_it(active_genotypes[list_num]);
+  while (list_it.Next() != NULL) {
+    if (list_it.Get()->GetGenome() == in_genome) break;
+  }
+  return list_it.Get();
+}
+
+void cGenebank::RemoveGenotype(cGenotype & in_genotype)
+{
+  // If this genotype is still active, mark it no longer active and
+  // take it out of the hash table so it doesn't have any new organisms
+  // assigned to it.
+
+  if (in_genotype.GetActive() == true) {
+    int list_num = FindCRC(in_genotype.GetGenome());
+    active_genotypes[list_num].Remove(&in_genotype);
+    genotype_control->Remove(in_genotype);
+    in_genotype.Deactivate(stats.GetUpdate());
+    if (cConfig::GetTrackMainLineage()) {
+      genotype_control->InsertHistoric(in_genotype);
+    }
+  }
+
+  // If we are tracking the main lineage, we only want to delete a
+  // genotype when all of its decendents have also died out.
+
+  if (cConfig::GetTrackMainLineage()) {
+    // If  there are more offspring genotypes, hold off on deletion...
+    if (in_genotype.GetNumOffspringGenotypes() != 0) return;
+
+    // If this is a dead end, delete it and recurse up...
+    cGenotype * parent = in_genotype.GetParentGenotype();
+    if (parent != NULL) {
+      parent->RemoveOffspringGenotype();
+
+      // Test to see if we need to update the coalescent genotype.
+      const int new_coal = genotype_control->UpdateCoalescent();
+      stats.SetCoalescentGenotypeDepth(new_coal);
+      // cout << "Set coalescent to " << found_gen->GetDepth() << endl;
+
+      if (parent->GetNumOrganisms() == 0) {
+	// Regardless, run RemoveGenotype on the parent.
+	RemoveGenotype(*parent);
+      }
+    }
+
+    genotype_control->RemoveHistoric(in_genotype);
+  }
+
+  // Handle the relevent statistics...
+  stats.RemoveGenotype(in_genotype.GetID(),
+	      in_genotype.GetParentID(), in_genotype.GetParentDistance(),
+	      in_genotype.GetDepth(), in_genotype.GetTotalOrganisms(),
+              in_genotype.GetTotalParasites(),
+	      stats.GetUpdate() - in_genotype.GetUpdateBorn(),
+              in_genotype.GetLength());
+  if (in_genotype.GetThreshold()) {
+    stats.RemoveThreshold(in_genotype.GetID());
+  }
+
+
+  // Speciation...  If a Threshold genotype was removed, the position of this
+  // species in the active list will at least shift, and it is possible that
+  // the species is made inactive, or removed all-togeather.  If it is a non-
+  // threshold genotype, then the species will only be effected if this was
+  // the last genotype of that species.
+
+  cSpecies * cur_species = in_genotype.GetSpecies();
+  if (cur_species) {
+
+    // First, re-adjust the species.
+
+    cur_species->RemoveGenotype();
+
+    // Then, check to see how this species changes if it is a threshold.
+
+    if (in_genotype.GetThreshold()) {
+      cur_species->RemoveThreshold(in_genotype);
+
+      // If we are out of thresholds, move this species to the inactive
+      // list for now.  Otherwise, just adjust it.
+
+      if (cur_species->GetNumThreshold() == 0) {
+	species_control->SetInactive(*cur_species);
+      }
+      else {
+	species_control->Adjust(*cur_species);
+      }
+    }
+
+    // Finally, remove the species completely if it has no genotypes left.
+
+    if (!cur_species->GetNumGenotypes()) {
+      species_control->SetGarbage(*cur_species);
+    }
+  }
+
+
+  delete &in_genotype;
+}
+
+void cGenebank::ThresholdGenotype(cGenotype & in_genotype)
+{
+  cSpecies * found_species = NULL;
+
+  in_genotype.SetName( GetLabel(in_genotype.GetLength(),
+				genotype_count[in_genotype.GetLength()]++) );
+  in_genotype.SetThreshold();
+
+  // If speciation is on, assign a species to the genotype now that it is
+  // threshold.
+
+  if (cConfig::GetSpeciesRecording()) {
+    // Record the old species to know if it changes.
+
+    cSpecies * old_species = in_genotype.GetSpecies();
+
+    // Determine the "proper" species.
+
+    found_species = species_control->Find(in_genotype,
+					  cConfig::GetSpeciesRecording());
+
+    // If no species was found, create a new one.
+
+    if (!found_species) {
+      found_species = new cSpecies(in_genotype.GetGenome(), stats.GetUpdate());
+      if (in_genotype.GetSpecies())
+	found_species->SetParentID(in_genotype.GetSpecies()->GetID());
+      species_control->SetActive(*found_species);
+      stats.AddSpecies(found_species->GetID());
+
+      // Since this is a new species, see if we should be printing it.
+
+      if (cConfig::GetSpeciesPrint()) {
+	cString filename;
+	filename.Set("genebank/spec-%04d", found_species->GetID());
+	cTestUtil::PrintGenome(in_genotype.GetGenome(), filename,
+			       &in_genotype, stats.GetUpdate());
+      }
+    }
+    else {
+      // If we are not creating a new species, but are adding a threshold
+      // to one which is currently in-active, make sure to move it back to
+      // the active list.
+
+      if (found_species->GetNumThreshold() == 0) {
+	species_control->SetActive(*found_species);
+      }
+    }
+
+    // Now that we know for sure what the species is, and that it is in
+    // the proper list, setup both the species and the genotype.
+
+    in_genotype.SetSpecies(found_species);
+    found_species->AddThreshold(in_genotype);
+
+    // Finally test to see if the species has been changed, and adjust
+    // accordingly.
+
+    if (found_species != old_species) {
+      found_species->AddGenotype();
+      if (old_species) {
+	old_species->RemoveGenotype();
+	if (old_species->GetNumGenotypes() == 0)
+	  species_control->SetGarbage(*old_species);
+      }
+    }
+    else {
+      if (found_species->GetNumThreshold() > 1) {
+	species_control->Adjust(*found_species);
+      }
+    }
+  }
+
+  // Do the relevent statistics...
+
+  if (cConfig::GetSpeciesRecording()) {
+    stats.AddThreshold(in_genotype.GetID(), in_genotype.GetName()(),
+			 found_species->GetID());
+  } else {
+    stats.AddThreshold(in_genotype.GetID(), in_genotype.GetName()());
+  }
+
+  // Print the genotype?
+
+  if (cConfig::GetGenotypePrint()) {
+    cString filename;
+    filename.Set("genebank/%s", in_genotype.GetName()());
+    cTestUtil::PrintGenome(in_genotype.GetGenome(), filename,
+			   &in_genotype, stats.GetUpdate());
+  }
+}
+
+bool cGenebank::AdjustGenotype(cGenotype & in_genotype)
+{
+  if (!genotype_control->Adjust(in_genotype)) return false;
+
+  if ((in_genotype.GetNumOrganisms() >= cConfig::GetThreshold() ||
+       &in_genotype == genotype_control->GetBest()) &&
+      !(in_genotype.GetThreshold())) {
+    ThresholdGenotype(in_genotype);
+  }
+
+  return true;
+}
+
+bool cGenebank::SaveClone(ofstream & fp)
+{
+  // This method just save the counts at each size-class of genotypes.
+  // The rest is reconstructable.
+
+  // Save the numbers of organisms we're up to at each size.
+  fp << MAX_CREATURE_SIZE << " ";
+  for (int i = 0; i < MAX_CREATURE_SIZE; i++) {
+    fp << genotype_count[i] << " ";
+  }
+
+  return true;
+}
+
+bool cGenebank::LoadClone(ifstream & fp)
+{
+  // This method just restores the counts at each size-class of genotypes.
+  // The rest of the loading process should be handled elsewhere.
+
+  // Load the numbers of organisms we're up to at each size.
+  int max_size;
+  fp >> max_size;
+  assert (max_size <= MAX_CREATURE_SIZE); // MAX_CREATURE_SIZE too small
+  for (int i = 0; i < max_size && i < MAX_CREATURE_SIZE; i++) {
+    fp >> genotype_count[i];
+  }
+
+  return true;
+}
+
+bool cGenebank::DumpTextSummary(ofstream & fp)
+{
+  genotype_control->Reset(0);
+  for (int i = 0; i < genotype_control->GetSize(); i++) {
+    cGenotype * genotype = genotype_control->Get(0);
+    fp << genotype->GetGenome().AsString() << " "
+       << genotype->GetNumOrganisms() << " "
+       << genotype->GetID() << endl;
+    genotype_control->Next(0);
+  }
+
+  return true;
+}
+
+bool cGenebank::DumpDetailedSummary(ofstream & fp)
+{
+  genotype_control->Reset(0);
+  DumpDetailHeading(fp);
+  for (int i = 0; i < genotype_control->GetSize(); i++) {
+    DumpDetailedEntry(genotype_control->Get(0), fp);
+    genotype_control->Next(0);
+  }
+
+  return true;
+}
+
+bool cGenebank::DumpHistoricSummary(ofstream & fp)
+{
+  genotype_control->ResetHistoric(0);
+  DumpDetailHeading(fp);
+  for (int i = 0; i < genotype_control->GetHistoricCount(); i++) {
+    DumpDetailedEntry(genotype_control->Get(0), fp);
+    genotype_control->Next(0);
+  }
+
+  return true;
+}
+
+void cGenebank::DumpDetailHeading (ofstream & fp)
+{
+  fp << endl
+     << "#  1: ID" << endl
+     << "#  2: parent ID" << endl
+     << "#  3: parent distance" << endl
+     << "#  4: number of orgranismsi currently alive" << endl
+     << "#  5: total number of organisms that ever existed" << endl
+     << "#  6: length of genome" << endl
+     << "#  7: merit" << endl
+     << "#  8: gestation time" << endl
+     << "#  9: fitness" << endl
+     << "# 10: update born" << endl
+     << "# 11: update deactivated" << endl
+     << "# 12: depth in phylogentic tree" << endl
+     << "# 13: genome of organism" << endl << endl;
+}
+
+void cGenebank::DumpDetailedEntry(cGenotype * genotype, ofstream & fp)
+{
+  fp << genotype->GetID() << " "                //  1
+     << genotype->GetParentID() << " "          //  2
+     << genotype->GetParentDistance() << " "    //  3
+     << genotype->GetNumOrganisms() << " "      //  4
+     << genotype->GetTotalOrganisms() << " "    //  5
+     << genotype->GetLength() << " "            //  6
+     << genotype->GetMerit() << " "             //  7
+     << genotype->GetGestationTime() << " "     //  8
+     << genotype->GetFitness() << " "           //  9
+     << genotype->GetUpdateBorn() << " "        // 10
+     << genotype->GetUpdateDeactivated() << " " // 11
+     << genotype->GetDepth() << " "             // 12
+     << genotype->GetGenome().AsString() << " " // 13
+     << endl;
+}
+
+bool cGenebank::OK()
+{
+  bool ret_value = true;
+  int i;
+
+  // Check components...
+
+  if (!genotype_control->OK() || !species_control->OK()) {
+    ret_value = false;
+  }
+
+  // Now to double check the numbers of genotypes (and threshold) for each
+  // species.  This will only work if debug mode is on.
+
+#ifdef DEBUG
+  // Initialize debug routines in the species.
+
+  cSpecies * cur_species = NULL;
+  cSpecies * first_active = species_control->GetFirst();
+  cSpecies * first_inactive = species_control->GetFirstInactive();
+  cSpecies * first_garbage = species_control->GetFirstGarbage();
+
+  while (cur_species != first_active) {
+    if (!cur_species) cur_species = first_active;
+    cur_species->debug_num_genotypes = 0;
+    cur_species->debug_num_threshold = 0;
+    cur_species = cur_species->GetNext();
+  }
+
+  cur_species = NULL;
+  while (cur_species != first_inactive) {
+    if (!cur_species) cur_species = first_inactive;
+    cur_species->debug_num_genotypes = 0;
+    cur_species->debug_num_threshold = 0;
+    cur_species = cur_species->GetNext();
+  }
+
+  cur_species = NULL;
+  while (cur_species != first_garbage) {
+    if (!cur_species) cur_species = first_garbage;
+    cur_species->debug_num_genotypes = 0;
+    cur_species->debug_num_threshold = 0;
+    cur_species = cur_species->GetNext();
+  }
+
+
+  // Check the species for each genotype and place results in the species.
+
+  cGenotype * cur_gen = genotype_control->GetBest();
+  for (i = 0; i < genotype_control->GetSize(); i++) {
+    if (cur_gen->GetSpecies()) {
+      cur_gen->GetSpecies()->debug_num_genotypes++;
+      if (cur_gen->GetThreshold()) {
+	cur_gen->GetSpecies()->debug_num_threshold++;
+      }
+    }
+    cur_gen = cur_gen->GetNext();
+  }
+
+  // Finally, make sure all the numbers match up.
+
+  cur_species = NULL;
+  while (cur_species != first_active) {
+    if (!cur_species) cur_species = first_active;
+    assert(cur_species->debug_num_genotypes == cur_species->GetNumGenotypes());
+    assert(cur_species->debug_num_threshold == cur_species->GetNumThreshold());
+    assert(cur_species->debug_num_genotypes >= cur_species->debug_num_threshold);
+
+    assert (cur_species->debug_num_threshold);
+    cur_species = cur_species->GetNext();
+  }
+
+  cur_species = NULL;
+  while (cur_species != first_inactive) {
+    if (!cur_species) cur_species = first_inactive;
+    assert(cur_species->debug_num_genotypes == cur_species->GetNumGenotypes());
+    assert(cur_species->debug_num_threshold == cur_species->GetNumThreshold());
+    assert(cur_species->debug_num_threshold);
+    assert(cur_species->debug_num_genotypes);
+  }
+
+  cur_species = NULL;
+  while (cur_species != first_garbage) {
+    if (!cur_species) cur_species = first_garbage;
+    assert(cur_species->debug_num_genotypes == 0 &&
+	   cur_species->debug_num_threshold == 0);
+  }
+
+#endif
+
+  assert (ret_value == true);
+
+  return ret_value;
+}
+
+int cGenebank::CountNumCreatures()
+{
+  int i;
+  int total = 0;
+
+  genotype_control->Reset(0);
+  for (i = 0; i < genotype_control->GetSize(); i++) {
+    total += genotype_control->Get(0)->GetNumOrganisms();
+    genotype_control->Next(0);
+  }
+
+  return total;
+}
+
+
+unsigned int cGenebank::FindCRC(const cGenome & in_genome) const
+{
+  unsigned int total = 0;
+
+  for (int i = 0; i < in_genome.GetSize(); i++) {
+    total += (in_genome[i].GetOp() + 3) * i;
+  }
+
+  return total % GENOTYPE_HASH_SIZE;
+}
+
+void cGenebank::SpeciesTest(char * message, cGenotype & genotype)
+{
+  cSpecies * cur_species = genotype.GetSpecies();
+
+//    if (cur_species) {
+//      g_debug.Comment("UD %d: %s on genotype [%d] (size %d) of species [%d]",
+//  		    stats.GetUpdate(), message, genotype.GetID(),
+//  		    genotype.GetNumOrganisms(), cur_species->GetID());
+//    } else {
+//      g_debug.Comment("UD %d: %s on genotype [%d] (size %d) (no species)",
+//  	    stats.GetUpdate(), message, genotype.GetID(),
+//  	    genotype.GetNumOrganisms());
+//    }
+
+//    if (cur_species) {
+//      g_debug.Comment("   Species [%d] has %d gen and %d thresh. (list %d)",
+//  	    cur_species->GetID(), cur_species->GetNumGenotypes(),
+//  	    cur_species->GetNumThreshold(), cur_species->GetQueueType());
+//    }
+}
Index: avida/current/source/main/genebank.hh
diff -u /dev/null avida/current/source/main/genebank.hh:1.25
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/genebank.hh	Tue Nov 25 09:37:56 2003
@@ -0,0 +1,109 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef GENEBANK_HH
+#define GENEBANK_HH
+
+#include <fstream>
+
+#ifndef DEFS_HH
+#include "defs.hh"
+#endif
+#ifndef GENOTYPE_CONTROL_HH
+#include "genotype_control.hh"
+#endif
+#ifndef SPECIES_CONTROL_HH
+#include "species_control.hh"
+#endif
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+#ifndef TLIST_HH
+#include "tList.hh"
+#endif
+
+template <class T> class tList; // array
+class cGenome;
+class cGenotype;
+class cGenotypeControl; // access
+class cSpeciesControl; // access
+class cStats;
+class cString; // aggregate
+
+class cGenebank {
+private:
+  unsigned int genotype_count[MAX_CREATURE_SIZE];
+  tList<cGenotype> active_genotypes[GENOTYPE_HASH_SIZE];
+  cGenotypeControl * genotype_control;
+  cSpeciesControl * species_control;
+  cStats & stats;
+
+private:
+  cString GetLabel(int in_size, int in_num);
+
+public:
+  cGenebank(cStats & _stats);
+  ~cGenebank();
+
+  void UpdateReset();
+
+  /** 
+   * This function can be used to add a genotype that was created
+   * outside the genebank. In this case, the parameter in_list_num
+   * should not be given. Normally, genotypes are added through the 
+   * function AddGenotype(const cGenome & in_genome, 
+   * cGenotype * parent_genotype = NULL), which then calls this one.
+   **/
+  void AddGenotype(cGenotype *in_genotype, int list_num=-1);
+  cGenotype * AddGenotype(const cGenome & in_genome,
+			  cGenotype * parent_genotype = NULL);
+  const cGenotype * FindGenotype(const cGenome & in_genome, int list_num=-1) const;
+  cGenotype * FindGenotype(const cGenome & in_genome, int list_num=-1);
+  void RemoveGenotype(cGenotype & in_genotype);
+  void ThresholdGenotype(cGenotype & in_genotype);
+  bool AdjustGenotype(cGenotype & in_genotype);
+
+  bool SaveClone(std::ofstream & fp);
+  bool LoadClone(std::ifstream & fp);
+  bool DumpTextSummary(std::ofstream & fp);
+  bool DumpDetailedSummary(std::ofstream & fp);
+  bool DumpHistoricSummary(std::ofstream & fp);
+  void DumpDetailHeading (std::ofstream & fp);
+  void DumpDetailedEntry(cGenotype * genotype, std::ofstream & fp);
+  bool OK();
+
+  inline int GetSize() const { return genotype_control->GetSize(); }
+  inline cGenotype * GetBestGenotype() const
+    { return genotype_control->GetBest(); }
+  inline cGenotype * GetCoalescentGenotype() const
+    { return genotype_control->GetCoalescent(); }
+  inline cSpecies * GetFirstSpecies() const
+    { return species_control->GetFirst(); }
+
+  inline cGenotype * GetGenotype(int thread) const
+    { return genotype_control->Get(thread); }
+  inline cGenotype * NextGenotype(int thread) {
+    cGenotype * next = genotype_control->Next(thread);
+    return (next == genotype_control->GetBest()) ? (cGenotype*)NULL : next;
+  }
+  inline cGenotype * ResetThread(int thread)
+    { return genotype_control->Reset(thread); }
+
+  int CountNumCreatures();
+  inline int GetNumSpecies() const { return species_control->GetSize(); }
+  inline int CountSpecies() { return species_control->OK(); }
+  inline int FindPos(cGenotype & in_genotype, int max_depth = -1)
+    { return genotype_control->FindPos(in_genotype, max_depth); }
+  inline int FindPos(cSpecies & in_species, int max_depth = -1)
+    { return species_control->FindPos(in_species, max_depth); }
+
+  unsigned int FindCRC(const cGenome & in_genome) const;
+
+  void SpeciesTest(char * message, cGenotype & genotype);
+};
+
+#endif
Index: avida/current/source/main/genome.cc
diff -u /dev/null avida/current/source/main/genome.cc:1.7
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/genome.cc	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,96 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#include "genome.hh"
+
+
+using namespace std;
+
+
+/////////////
+//  cGenome
+/////////////
+
+cGenome::cGenome(int _size)
+  : genome(_size), active_size(_size)
+{
+}
+
+cGenome::cGenome(const cGenome & in_genome)
+  : genome(in_genome.GetSize()), active_size(in_genome.GetSize())
+{
+  for (int i = 0; i < active_size; i++)  genome[i] = in_genome[i];
+}
+
+cGenome::cGenome(const cString & in_string)
+{
+  cString tmp_string(in_string);
+  tmp_string.RemoveChar('_');  // Remove all blanks from alignments...
+
+  active_size = tmp_string.GetSize();
+  genome.ResizeClear(active_size);
+  for (int i = 0; i < active_size; i++) {
+    genome[i].SetSymbol(tmp_string[i]);
+  }
+}
+
+cGenome::~cGenome()
+{
+}
+
+
+void cGenome::operator=(const cGenome & other_genome)
+{
+  // If we need to resize, do so...
+  active_size = other_genome.GetSize();
+  genome.ResizeClear(active_size);
+
+  // Now that both code arrays are the same size, copy the other one over.
+
+  for (int i = 0; i < active_size; i++) {
+    genome[i] = other_genome[i];
+  }
+}
+
+
+bool cGenome::operator==(const cGenome & other_genome) const
+{
+  // Make sure the sizes are the same.
+  if (active_size != other_genome.active_size) return false;
+
+  // Then go through line by line.
+  for (int i = 0; i < active_size; i++)
+    if (genome[i] != other_genome[i]) return false;
+
+  return true;
+}
+
+
+void cGenome::Copy(int to, int from)
+{
+  assert(to   >= 0   && to   < active_size);
+  assert(from >= 0   && from < active_size);
+  genome[to] = genome[from];
+}
+
+bool cGenome::OK() const
+{
+  assert (active_size <= genome.GetSize()); // active_size too large!
+
+  return true;
+}
+ 
+
+cString cGenome::AsString() const
+{
+  cString out_string(active_size);
+  for (int i = 0; i < active_size; i++) {
+    out_string[i] = genome[i].GetSymbol();
+  }
+
+  return out_string;
+}
Index: avida/current/source/main/genome.hh
diff -u /dev/null avida/current/source/main/genome.hh:1.7
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/genome.hh	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,60 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef GENOME_HH
+#define GENOME_HH
+
+#include <assert.h>
+
+#ifndef INSTRUCTION_HH
+#include "instruction.hh"
+#endif
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+#ifndef TARRAY_HH
+#include "tArray.hh"
+#endif
+
+/**
+ * This class stores the genome of an Avida organism.  Note that once created,
+ * a genome should not be modified; only the corresponding memory should be,
+ * before creating the genome.  Keeping genome light-weight...
+ **/
+
+class cGenome {
+protected:
+  tArray<cInstruction> genome;
+  int active_size;
+
+public:
+  explicit cGenome(int _size);
+  cGenome(const cGenome & in_genome);
+  cGenome(const cString & in_string);
+  virtual ~cGenome();
+
+  virtual void operator=(const cGenome & other_genome);
+  virtual bool operator==(const cGenome & other_genome) const;
+  virtual bool operator!=(const cGenome & other_genome) const
+  { return !(this->operator==(other_genome)); }
+  virtual bool operator<(const cGenome & other_genome) const
+  { return AsString() < other_genome.AsString(); }
+
+  cInstruction & operator[](int index)
+    { assert(index >= 0 && index < active_size);  return genome[index]; }
+  const cInstruction & operator[](int index) const
+    { assert(index >= 0 && index < active_size);  return genome[index]; }
+
+  virtual void Copy(int to, int from);
+
+  bool OK() const;
+   
+  int GetSize() const { return active_size; }
+  cString AsString() const;
+};
+
+#endif
Index: avida/current/source/main/genome_util.cc
diff -u /dev/null avida/current/source/main/genome_util.cc:1.8
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/genome_util.cc	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,214 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#include "genome_util.hh"
+
+#include "functions.hh"
+#include "genome.hh"
+
+
+using namespace std;
+
+
+int cGenomeUtil::FindInst(const cGenome & gen, const cInstruction & inst,
+			  int start_index)
+{
+  assert(start_index < gen.GetSize());  // Starting search after genome end.
+
+  for(int i = start_index; i < gen.GetSize(); i++) {
+    if (gen[i] == inst) return i;
+  }
+
+  // Search failed
+  return -1;
+}
+
+
+int cGenomeUtil::FindOverlap(const cGenome & gen1, const cGenome & gen2,
+			     int offset)
+{
+  assert(offset < gen1.GetSize());
+  assert(-offset < gen2.GetSize());
+
+  if (offset > 0) return Min(gen1.GetSize() - offset, gen2.GetSize());
+  // else
+  return Min(gen2.GetSize() + offset, gen1.GetSize());
+}
+
+
+int cGenomeUtil::FindHammingDistance(const cGenome &gen1, const cGenome &gen2,
+				     int offset)
+{
+  const int start1 = (offset < 0) ? 0 : offset;
+  const int start2 = (offset > 0) ? 0 : -offset;
+  const int overlap = FindOverlap(gen1, gen2, offset);
+
+  // Initialize the hamming distance to anything protruding past the overlap.
+
+  int hamming_distance = gen1.GetSize() + gen2.GetSize() - 2 * overlap;
+
+  // Cycle through the overlap adding all differences to the distance.
+  for (int i = 0; i < overlap; i++) {
+    if (gen1[start1 + i] != gen2[start2 + i])  hamming_distance++;
+  }
+
+  return hamming_distance;
+}
+
+
+int cGenomeUtil::FindBestOffset(const cGenome & gen1, const cGenome & gen2)
+{
+  const int size1 = gen1.GetSize();
+  const int size2 = gen2.GetSize();
+
+  int best_offset = 0;
+  int cur_distance = FindHammingDistance(gen1, gen2);
+  int best_distance = cur_distance;
+
+  // Check positive offsets...
+  for (int i = 1; i < size1 || i < size2; i++) {
+    if (size1 + size2 - 2 * FindOverlap(gen1, gen2, i) > best_distance) break;
+    cur_distance = FindHammingDistance(gen1, gen2, i);
+    if (cur_distance < best_distance) {
+      best_distance = cur_distance;
+      best_offset = i;
+    }
+  }
+
+  // Check negative offsets...
+  for (int i = 1; i < size1 || i < size2; i++) {
+    if (size1 + size2 - 2 * FindOverlap(gen1, gen2, -i) > best_distance) break;
+    cur_distance = FindHammingDistance(gen1, gen2, -i);
+    if (cur_distance < best_distance) {
+      best_distance = cur_distance;
+      best_offset = -i;
+    }
+  }
+
+  return best_offset;
+}
+
+
+int cGenomeUtil::FindSlidingDistance(const cGenome &gen1, const cGenome &gen2)
+{
+  const int offset = FindBestOffset(gen1, gen2);
+  return FindHammingDistance(gen1, gen2, offset);
+}
+
+
+int cGenomeUtil::FindEditDistance(const cGenome & gen1, const cGenome & gen2)
+{
+  const int size1 = gen1.GetSize();
+  const int size2 = gen2.GetSize();
+
+  if (!size1) return size2;
+  if (!size2) return size1;
+
+  int * cur_row  = new int[size1];  // The row we are calculating
+  int * prev_row = new int[size1];  // The last row we calculater
+
+  // Initialize the previous row to record the differece from nothing.
+  for (int i = 0; i < size1; i++)  prev_row[i] = i + 1;
+
+  // Loop through each subsequent character in the test code
+  for (int i = 0; i < size2; i++) {
+    // Initialize the first entry in cur_row.
+    if (gen1[0] == gen2[i]) cur_row[0] = i;
+    else cur_row[0] = (i < prev_row[0]) ? (i+1) : (prev_row[0] + 1);
+
+    // Move down the cur_row and fill it out.
+    for (int j = 1; j < size1; j++) {
+      // If the values are equal, keep the value in the upper left.
+      if (gen1[j] == gen2[i]) {
+	cur_row[j] = prev_row[j-1];
+      }
+
+      // Otherwise, set the current position the the minimal of the three
+      // numbers above (insertion), to the left (deletion), or upper left
+      // (mutation) in the chart, plus one.
+      else {
+	cur_row[j] =
+	  (prev_row[j] < prev_row[j-1]) ? prev_row[j] : prev_row[j-1];
+	if (cur_row[j-1] < cur_row[j]) cur_row[j] = cur_row[j-1];
+	cur_row[j]++;
+      }
+    }
+
+    // Swap cur_row and prev_row. (we only really need to move the cur row
+    // over to prev, but this saves us from having to keep re-allocating
+    // new rows.  We recycle!
+    int * temp_row = cur_row;
+    cur_row = prev_row;
+    prev_row = temp_row;
+  }
+
+  // Now that we are done, return the bottom-right corner of the chart.
+
+  const int value = prev_row[size1 - 1];
+
+  delete [] cur_row;
+  delete [] prev_row;
+
+  return value;
+}
+
+
+cGenome cGenomeUtil::Crop(const cGenome & in_genome, int start, int end)
+{
+  assert(end > start);                // Must have a positive length clip!
+  assert(in_genome.GetSize() >= end); // end must be < genome length
+  assert(start >= 0);                 // negative start illegal
+
+  const int out_length = end - start;
+  cGenome out_genome(out_length);
+  for (int i = 0; i < out_length; i++) {
+    out_genome[i] = in_genome[i+start];
+  }
+
+  return out_genome;
+}
+
+
+cGenome cGenomeUtil::Cut(const cGenome & in_genome, int start, int end)
+{
+  assert(end > start);                // Must have a positive size cut!
+  assert(in_genome.GetSize() >= end); // end must be < genome length
+  assert(start >= 0);                 // negative start illegal
+
+  const int cut_length = end - start;
+  const int out_length = in_genome.GetSize() - cut_length;
+
+  assert(out_length > 0);             // Can't cut everything!
+
+  cGenome out_genome(out_length);
+  for (int i = 0; i < start; i++) {
+    out_genome[i] = in_genome[i];
+  }
+  for (int i = start; i < out_length; i++) {
+    out_genome[i] = in_genome[i+cut_length];
+  }
+
+  return out_genome;
+}
+
+
+cGenome cGenomeUtil::Join(const cGenome & genome1, const cGenome & genome2)
+{
+  const int length1 = genome1.GetSize();
+  const int length2 = genome2.GetSize();
+  const int out_length = length1 + length2;
+
+  cGenome out_genome(out_length);
+  for (int i = 0; i < length1; i++) {
+    out_genome[i] = genome1[i];
+  }
+  for (int i = 0; i < length2; i++) {
+    out_genome[i+length1] = genome2[i];
+  }
+
+  return out_genome;
+}
Index: avida/current/source/main/genome_util.hh
diff -u /dev/null avida/current/source/main/genome_util.hh:1.4
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/genome_util.hh	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,39 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef GENOME_UTIL_HH
+#define GENOME_UTIL_HH
+
+#ifndef GENOME_HH
+#include "genome.hh"
+#endif
+
+class cInstruction;
+class cGenomeUtil {
+public:
+  // ========= Detection =========
+  static int FindInst(const cGenome & gen, const cInstruction & inst,
+		      int start_index=0);
+  static bool HasInst(const cGenome & gen, const cInstruction & inst)
+    { return ( FindInst(gen, inst) >= 0 ) ? true : false; }
+
+  // === Genetic distance tools ===
+  static int FindOverlap(const cGenome & gen1, const cGenome & gen2,
+			 int offset = 0);
+  static int FindHammingDistance(const cGenome & gen1, const cGenome & gen2,
+				 int offset = 0);
+  static int FindBestOffset(const cGenome & gen1, const cGenome & gen2);
+  static int FindSlidingDistance(const cGenome & gen1, const cGenome & gen2);
+  static int FindEditDistance(const cGenome & gen1, const cGenome & gen2);
+
+  // ===== Construction methods =====
+  static cGenome Crop(const cGenome & genome, int start, int end);
+  static cGenome Cut(const cGenome & genome, int start, int end);
+  static cGenome Join(const cGenome & genome1, const cGenome & genome2);
+};
+
+#endif
Index: avida/current/source/main/genotype.cc
diff -u /dev/null avida/current/source/main/genotype.cc:1.25
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/genotype.cc	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,299 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef GENOTYPE_HH
+#include "genotype.hh"
+#endif
+
+#ifndef CONFIG_HH
+#include "config.hh"
+#endif
+#ifndef CPU_TEST_INFO_HH
+#include "cpu_test_info.hh"
+#endif
+#ifndef GENOME_UTIL_HH
+#include "genome_util.hh"
+#endif
+#ifndef MERIT_HH
+#include "merit.hh"
+#endif
+#ifndef ORGANISM_HH
+#include "organism.hh"
+#endif
+#ifndef PHENOTYPE_HH
+#include "phenotype.hh"
+#endif
+#ifndef TEST_CPU_HH
+#include "test_cpu.hh"
+#endif
+#ifndef TOOLS_HH
+#include "tools.hh"
+#endif
+
+using namespace std;
+
+class cSpecies;
+
+///////////////////////////
+//  cGenotype
+///////////////////////////
+
+cGenotype::cGenotype(int in_update_born, int in_id)
+  : genome(1)
+  , name("001-no_name")
+  , flag_threshold(false)
+  , is_active(true)
+  , defer_adjust(0)
+  , symbol(0)
+  , birth_data(in_update_born)
+  , num_organisms(0)
+  , last_num_organisms(0)
+  , total_organisms(0)
+  , total_parasites(0)
+  , species(NULL)
+  , next(NULL)
+  , prev(NULL)
+{
+  static int next_id = 1;
+  
+  if ( in_id >= 0 )
+    next_id = in_id;
+  
+  id_num = next_id++;
+}
+
+cGenotype::~cGenotype()
+{
+  // Reset some of the variables to make sure program will crash if a deleted
+  // cell is read!
+
+  symbol = '!';
+
+  num_organisms = -1;
+  total_organisms = -1;
+
+  next = NULL;
+  prev = NULL;
+}
+
+bool cGenotype::SaveClone(ofstream & fp)
+{
+  fp << id_num         << " ";
+  fp << genome.GetSize() << " ";
+
+  for (int i = 0; i < genome.GetSize(); i++) {
+    fp << ((int) genome[i].GetOp()) << " ";
+  }
+
+  return true;
+}
+
+bool cGenotype::LoadClone(ifstream & fp)
+{
+  int genome_size = 0;
+
+  fp >> id_num;
+  fp >> genome_size;
+
+  genome = cGenome(genome_size);
+  for (int i = 0; i < genome_size; i++) {
+    cInstruction temp_inst;
+    int inst_op;
+    fp >> inst_op;
+    temp_inst.SetOp((UCHAR) inst_op);
+    genome[i] = temp_inst;
+    // @CAO add something here to load arguments for instructions.
+  }
+
+  return true;
+}
+
+bool cGenotype::OK()
+{
+  bool ret_value = true;
+
+  // Check the components...
+
+  if (!genome.OK()) ret_value = false;
+
+  // And the statistics
+  assert( id_num >= 0 && num_organisms >= 0 && total_organisms >= 0 );
+  assert( birth_data.update_born >= -1 && birth_data.parent_distance >= -1 );
+  assert( sum_copied_size.Sum() >= 0 && sum_exe_size.Sum() >= 0 );
+  assert( sum_gestation_time.Sum() >= 0 && sum_repro_rate.Sum() >= 0 );
+  assert( sum_merit.Sum() >= 0 && sum_fitness.Sum() >= 0 );
+  assert( tmp_sum_copied_size.Sum() >= 0 && tmp_sum_exe_size.Sum() >= 0 );
+  assert( tmp_sum_gestation_time.Sum() >= 0 && tmp_sum_repro_rate.Sum() >= 0 );
+  assert( tmp_sum_merit.Sum() >= 0 && tmp_sum_fitness.Sum() >= 0 );
+
+  return ret_value;
+};
+
+void cGenotype::SetParent(cGenotype * parent)
+{
+  birth_data.parent_genotype = parent;
+
+  // If we have a real parent genotype, collect other data about parent.
+  if (parent == NULL) return;
+  birth_data.parent_id = parent->GetID();
+  birth_data.parent_distance =
+    cGenomeUtil::FindEditDistance(genome, parent->genome);
+  birth_data.parent_species = parent->GetSpecies();
+  birth_data.gene_depth = parent->GetDepth() + 1;
+  parent->AddOffspringGenotype();
+
+  // Initialize all stats to those of the parent genotype....
+  tmp_sum_copied_size.Add(    parent->GetCopiedSize());
+  tmp_sum_exe_size.Add(       parent->GetExecutedSize());
+  tmp_sum_gestation_time.Add( parent->GetGestationTime());
+  tmp_sum_repro_rate.Add(   1/parent->GetGestationTime());
+  tmp_sum_merit.Add(          parent->GetMerit());
+  tmp_sum_fitness.Add(        parent->GetFitness());
+}
+
+void cGenotype::Mutate()  // Check each location to be mutated.
+{
+  int i;
+
+  for (i = 0; i < genome.GetSize(); i++) {
+    if (true) { // g_random.GetUInt()) {     //@CAO always true!
+      genome[i].SetOp(g_random.GetUInt(cConfig::GetNumInstructions()));
+      // Flag command as having been mutated? @CAO
+    }
+  }
+}
+
+void cGenotype::UpdateReset()
+{
+  last_num_organisms = num_organisms;
+  birth_data.birth_track.Next();
+  birth_data.death_track.Next();
+  birth_data.breed_out_track.Next();
+  birth_data.breed_true_track.Next();
+  birth_data.breed_in_track.Next();
+}
+
+void cGenotype::SetGenome(const cGenome & in_genome)
+{
+  genome = in_genome;
+  // Zero Stats
+  sum_copied_size.Clear();
+  sum_exe_size.Clear();
+  sum_gestation_time.Clear();
+  sum_repro_rate.Clear();
+  sum_merit.Clear();
+  sum_fitness.Clear();
+  tmp_sum_copied_size.Clear();
+  tmp_sum_exe_size.Clear();
+  tmp_sum_gestation_time.Clear();
+  tmp_sum_repro_rate.Clear();
+  tmp_sum_merit.Clear();
+  tmp_sum_fitness.Clear();
+
+  name.Set("%03d-no_name", genome.GetSize());
+}
+
+void cGenotype::CalcTestStats() const
+{
+  //  cerr << ".......Calculating test stats..." << endl;
+
+  cCPUTestInfo test_info;
+  cTestCPU::TestGenome(test_info, genome);
+  test_data.is_viable = test_info.IsViable();
+
+  // Setup all possible test values.
+  cPhenotype & phenotype = test_info.GetTestOrganism()->GetPhenotype();
+  test_data.fitness = test_info.GetGenotypeFitness();
+  test_data.merit = phenotype.GetMerit().GetDouble();
+  test_data.gestation_time = phenotype.GetGestationTime();
+  test_data.executed_size = phenotype.GetExecutedSize();
+  test_data.copied_size = phenotype.GetCopiedSize();
+  test_data.colony_fitness = test_info.GetColonyFitness();
+  test_data.generations = test_info.GetMaxDepth();
+}
+
+
+bool cGenotype::GetTestViable() const {
+  if (test_data.fitness == -1) CalcTestStats();
+  return test_data.is_viable;
+}
+
+
+double cGenotype::GetTestFitness() const {
+  if (test_data.fitness == -1) CalcTestStats();
+  return test_data.fitness;
+}
+
+
+double cGenotype::GetTestMerit() const {
+  if (test_data.fitness == -1) CalcTestStats();
+  return test_data.merit;
+}
+
+
+int cGenotype::GetTestGestationTime() const {
+  if (test_data.fitness == -1) CalcTestStats();
+  return test_data.gestation_time;
+}
+
+
+int cGenotype::GetTestExecutedSize() const {
+  if (test_data.fitness == -1) CalcTestStats();
+  return test_data.executed_size;
+}
+
+
+int cGenotype::GetTestCopiedSize() const {
+  if (test_data.fitness == -1) CalcTestStats();
+  return test_data.copied_size;
+}
+
+
+double cGenotype::GetTestColonyFitness() const {
+  if (test_data.fitness == -1) CalcTestStats();
+  return test_data.colony_fitness;
+}
+
+
+int cGenotype::GetTestGenerations() const {
+  if (test_data.fitness == -1) CalcTestStats();
+  return test_data.generations;
+}
+
+void cGenotype::SetSpecies(cSpecies * in_species)
+{
+  species = in_species;
+}
+
+void cGenotype::AddMerit(const cMerit & in)
+{
+  sum_merit.Add(in.GetDouble());
+}
+
+void cGenotype::RemoveMerit(const cMerit & in)
+{
+  sum_merit.Subtract(in.GetDouble());
+}
+
+void cGenotype::Deactivate(int update)
+{
+  is_active = false;
+  birth_data.update_deactivated = update;
+}
+
+int cGenotype::AddOrganism()
+{
+  total_organisms++;
+  return num_organisms++;
+}
+
+int cGenotype::RemoveOrganism()
+{
+  birth_data.death_track.Inc();
+  return num_organisms--;
+}
+
Index: avida/current/source/main/genotype.hh
diff -u /dev/null avida/current/source/main/genotype.hh:1.27
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/genotype.hh	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,243 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef GENOTYPE_HH
+#define GENOTYPE_HH
+
+#include <fstream>
+
+#ifndef DOUBLE_SUM_HH
+#include "double_sum.hh"
+#endif
+#ifndef GENOME_HH
+#include "genome.hh"
+#endif
+#ifndef GENOTYPE_BIRTH_DATA_HH
+#include "genotype_birth_data.hh"
+#endif
+#ifndef GENOTYPE_TEST_DATA_HH
+#include "genotype_test_data.hh"
+#endif
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+
+class cSpecies;
+class cMerit;
+
+class cGenotype {
+private:
+  cGenome genome;
+  cString name;
+  bool flag_threshold;
+  bool is_active;      // Is this genotype still alive?
+  int defer_adjust;    // Don't adjust in the genebank until all are cleared.
+
+  int id_num;
+  char symbol;
+
+  mutable cGenotype_TestData test_data;
+  cGenotype_BirthData birth_data;
+
+  // Statistical info
+
+  int num_organisms;
+  int last_num_organisms;
+  int total_organisms;
+  int total_parasites;
+
+  cSpecies * species;
+
+  // Data Structure stuff...
+  cGenotype * next;
+  cGenotype * prev;
+
+
+  ////// Statistical info //////
+
+  // Collected on Divides
+  cDoubleSum sum_copied_size;
+  cDoubleSum sum_exe_size;
+
+  cDoubleSum sum_gestation_time;
+  cDoubleSum sum_repro_rate;  // should make gestation obsolete (not new)
+
+  cDoubleSum sum_merit;
+  cDoubleSum sum_fitness;
+
+  // Temporary (Approx stats used before any divides done)
+  // Set in "SetParent"
+  cDoubleSum tmp_sum_copied_size;
+  cDoubleSum tmp_sum_exe_size;
+
+  cDoubleSum tmp_sum_gestation_time;
+  cDoubleSum tmp_sum_repro_rate;
+
+  cDoubleSum tmp_sum_merit;
+  cDoubleSum tmp_sum_fitness;
+
+  void CalcTestStats() const;
+public:
+  /**
+   * Constructs an empty genotype. Normally, in_id should not specified as
+   * parameter, because cGenotype keeps track of the last id given out, and
+   * choses a new one based on that. However, in some cases it is necessary
+   * to specify an id (e.g., when loading a history file from disk). Note 
+   * that in this case, cGenotype does not check if the id has already been 
+   * used before.
+   **/
+  cGenotype(int in_update_born = 0, int in_id = -1);
+  ~cGenotype();
+
+  bool SaveClone(std::ofstream & fp);
+  bool LoadClone(std::ifstream & fp);
+  bool OK();
+  void Mutate();
+  void UpdateReset();
+
+  void SetGenome(const cGenome & in_genome);
+  void SetSpecies(cSpecies * in_species);
+
+  // Test CPU info -- only used with limited options on.
+  bool GetTestViable() const;
+  double GetTestFitness() const;
+  double GetTestMerit() const;
+  int GetTestGestationTime() const;
+  int GetTestExecutedSize() const;
+  int GetTestCopiedSize() const;
+  double GetTestColonyFitness() const;
+  int GetTestGenerations() const;
+
+  void SetParent(cGenotype * parent);
+  void SetName(cString in_name)     { name = in_name; }
+  void SetNext(cGenotype * in_next) { next = in_next; }
+  void SetPrev(cGenotype * in_prev) { prev = in_prev; }
+  void SetSymbol(char in_symbol) { symbol = in_symbol; }
+  inline void SetThreshold();
+  void IncDeferAdjust() { defer_adjust++; }
+  void DecDeferAdjust() { defer_adjust--; assert(defer_adjust >= 0); }
+
+  // Setting New Stats
+  void AddCopiedSize      (int in)   { sum_copied_size.Add(in); }
+  void AddExecutedSize         (int in)   { sum_exe_size.Add(in); }
+  void AddGestationTime   (int in)   { sum_gestation_time.Add(in);
+                                       sum_repro_rate.Add(1/(double)in); }
+  void AddMerit      (const cMerit & in);
+  void RemoveMerit   (const cMerit & in);
+  void AddFitness    (double in){
+    assert(in >= 0.0);
+    sum_fitness.Add(in);
+  }
+  void RemoveFitness (double in){
+    assert(in >= 0.0);
+    sum_fitness.Subtract(in);
+  }
+
+  //// Properties Native to Genotype ////
+  cGenome & GetGenome()             { return genome; }
+  const cGenome & GetGenome() const { return genome; }
+  int GetLength()             const { return genome.GetSize(); }
+
+  int GetBirths()    const { return birth_data.birth_track.GetTotal(); }
+  int GetBreedOut()  const { return birth_data.breed_out_track.GetTotal(); }
+  int GetBreedTrue() const { return birth_data.breed_true_track.GetTotal(); }
+  int GetBreedIn()   const { return birth_data.breed_in_track.GetTotal(); }
+
+  int GetThisBirths()    const { return birth_data.birth_track.GetCur(); }
+  int GetThisBreedOut()  const { return birth_data.breed_out_track.GetCur(); }
+  int GetThisBreedTrue() const { return birth_data.breed_true_track.GetCur(); }
+  int GetThisBreedIn()   const { return birth_data.breed_in_track.GetCur(); }
+
+  int GetThisDeaths() const { return birth_data.death_track.GetCur(); }
+
+  int GetLastNumOrganisms() const { return last_num_organisms; }
+  int GetLastBirths()    const { return birth_data.birth_track.GetLast(); }
+  int GetLastBreedOut()  const { return birth_data.breed_out_track.GetLast(); }
+  int GetLastBreedTrue() const { return birth_data.breed_true_track.GetLast();}
+  int GetLastBreedIn()   const { return birth_data.breed_in_track.GetLast(); }
+
+  inline void SetBreedStats(cGenotype & daughter); // called by ActivateChild
+
+  //// Properties Averaged Over Creatues ////
+  double GetCopiedSize()    const { return (sum_copied_size.Count()>0) ?
+	   sum_copied_size.Average() : tmp_sum_copied_size.Average(); }
+  double GetExecutedSize()  const { return (sum_exe_size.Count()>0) ?
+	   sum_exe_size.Average() : tmp_sum_exe_size.Average(); }
+  double GetGestationTime() const { return (sum_gestation_time.Count()>0) ?
+	   sum_gestation_time.Average() : tmp_sum_gestation_time.Average(); }
+  double GetReproRate()     const { return (sum_repro_rate.Count()>0) ?
+	   sum_repro_rate.Average() : tmp_sum_repro_rate.Average(); }
+  double GetMerit()         const { return (sum_merit.Count()>0) ?
+	   sum_merit.Average() : tmp_sum_merit.Average(); }
+  double GetFitness()       const { return (sum_fitness.Count()>0) ?
+	   sum_fitness.Average() : tmp_sum_fitness.Average(); }
+
+
+  // For tracking the genotype line back to the ancestor...
+  cGenotype * GetParentGenotype() { return birth_data.parent_genotype; }
+  int GetNumOffspringGenotypes() const
+    { return birth_data.num_offspring_genotypes; }
+  void AddOffspringGenotype() { birth_data.num_offspring_genotypes++; }
+  void RemoveOffspringGenotype() { birth_data.num_offspring_genotypes--; }
+  bool GetActive() const { return is_active; }
+  bool GetDeferAdjust() const { return defer_adjust > 0; }
+  int GetUpdateDeactivated() { return birth_data.update_deactivated; }
+  void Deactivate(int update);
+
+
+
+  int GetUpdateBorn()           { return birth_data.update_born; }
+  int GetParentID()             { return birth_data.parent_id; }
+  int GetParentDistance()       { return birth_data.parent_distance; }
+  int GetDepth()                { return birth_data.gene_depth; }
+  cString & GetName()           { return name; }
+  cSpecies * GetSpecies()       { return species; }
+  cSpecies * GetParentSpecies() { return birth_data.parent_species; }
+  cGenotype * GetNext()         { return next; }
+  cGenotype * GetPrev()         { return prev; }
+  bool GetThreshold() const     { return flag_threshold; }
+  int GetID() const             { return id_num; }
+  char GetSymbol() const        { return symbol; }
+
+  int AddOrganism();
+  int RemoveOrganism();
+  int AddParasite()        { return ++total_parasites; }
+  void SwapOrganism()      { total_organisms++; }
+  int GetNumOrganisms()    { return num_organisms; }
+  int GetTotalOrganisms()  { return total_organisms; }
+  int GetTotalParasites()  { return total_parasites; }
+};
+
+// The genotype pointer template...
+
+
+
+// All the inline stuff...
+
+  ////////////////
+ //  cGenotype //
+////////////////
+
+inline void cGenotype::SetThreshold()
+{
+  flag_threshold = true;
+  if (symbol == '.') symbol = '+';
+}
+
+
+inline void cGenotype::SetBreedStats(cGenotype & daughter)
+{
+  birth_data.birth_track.Inc();
+  if (daughter.id_num == id_num) {
+    birth_data.breed_true_track.Inc();
+  } else {
+    birth_data.breed_out_track.Inc();
+    daughter.birth_data.breed_in_track.Inc();
+  }
+}
+
+#endif
Index: avida/current/source/main/inject_genebank.cc
diff -u /dev/null avida/current/source/main/inject_genebank.cc:1.5
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/inject_genebank.cc	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,355 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef INJECT_GENEBANK_HH
+#include "inject_genebank.hh"
+#endif
+
+#ifndef CONFIG_HH
+#include "config.hh"
+#endif
+#ifndef DATA_FILE_HH
+#include "data_file.hh"
+#endif
+#ifndef GENOME_HH
+#include "genome.hh"
+#endif
+#ifndef INJECT_GENOTYPE_HH
+#include "inject_genotype.hh"
+#endif
+#ifndef STATS_HH
+#include "stats.hh"
+#endif
+#ifndef TEST_UTIL_HH
+#include "test_util.hh"
+#endif
+
+using namespace std;
+
+////////////////////
+//  cInjectGenebank
+////////////////////
+
+cInjectGenebank::cInjectGenebank(cStats & in_stats)
+  : stats(in_stats)
+{
+  for (int i = 0; i < MAX_CREATURE_SIZE; i++) {
+    inject_genotype_count[i] = 0;
+  }
+
+  inject_genotype_control = new cInjectGenotypeControl(*this);
+
+}
+
+cInjectGenebank::~cInjectGenebank()
+{
+  delete inject_genotype_control;
+}
+
+void cInjectGenebank::UpdateReset()
+{
+  static int genotype_dom_time = 0;
+  static int prev_dom = -1;
+
+  cInjectGenotype * best_inject_genotype = GetBestInjectGenotype();
+
+  if (best_inject_genotype && best_inject_genotype->GetID() != prev_dom) {
+    genotype_dom_time = 0;
+    prev_dom = best_inject_genotype->GetID();
+  }
+  else {
+    genotype_dom_time++;
+    if (genotype_dom_time == cConfig::GetGenotypePrintDom()) {
+      cString filename;
+      filename.Set("genebank/%s", best_inject_genotype->GetName()());
+      cTestUtil::PrintGenome(best_inject_genotype, best_inject_genotype->GetGenome(), 
+			     filename, stats.GetUpdate());
+    }
+  }
+}
+
+cString cInjectGenebank::GetLabel(int in_size, int in_num)
+{
+  char alpha[6];
+  char full_name[12];
+  int i;
+
+  for (i = 4; i >= 0; i--) {
+    alpha[i] = (in_num % 26) + 'a';
+    in_num /= 26;
+  }
+  alpha[5] = '\0';
+
+  sprintf(full_name, "p%03d-%s", in_size, alpha);
+
+  return full_name;
+}
+
+void cInjectGenebank::AddInjectGenotype(cInjectGenotype * in_inject_genotype, int in_list_num)
+{
+  assert( in_inject_genotype != 0 );
+  
+  if ( in_list_num < 0 )
+    in_list_num = FindCRC(in_inject_genotype->GetGenome()) % INJECTGENOTYPE_HASH_SIZE;
+  
+  active_inject_genotypes[in_list_num].Insert(*in_inject_genotype);
+  inject_genotype_control->Insert(*in_inject_genotype);
+  //stats.AddGenotype(in_inject_genotype->GetID());
+}
+
+
+cInjectGenotype * cInjectGenebank::AddInjectGenotype(const cGenome & in_genome,
+				   cInjectGenotype * parent_genotype)
+{
+  int list_num = FindCRC(in_genome) % INJECTGENOTYPE_HASH_SIZE;
+  cInjectGenotype * found_genotype;
+
+  found_genotype = active_inject_genotypes[list_num].Find(in_genome);
+
+  if (!found_genotype) {
+    found_genotype = new cInjectGenotype(stats.GetUpdate());
+    found_genotype->SetGenome(in_genome);
+    found_genotype->SetParent(parent_genotype);
+    if(parent_genotype!=NULL)
+      {
+	parent_genotype->SetCanReproduce();
+      }
+    AddInjectGenotype( found_genotype, list_num );
+  }
+  return found_genotype;
+}
+
+cInjectGenotype * cInjectGenebank::FindInjectGenotype(const cGenome & in_genome) const
+{
+  int list_num = FindCRC(in_genome) % INJECTGENOTYPE_HASH_SIZE;
+  return active_inject_genotypes[list_num].Find(in_genome);
+}
+
+void cInjectGenebank::RemoveInjectGenotype(cInjectGenotype & in_inject_genotype)
+{
+  // If this genotype is still active, mark it no longer active and
+  // take it out of the hash table so it doesn't have any new organisms
+  // assigned to it.
+
+  if (in_inject_genotype.GetActive() == true) {
+    int list_num = FindCRC(in_inject_genotype.GetGenome()) % INJECTGENOTYPE_HASH_SIZE;
+    active_inject_genotypes[list_num].Remove(in_inject_genotype);
+    inject_genotype_control->Remove(in_inject_genotype);
+    //in_inject_genotype.Deactivate(stats.GetUpdate());
+    if (cConfig::GetTrackMainLineage()) {
+      inject_genotype_control->InsertHistoric(in_inject_genotype);
+    }
+  }
+
+  // If we are tracking the main lineage, we only want to delete a
+  // genotype when all of its decendents have also died out.
+
+  /*if (cConfig::GetTrackMainLineage()) {
+    // If  there are more offspring genotypes, hold off on deletion...
+    if (in_inject_genotype.GetNumOffspringGenotypes() != 0) return;
+
+    // If this is a dead end, delete it and recurse up...
+    cInjectGenotype * parent = in_inject_genotype.GetParentGenotype();
+    if (parent != NULL) {
+      parent->RemoveOffspringGenotype();
+
+      // Test to see if we need to update the coalescent genotype.
+      const int new_coal = inject_genotype_control->UpdateCoalescent();
+      stats.SetCoalescentGenotypeDepth(new_coal);
+      // cout << "Set coalescent to " << found_gen->GetDepth() << endl;
+
+      if (parent->GetNumInjected() == 0) {
+	// Regardless, run RemoveGenotype on the parent.
+	RemoveGenotype(*parent);
+      }
+    }
+
+    inject_genotype_control->RemoveHistoric(in_inject_genotype);
+  }
+
+  // Handle the relevent statistics...
+  stats.RemoveGenotype(in_inject_genotype.GetID(),
+	      in_inject_genotype.GetParentID(), in_inject_genotype.GetParentDistance(),
+	      in_inject_genotype.GetDepth(), in_inject_genotype.GetTotalOrganisms(),
+              in_inject_genotype.GetTotalParasites(),
+	      stats.GetUpdate() - in_inject_genotype.GetUpdateBorn(),
+              in_inject_genotype.GetLength());
+  if (in_inject_genotype.GetThreshold()) {
+  stats.RemoveThreshold(in_inject_genotype.GetID());
+  }*/
+
+  delete &in_inject_genotype;
+}
+
+void cInjectGenebank::ThresholdInjectGenotype(cInjectGenotype & in_inject_genotype)
+{
+  in_inject_genotype.SetName( GetLabel(in_inject_genotype.GetLength(),
+				inject_genotype_count[in_inject_genotype.GetLength()]++) );
+  in_inject_genotype.SetThreshold();
+
+  //stats.AddThreshold(in_inject_genotype.GetID(), in_inject_genotype.GetName()());
+  
+  // Print the genotype?
+
+  if (cConfig::GetGenotypePrint()) {
+    cString filename;
+    filename.Set("genebank/%s", in_inject_genotype.GetName()());
+    //cTestUtil::PrintGenome(in_inject_genotype.GetGenome(), filename,
+    //			   &in_inject_genotype, stats.GetUpdate());
+  }
+}
+
+bool cInjectGenebank::AdjustInjectGenotype(cInjectGenotype & in_inject_genotype)
+{
+  if (!inject_genotype_control->Adjust(in_inject_genotype)) return false;
+
+  if ((in_inject_genotype.GetNumInjected() >= cConfig::GetThreshold() ||
+       &in_inject_genotype == inject_genotype_control->GetBest()) &&
+      !(in_inject_genotype.GetThreshold())) {
+    ThresholdInjectGenotype(in_inject_genotype);
+  }
+
+  return true;
+}
+
+bool cInjectGenebank::SaveClone(ofstream & fp)
+{
+  // This method just save the counts at each size-class of genotypes.
+  // The rest is reconstructable.
+
+  // Save the numbers of organisms we're up to at each size.
+  fp << MAX_CREATURE_SIZE << " ";
+  for (int i = 0; i < MAX_CREATURE_SIZE; i++) {
+    fp << inject_genotype_count[i] << " ";
+  }
+
+  return true;
+}
+
+bool cInjectGenebank::LoadClone(ifstream & fp)
+{
+  // This method just restores the counts at each size-class of genotypes.
+  // The rest of the loading process should be handled elsewhere.
+
+  // Load the numbers of organisms we're up to at each size.
+  int max_size;
+  fp >> max_size;
+  assert (max_size <= MAX_CREATURE_SIZE); // MAX_CREATURE_SIZE too small
+  for (int i = 0; i < max_size && i < MAX_CREATURE_SIZE; i++) {
+    fp >> inject_genotype_count[i];
+  }
+
+  return true;
+}
+
+bool cInjectGenebank::DumpTextSummary(ofstream & fp)
+{
+  inject_genotype_control->Reset(0);
+  for (int i = 0; i < inject_genotype_control->GetSize(); i++) {
+    cInjectGenotype * genotype = inject_genotype_control->Get(0);
+    fp << genotype->GetGenome().AsString() << " "
+       << genotype->GetNumInjected() << " "
+       << genotype->GetID() << endl;
+    inject_genotype_control->Next(0);
+  }
+
+  return true;
+}
+
+bool cInjectGenebank::DumpDetailedSummary(const cString & file, int update)
+{
+  inject_genotype_control->Reset(0);
+  for (int i = 0; i < inject_genotype_control->GetSize(); i++) {
+    DumpDetailedEntry(inject_genotype_control->Get(0), file, update);
+    inject_genotype_control->Next(0);
+  }
+  return true;
+}
+
+/*bool cInjectGenebank::DumpHistoricSummary(ofstream & fp)
+{
+  inject_genotype_control->ResetHistoric(0);
+  for (int i = 0; i < inject_genotype_control->GetHistoricCount(); i++) {
+    DumpDetailedEntry(inject_genotype_control->Get(0), fp);
+    inject_genotype_control->Next(0);
+  }
+
+  return true;
+}*/
+
+void cInjectGenebank::DumpDetailedEntry(cInjectGenotype * genotype, const cString & filename, int update)
+{
+  //if(genotype->CanReproduce())
+  //  {
+      cDataFile & df = stats.GetDataFile(filename);
+      
+      df.WriteComment( "Avida parasite dump data" );
+      df.WriteTimeStamp();
+      
+      df.Write( genotype->GetID(),                 "parasite genotype ID");
+      df.Write( genotype->GetName(),              "parasite genotype name");
+      df.Write( genotype->GetParentID(),           "parasite parent ID");
+      df.Write( genotype->GetNumInjected(),        "current number of injected creatures with this genotype");
+      df.Write( genotype->GetTotalInjected(),      "total number of injected creatures with this genotype");
+      df.Write( genotype->GetLength(),             "genotype length");
+      df.Write( genotype->GetUpdateBorn(),         "update this genotype was born");
+      df.Write( genotype->CanReproduce(),          "has this genotype reproduced?");
+      df.Write( genotype->GetGenome().AsString(),  "genome of this genotype");
+      df.Endl();
+      //}
+}
+
+bool cInjectGenebank::OK()
+{
+  bool ret_value = true;
+  int i;
+
+  // Check components...
+
+  if (!inject_genotype_control->OK()) {
+    ret_value = false;
+  }
+
+  // Loop through all of the reference lists for matching genotypes...
+
+  for (i = 0; i < INJECTGENOTYPE_HASH_SIZE; i++) {
+    assert (active_inject_genotypes[i].OK());
+  }
+
+  assert (ret_value == true);
+
+  return ret_value;
+}
+
+int cInjectGenebank::CountNumCreatures()
+{
+  int i;
+  int total = 0;
+
+  inject_genotype_control->Reset(0);
+  for (i = 0; i < inject_genotype_control->GetSize(); i++) {
+    total += inject_genotype_control->Get(0)->GetNumInjected();
+    inject_genotype_control->Next(0);
+  }
+
+  return total;
+}
+
+
+unsigned int cInjectGenebank::FindCRC(const cGenome & in_genome) const
+{
+  unsigned int total = 13;
+  int i;
+
+  for (i = 0; i < in_genome.GetSize(); i++) {
+    total *= in_genome[i].GetOp() + 10 + i << 6;
+    total += 3;
+  }
+
+  return total;
+}
+
Index: avida/current/source/main/inject_genebank.hh
diff -u /dev/null avida/current/source/main/inject_genebank.hh:1.3
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/inject_genebank.hh	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,101 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef INJECT_GENEBANK_HH
+#define INJECT_GENEBANK_HH
+
+#include <fstream>
+
+#ifndef DEFS_HH
+#include "defs.hh"
+#endif
+#ifndef INJECT_GENEBANK_MACROS_HH
+#include "inject_genebank_macros.hh"
+#endif
+#ifndef INJECT_GENOTYPE_CONTROL_HH
+#include "inject_genotype_control.hh"
+#endif
+#ifndef INJECT_GENOTYPE_QUEUE_HH
+#include "inject_genotype_queue.hh"
+#endif
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+
+class cGenome;
+class cStats;
+class cInjectGenotype;
+class cInjectGenotypeQueue; // array
+class cInjectGenotypeControl; // access
+class cStats;
+class cString; // aggregate
+class cInjectGenotype;
+class cGenome;
+
+class cInjectGenebank {
+private:
+  unsigned int inject_genotype_count[MAX_CREATURE_SIZE];
+  cInjectGenotypeQueue active_inject_genotypes[INJECTGENOTYPE_HASH_SIZE];
+  cInjectGenotypeControl * inject_genotype_control;
+  cStats & stats;
+
+private:
+  cString GetLabel(int in_size, int in_num);
+
+public:
+  cInjectGenebank(cStats & stats);
+  ~cInjectGenebank();
+
+  void UpdateReset();
+
+  /** 
+   * This function can be used to add a injectgenotype that was created
+   * outside the genebank. In this case, the parameter in_list_num
+   * should not be given. Normally, injectgenotypes are added through the 
+   * function AddInjectGenotype(const cGenome & in_genome, 
+   * cInjectGenotype * parent_injectgenotype = NULL), which then calls this one.
+   **/
+  void AddInjectGenotype(cInjectGenotype *in_inject_genotype, int in_list_num = -1 );
+  cInjectGenotype * AddInjectGenotype(const cGenome & in_genome,
+			  cInjectGenotype * parent_inject_genotype = NULL);
+  cInjectGenotype * FindInjectGenotype(const cGenome & in_genome) const;
+  void RemoveInjectGenotype(cInjectGenotype & in_inject_genotype);
+  void ThresholdInjectGenotype(cInjectGenotype & in_inject_genotype);
+  bool AdjustInjectGenotype(cInjectGenotype & in_inject_genotype);
+
+  bool SaveClone(std::ofstream & fp);
+  bool LoadClone(std::ifstream & fp);
+  bool DumpTextSummary(std::ofstream & fp);
+  //bool DumpDetailedSummary(std::ofstream & fp);
+  bool DumpDetailedSummary(const cString & file, int update);
+  bool DumpHistoricSummary(std::ofstream & fp);
+  //void DumpDetailedEntry(cInjectGenotype * inject_genotype, std::ofstream & fp);
+  void DumpDetailedEntry(cInjectGenotype * inject_genotype, const cString & file, int update);
+  bool OK();
+
+  inline int GetSize() const { return inject_genotype_control->GetSize(); }
+  inline cInjectGenotype * GetBestInjectGenotype() const
+    { return inject_genotype_control->GetBest(); }
+  inline cInjectGenotype * GetCoalescentInjectGenotype() const
+    { return inject_genotype_control->GetCoalescent(); }
+  
+  inline cInjectGenotype * GetInjectGenotype(int thread) const
+    { return inject_genotype_control->Get(thread); }
+  inline cInjectGenotype * NextInjectGenotype(int thread) {
+    cInjectGenotype * next = inject_genotype_control->Next(thread);
+    return (next == inject_genotype_control->GetBest()) ? (cInjectGenotype*)NULL : next;
+  }
+  inline cInjectGenotype * ResetThread(int thread)
+    { return inject_genotype_control->Reset(thread); }
+
+  int CountNumCreatures();
+  inline int FindPos(cInjectGenotype & in_inject_genotype, int max_depth = -1)
+    { return inject_genotype_control->FindPos(in_inject_genotype, max_depth); }
+   unsigned int FindCRC(const cGenome & in_genome) const;
+};
+
+#endif
Index: avida/current/source/main/inject_genotype.cc
diff -u /dev/null avida/current/source/main/inject_genotype.cc:1.4
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/inject_genotype.cc	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,162 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef INJECT_GENOTYPE_HH
+#include "inject_genotype.hh"
+#endif
+
+#ifndef CONFIG_HH
+#include "config.hh"
+#endif
+#ifndef TOOLS_HH
+#include "tools.hh"
+#endif
+
+using namespace std;
+
+
+
+///////////////////////////
+//  cInjectGenotype
+///////////////////////////
+
+cInjectGenotype::cInjectGenotype(int in_update_born, int in_id)
+  : genome(1)
+  , name("p001-no_name")
+  , flag_threshold(false)
+  , is_active(true)
+      , can_reproduce(false)
+  , defer_adjust(0)
+  , symbol(0)
+  , birth_data(in_update_born)
+  , num_injected(0)
+  , last_num_injected(0)
+  , total_injected(0)
+  , next(NULL)
+  , prev(NULL)
+{
+  static int next_id = 1;
+  
+  if ( in_id >= 0 )
+    next_id = in_id;
+  
+  id_num = next_id++;
+}
+
+cInjectGenotype::~cInjectGenotype()
+{
+  // Reset some of the variables to make sure program will crash if a deleted
+  // cell is read!
+  symbol = '!';
+
+  num_injected = -1;
+  total_injected = -1;
+
+  next = NULL;
+  prev = NULL;
+}
+
+bool cInjectGenotype::SaveClone(ofstream & fp)
+{
+  fp << id_num         << " ";
+  fp << genome.GetSize() << " ";
+
+  for (int i = 0; i < genome.GetSize(); i++) {
+    fp << ((int) genome[i].GetOp()) << " ";
+  }
+
+  return true;
+}
+
+bool cInjectGenotype::LoadClone(ifstream & fp)
+{
+  int genome_size = 0;
+
+  fp >> id_num;
+  fp >> genome_size;
+
+  genome = cGenome(genome_size);
+  for (int i = 0; i < genome_size; i++) {
+    cInstruction temp_inst;
+    int inst_op;
+    fp >> inst_op;
+    temp_inst.SetOp((UCHAR) inst_op);
+    genome[i] = temp_inst;
+    // @CAO add something here to load arguments for instructions.
+  }
+
+  return true;
+}
+
+bool cInjectGenotype::OK()
+{
+  bool ret_value = true;
+
+  // Check the components...
+
+  if (!genome.OK()) ret_value = false;
+
+  // And the statistics
+  assert( id_num >= 0 && num_injected >= 0 && total_injected >= 0 );
+  assert( birth_data.update_born >= -1);
+
+  return ret_value;
+};
+
+void cInjectGenotype::SetParent(cInjectGenotype * parent)
+{
+  birth_data.parent_genotype = parent;
+
+  // If we have a real parent genotype, collect other data about parent.
+  if (parent == NULL) return;
+  birth_data.parent_id = parent->GetID();
+  birth_data.gene_depth = parent->GetDepth() + 1;
+  parent->AddOffspringGenotype();
+}
+
+void cInjectGenotype::Mutate()  // Check each location to be mutated.
+{
+  int i;
+
+  for (i = 0; i < genome.GetSize(); i++) {
+      genome[i].SetOp(g_random.GetUInt(cConfig::GetNumInstructions()));
+    }
+  
+}
+
+void cInjectGenotype::UpdateReset()
+{
+  last_num_injected = num_injected;
+  birth_data.birth_track.Next();
+  birth_data.death_track.Next();
+}
+
+void cInjectGenotype::SetGenome(const cGenome & in_genome)
+{
+  genome = in_genome;
+
+  name.Set("p%03d-no_name", genome.GetSize());
+}
+
+void cInjectGenotype::Deactivate(int update)
+{
+  is_active = false;
+  birth_data.update_deactivated = update;
+}
+
+int cInjectGenotype::AddParasite()
+{
+  total_injected++;
+  return num_injected++;
+}
+
+int cInjectGenotype::RemoveParasite()
+{
+  //birth_data.death_track.Inc();
+  return num_injected--;
+}
+
Index: avida/current/source/main/inject_genotype.hh
diff -u /dev/null avida/current/source/main/inject_genotype.hh:1.5
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/inject_genotype.hh	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,254 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef INJECT_GENOTYPE_HH
+#define INJECT_GENOTYPE_HH
+
+#include <fstream>
+
+#ifndef GENOME_HH
+#include "genome.hh"
+#endif
+#ifndef INJECT_GENOTYPE_BIRTH_DATA_HH
+#include "inject_genotype_birth_data.hh"
+#endif
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+
+/*class cInjectGenotype_TestData {
+public:
+  cGenotype_TestData();
+  ~cGenotype_TestData();
+
+  bool is_viable;
+
+  double fitness;
+  double merit;
+  int gestation_time;
+  int executed_size;
+  int copied_size;
+  double colony_fitness;
+  int generations;
+  };*/
+
+class cGenome; // aggregate
+class cString; // aggregate
+class cInjectGenotype_BirthData; // aggregate
+
+class cInjectGenotype {
+private:
+  cGenome genome;
+  cString name;
+  bool flag_threshold;
+  bool is_active;      // Is this genotype still alive?
+  bool can_reproduce;  // Can this genotype reproduce?
+  int defer_adjust;    // Don't adjust in the genebank until all are cleared.
+
+  int id_num;
+  char symbol;
+
+  //mutable cGenotype_TestData test_data;
+  cInjectGenotype_BirthData birth_data;
+
+  // Statistical info
+
+  int num_injected;
+  int last_num_injected;
+  int total_injected;
+  //int total_parasites;
+
+  //cSpecies * species;
+
+  // Data Structure stuff...
+  cInjectGenotype * next;
+  cInjectGenotype * prev;
+
+
+  ////// Statistical info //////
+
+  // Collected on Divides
+  //cDoubleSum sum_copied_size;
+  //cDoubleSum sum_exe_size;
+
+  //cDoubleSum sum_gestation_time;
+  //cDoubleSum sum_repro_rate;  // should make gestation obsolete (not new)
+
+  //cDoubleSum sum_merit;
+  //cDoubleSum sum_fitness;
+
+  // Temporary (Approx stats used before any divides done)
+  // Set in "SetParent"
+  //cDoubleSum tmp_sum_copied_size;
+  //cDoubleSum tmp_sum_exe_size;
+
+  //cDoubleSum tmp_sum_gestation_time;
+  //cDoubleSum tmp_sum_repro_rate;
+
+  //cDoubleSum tmp_sum_merit;
+  //cDoubleSum tmp_sum_fitness;
+
+  void CalcTestStats() const;
+public:
+  /**
+   * Constructs an empty genotype. Normally, in_id should not specified as
+   * parameter, because cGenotype keeps track of the last id given out, and
+   * choses a new one based on that. However, in some cases it is necessary
+   * to specify an id (e.g., when loading a history file from disk). Note 
+   * that in this case, cGenotype does not check if the id has already been 
+   * used before.
+   **/
+  cInjectGenotype(int in_update_born = 0, int in_id = -1);
+  ~cInjectGenotype();
+
+  bool SaveClone(std::ofstream & fp);
+  bool LoadClone(std::ifstream & fp);
+  bool OK();
+  void Mutate();
+  void UpdateReset();
+
+  void SetGenome(const cGenome & in_genome);
+  //void SetSpecies(cSpecies * in_species);
+
+  // Test CPU info -- only used with limited options on.
+  //bool GetTestViable() const;
+  //double GetTestFitness() const;
+  //double GetTestMerit() const;
+  //int GetTestGestationTime() const;
+  //int GetTestExecutedSize() const;
+  //int GetTestCopiedSize() const;
+  //double GetTestColonyFitness() const;
+  //int GetTestGenerations() const;
+
+  void SetParent(cInjectGenotype * parent);
+  void SetUpdateBorn (int update) { birth_data.update_born = update; }
+  void SetName(cString in_name)     { name = in_name; }
+  void SetNext(cInjectGenotype * in_next) { next = in_next; }
+  void SetPrev(cInjectGenotype * in_prev) { prev = in_prev; }
+  void SetSymbol(char in_symbol) { symbol = in_symbol; }
+  void SetCanReproduce() { can_reproduce = true; }
+  inline void SetThreshold();
+  void IncDeferAdjust() { defer_adjust++; }
+  void DecDeferAdjust() { defer_adjust--; assert(defer_adjust >= 0); }
+
+  // Setting New Stats
+  //void AddCopiedSize      (int in)   { sum_copied_size.Add(in); }
+  //void AddExecutedSize         (int in)   { sum_exe_size.Add(in); }
+  //void AddGestationTime   (int in)   { sum_gestation_time.Add(in);
+  //                            sum_repro_rate.Add(1/(double)in); }
+  //void AddMerit      (const cMerit & in);
+  //void RemoveMerit   (const cMerit & in);
+  //void AddFitness    (double in){
+  //  assert(in >= 0.0);
+  //  sum_fitness.Add(in);
+  //}
+  //void RemoveFitness (double in){
+  //  assert(in >= 0.0);
+  //  sum_fitness.Subtract(in);
+  //}
+  
+  //// Properties Native to Genotype ////
+  cGenome & GetGenome()             { return genome; }
+  const cGenome & GetGenome() const { return genome; }
+  int GetLength()             const { return genome.GetSize(); }
+  
+  //int GetBirths()    const { return birth_data.birth_track.GetTotal(); }
+  //int GetBreedOut()  const { return birth_data.breed_out_track.GetTotal(); }
+  //int GetBreedTrue() const { return birth_data.breed_true_track.GetTotal(); }
+  //int GetBreedIn()   const { return birth_data.breed_in_track.GetTotal(); }
+  
+  //int GetThisBirths()    const { return birth_data.birth_track.GetCur(); }
+  //int GetThisBreedOut()  const { return birth_data.breed_out_track.GetCur(); }
+  //int GetThisBreedTrue() const { return birth_data.breed_true_track.GetCur(); }
+  //int GetThisBreedIn()   const { return birth_data.breed_in_track.GetCur(); }
+  
+  //int GetThisDeaths() const { return birth_data.death_track.GetCur(); }
+  
+  //int GetLastNumOrganisms() const { return last_num_organisms; }
+  //int GetLastBirths()    const { return birth_data.birth_track.GetLast(); }
+  //int GetLastBreedOut()  const { return birth_data.breed_out_track.GetLast(); }
+  //int GetLastBreedTrue() const { return birth_data.breed_true_track.GetLast();}
+  //int GetLastBreedIn()   const { return birth_data.breed_in_track.GetLast(); }
+  
+  //inline void SetBreedStats(cGenotype & daughter); // called by ActivateChild
+  
+  //// Properties Averaged Over Creatues ////
+  //double GetCopiedSize()    const { return (sum_copied_size.Count()>0) ?
+  //   sum_copied_size.Average() : tmp_sum_copied_size.Average(); }
+  //double GetExecutedSize()  const { return (sum_exe_size.Count()>0) ?
+  //   sum_exe_size.Average() : tmp_sum_exe_size.Average(); }
+  //double GetGestationTime() const { return (sum_gestation_time.Count()>0) ?
+  //   sum_gestation_time.Average() : tmp_sum_gestation_time.Average(); }
+  //double GetReproRate()     const { return (sum_repro_rate.Count()>0) ?
+  //   sum_repro_rate.Average() : tmp_sum_repro_rate.Average(); }
+  //double GetMerit()         const { return (sum_merit.Count()>0) ?
+  //   sum_merit.Average() : tmp_sum_merit.Average(); }
+  //double GetFitness()       const { return (sum_fitness.Count()>0) ?
+  //   sum_fitness.Average() : tmp_sum_fitness.Average(); }
+  
+  
+  // For tracking the genotype line back to the ancestor...
+  cInjectGenotype * GetParentGenotype() { return birth_data.parent_genotype; }
+  int GetNumOffspringGenotypes() const
+    { return birth_data.num_offspring_genotypes; }
+  void AddOffspringGenotype() { birth_data.num_offspring_genotypes++; }
+  void RemoveOffspringGenotype() { birth_data.num_offspring_genotypes--; }
+  bool GetActive() const { return is_active; }
+  // bool GetDeferAdjust() const { return defer_adjust > 0; }
+  int GetUpdateDeactivated() { return birth_data.update_deactivated; }
+  void Deactivate(int update);
+
+  bool CanReproduce()           { return can_reproduce; }
+  int GetUpdateBorn()           { return birth_data.update_born; }
+  int GetParentID()             { return birth_data.parent_id; }
+  //int GetParentDistance()       { return birth_data.parent_distance; }
+  int GetDepth()                { return birth_data.gene_depth; }
+  cString & GetName()           { return name; }
+  cInjectGenotype * GetNext()         { return next; }
+  cInjectGenotype * GetPrev()         { return prev; }
+  bool GetThreshold() const     { return flag_threshold; }
+  int GetID() const             { return id_num; }
+  char GetSymbol() const        { return symbol; }
+
+  int AddParasite();
+  int RemoveParasite();
+  //int AddParasite()        { return ++total_parasites; }
+  //void SwapOrganism()      { total_organisms++; }
+  int GetNumInjected()    { return num_injected; }
+  int GetTotalInjected()  { return total_injected; }
+  //int GetTotalParasites()  { return total_parasites; }
+};
+
+// The genotype pointer template...
+
+
+
+// All the inline stuff...
+
+  ////////////////
+ //  cGenotype //
+////////////////
+
+inline void cInjectGenotype::SetThreshold()
+{
+  flag_threshold = true;
+  if (symbol == '.') symbol = '+';
+}
+
+/*
+inline void cGenotype::SetBreedStats(cGenotype & daughter)
+{
+  birth_data.birth_track.Inc();
+  if (daughter.id_num == id_num) {
+    birth_data.breed_true_track.Inc();
+  } else {
+    birth_data.breed_out_track.Inc();
+    daughter.birth_data.breed_in_track.Inc();
+  }
+}*/
+
+#endif
Index: avida/current/source/main/inst_set.cc
diff -u /dev/null avida/current/source/main/inst_set.cc:1.7
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/inst_set.cc	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,148 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef INST_SET_HH
+#include "inst_set.hh"
+#endif
+
+#ifndef STRING_UTIL_HH
+#include "string_util.hh"
+#endif
+#ifndef TOOLS_HH
+#include "tools.hh"
+#endif
+
+using namespace std;
+
+//////////////////////
+//  cInstSet
+//////////////////////
+
+// Initialize static variables
+const cInstruction cInstSet::inst_default(   0 );
+cInstruction cInstSet::inst_default2(   0 );
+cInstruction cInstSet::inst_error2  ( 255 );
+
+cInstSet::cInstSet()
+{
+}
+
+cInstSet::cInstSet(const cInstSet & in_inst_set)
+  : m_inst_lib(in_inst_set.m_inst_lib)
+  , m_lib_name_map(in_inst_set.m_lib_name_map)
+  , m_lib_nopmod_map(in_inst_set.m_lib_nopmod_map)
+  , mutation_chart2(in_inst_set.mutation_chart2)
+{
+}
+
+cInstSet::~cInstSet()
+{
+}
+
+cInstSet & cInstSet::operator=(const cInstSet & _in)
+{
+  m_inst_lib = _in.m_inst_lib;
+  m_lib_name_map = _in.m_lib_name_map;
+  m_lib_nopmod_map = _in.m_lib_nopmod_map;
+  mutation_chart2 = _in.mutation_chart2;
+  return *this;
+}
+
+bool cInstSet::OK() const
+{
+  assert(m_lib_name_map.GetSize() < 256);
+  assert(m_lib_nopmod_map.GetSize() < m_lib_name_map.GetSize());
+
+  // Make sure that all of the redundancies are represented the appropriate
+  // number of times.
+  tArray<int> test_redundancy2(m_lib_name_map.GetSize());
+  test_redundancy2.SetAll(0);
+  for (int i = 0; i < mutation_chart2.GetSize(); i++) {
+    int test_id = mutation_chart2[i];
+    test_redundancy2[test_id]++;
+  }
+  for (int i = 0; i < m_lib_name_map.GetSize(); i++) {
+    assert(m_lib_name_map[i].redundancy == test_redundancy2[i]);
+  }
+
+  return true;
+}
+
+cInstruction cInstSet::GetRandomInst() const
+{
+  int inst_op = mutation_chart2[g_random.GetUInt(mutation_chart2.GetSize())];
+  return cInstruction(inst_op);
+}
+
+int cInstSet::Add2(
+  const int lib_fun_id,
+  const int redundancy,
+  const int ft_cost,
+  const int cost,
+  const double prob_fail
+)
+{
+  const int inst_id = m_lib_name_map.GetSize();
+
+  assert(inst_id < 255);
+
+  // Increase the size of the array...
+  m_lib_name_map.Resize(inst_id + 1);
+
+  // Setup the new function...
+  m_lib_name_map[inst_id].lib_fun_id = lib_fun_id;
+  m_lib_name_map[inst_id].redundancy = redundancy;
+  m_lib_name_map[inst_id].cost = cost;
+  m_lib_name_map[inst_id].ft_cost = ft_cost;
+  m_lib_name_map[inst_id].prob_fail = prob_fail;
+
+  const int total_redundancy = mutation_chart2.GetSize();
+  mutation_chart2.Resize(total_redundancy + redundancy);
+  for (int i = 0; i < redundancy; i++) {
+    mutation_chart2[total_redundancy + i] = inst_id;
+  }
+
+  return inst_id;
+}
+
+int cInstSet::AddNop2(
+  const int lib_nopmod_id,
+  const int redundancy,
+  const int ft_cost,
+  const int cost,
+  const double prob_fail
+)
+{ 
+  // Assert nops are at the _beginning_ of an inst_set.
+  assert(m_lib_name_map.GetSize() == m_lib_nopmod_map.GetSize());
+
+  const int inst_id = Add2(lib_nopmod_id, redundancy, ft_cost, cost, prob_fail);
+
+  m_lib_nopmod_map.Resize(inst_id + 1);
+  m_lib_nopmod_map[inst_id] = lib_nopmod_id;
+
+  return inst_id;
+}
+
+cString cInstSet::FindBestMatch(const cString & in_name) const
+{
+  int best_dist = 1024;
+  cString best_name("");
+  
+  for (int i = 0; i < m_lib_name_map.GetSize(); i++) {
+    const cString & cur_name = m_inst_lib->GetName(m_lib_name_map[i].lib_fun_id);
+    const int cur_dist = cStringUtil::EditDistance(cur_name, in_name);
+    if (cur_dist < best_dist) {
+      best_dist = cur_dist;
+      best_name = cur_name;
+    }
+    if (cur_dist == 0) break;
+  }
+
+  return best_name;
+}
+
Index: avida/current/source/main/inst_set.hh
diff -u /dev/null avida/current/source/main/inst_set.hh:1.5
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/inst_set.hh	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,188 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef INST_SET_HH
+#define INST_SET_HH
+
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+#ifndef TARRAY_HH
+#include "tArray.hh"
+#endif
+#ifndef INSTRUCTION_HH
+#include "instruction.hh"
+#endif
+#ifndef INST_LIB_BASE_HH
+#include "inst_lib_base.hh"
+#endif
+
+// A typdef to simplify having an instruction point to methods in the
+// cHardwareBase object and its dirivitives...
+class cHardwareBase;
+
+// moved to cpu/hardware_method.hh for porting to gcc 3.1 -- k
+//typedef bool (cHardwareBase::*tHardwareMethod)();
+
+class cInstLibBase;
+
+/**
+ * This class is used to create a mapping from the command strings in
+ * an organism's genome into real methods in one of the hardware objects.  This
+ * object has been designed to allow easy manipulation of the instruction
+ * sets, as well as multiple instruction sets within a single soup (just
+ * attach different cInstSet objects to different hardware.
+ **/
+
+class cInstLibBase; // access
+template <class T> class tArray; // aggregate
+class cInstruction; // access
+class cString; // access
+
+class cInstSet {
+public:
+  cInstLibBase *m_inst_lib;
+  class cInstEntry2 {
+  public:
+    int lib_fun_id;
+    int redundancy;           // Weight in instruction set (not impl.)
+    int cost;                 // additional time spent to exectute inst.
+    int ft_cost;              // time spent first time exec (in add to cost)
+    double prob_fail;         // probability of failing to execute inst
+  };
+  tArray<cInstEntry2> m_lib_name_map;
+  tArray<int> m_lib_nopmod_map;
+  tArray<int> mutation_chart2;     // ID's represented by redundancy values.
+  // Static components...
+  static cInstruction inst_error2;
+  // static const cInstruction inst_none;
+  static cInstruction inst_default2;
+
+  // Static components...
+  static const cInstruction inst_error;
+  // static const cInstruction inst_none;
+  static const cInstruction inst_default;
+
+public:
+  cInstSet();
+  cInstSet(const cInstSet & in_inst_set);
+  ~cInstSet();
+
+  cInstSet & operator=(const cInstSet & _in);
+
+  bool OK() const;
+
+  // Accessors
+  const cString & GetName(int id) const
+  { 
+    return m_inst_lib->GetName(m_lib_name_map[id].lib_fun_id);
+  }
+  const cString & GetName(const cInstruction & inst) const
+  {
+    return GetName(inst.GetOp());
+  }
+  int GetCost(const cInstruction & inst) const
+  {
+    return m_lib_name_map[inst.GetOp()].cost;
+  }
+  int GetFTCost(const cInstruction & inst) const
+  {
+    return m_lib_name_map[inst.GetOp()].ft_cost;
+  }
+  double GetProbFail(const cInstruction & inst) const
+  {
+    return m_lib_name_map[inst.GetOp()].prob_fail;
+  }
+  int GetRedundancy(const cInstruction & inst) const
+  {
+    return m_lib_name_map[inst.GetOp()].redundancy;
+  }
+
+  int GetLibFunctionIndex(const cInstruction & inst) const
+  {
+    return m_lib_name_map[inst.GetOp()].lib_fun_id;
+  }
+
+  int GetNopMod(const cInstruction & inst) const
+  {
+    return m_inst_lib->GetNopMod(m_lib_nopmod_map[inst.GetOp()]);
+  }
+
+  cInstruction GetRandomInst() const;
+  int GetRandFunctionIndex() const
+  {
+    return m_lib_name_map[ GetRandomInst().GetOp() ].lib_fun_id;
+  }
+
+  int GetSize() const {
+    return m_lib_name_map.GetSize();
+  }
+  int GetNumNops() const {
+    return m_lib_nopmod_map.GetSize();
+  }
+
+  // Instruction Analysis.
+  int IsNop(const cInstruction & inst) const
+  {
+    return (inst.GetOp() < m_lib_nopmod_map.GetSize());
+  }
+
+  // Insertion of new instructions...
+  int Add2(
+    const int lib_fun_id,
+    const int redundancy=1,
+    const int ft_cost=0,
+    const int cost=0,
+    const double prob_fail=0.0
+  );
+  int AddNop2(
+    const int lib_nopmod_id,
+    const int redundancy=1,
+    const int ft_cost=0,
+    const int cost=0,
+    const double prob_fail=0.0
+  );
+
+  // accessors for instruction library
+  cInstLibBase *GetInstLib(){ return m_inst_lib; }
+  void SetInstLib(cInstLibBase *inst_lib){
+    m_inst_lib = inst_lib;
+    inst_error2 = inst_lib->GetInstError();
+    inst_default2 = inst_lib->GetInstDefault();
+  }
+
+  inline cInstruction GetInst(const cString & in_name) const;
+  cString FindBestMatch(const cString & in_name) const;
+
+  // Static methods..
+  static const cInstruction & GetInstDefault() {
+    return inst_default2;
+  }
+  static const cInstruction & GetInstError()   {
+    return inst_error2;
+  }
+  // static const cInstruction & GetInstNone()    { return inst_none; }
+};
+
+
+inline cInstruction cInstSet::GetInst(const cString & in_name) const
+{
+  for (int i = 0; i < m_lib_name_map.GetSize(); i++) {
+    if (m_inst_lib->GetName(m_lib_name_map[i].lib_fun_id) == in_name) {
+      return cInstruction(i);
+    }
+  }
+  // Adding default answer if nothing is found...
+  /*
+  FIXME:  this return value is supposed to be cInstSet::GetInstError
+  which should be the same as m_inst_lib->GetInstError().
+  -- kgn
+  */
+  return cInstruction(0);
+}
+
+#endif
Index: avida/current/source/main/inst_util.cc
diff -u /dev/null avida/current/source/main/inst_util.cc:1.16
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/inst_util.cc	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,109 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#include "inst_util.hh"
+
+#include "string.hh"
+#include "file.hh"
+
+#ifndef INIT_FILE_HH
+#include "init_file.hh"
+#endif
+
+#include "inst_set.hh"
+#include "genome.hh"
+
+
+using namespace std;
+
+
+cGenome cInstUtil::LoadGenome(const cString & filename,
+			      const cInstSet & inst_set)
+{
+    cInitFile input_file(filename);
+  if (!input_file.IsOpen()) {
+    cerr << "Cannot open file: " << filename << endl;
+    return cGenome(1);
+  }
+  input_file.Load();
+  input_file.Compress();
+  input_file.Close();
+
+  // Setup the code array...
+  cGenome new_genome(input_file.GetNumLines());
+
+  for (int line_num = 0; line_num < new_genome.GetSize(); line_num++) {
+    cString cur_line = input_file.GetLine(line_num);
+    new_genome[line_num] = inst_set.GetInst(cur_line);
+
+    if (new_genome[line_num] == cInstSet::GetInstError()) {
+      // You're using the wrong instruction set!  YOU FOOL!
+      cerr << "Cannot load organism '" << filename << "'" << endl
+	   << "       Unknown line: " << cur_line
+	   << " (best match is '" << inst_set.FindBestMatch(cur_line) << "')"
+	   << endl;
+      exit(1);
+    }
+  }
+
+  if(new_genome.GetSize()==0)
+    cerr << "WARNING: Genome size is 0!" << endl;
+
+  return new_genome;
+}
+
+cGenome cInstUtil::LoadInternalGenome(istream & fp, const cInstSet &inst_set)
+{
+  assert(fp.good()); // Invalid stream to load genome from!
+
+  int num_lines = -1;
+  fp >> num_lines;
+
+  if (num_lines <= 0) { return cGenome(1); }
+
+  // Setup the code array...
+  cGenome new_genome(num_lines);
+  cString cur_line;
+
+  for (int line_num = 0; line_num < new_genome.GetSize(); line_num++) {
+    fp >> cur_line;
+    new_genome[line_num] = inst_set.GetInst(cur_line);
+
+    if (new_genome[line_num] == cInstSet::GetInstError()) {
+      // You're using the wrong instruction set!  YOU FOOL!
+      cerr << "Cannot load creature from stream:" << endl
+	   << "       Unknown line: " << cur_line << endl;
+    }
+  }
+  return new_genome;
+}
+
+void cInstUtil::SaveGenome(ostream & fp, const cInstSet & inst_set,
+			   const cGenome & gen)
+{
+  for (int i = 0; i < gen.GetSize(); i++) {
+    fp << inst_set.GetName(gen[i]) << endl;
+  }
+}
+
+void cInstUtil::SaveInternalGenome(ostream & fp, const cInstSet & inst_set,
+				   const cGenome & gen)
+{
+  fp << gen.GetSize() << endl;
+  SaveGenome(fp, inst_set, gen);
+}
+
+
+cGenome cInstUtil::RandomGenome(int length, const cInstSet & inst_set)
+{
+  cGenome genome(length);
+  for (int i = 0; i < length; i++) {
+    genome[i] = inst_set.GetRandomInst();
+  }
+  return genome;
+}
+
Index: avida/current/source/main/inst_util.hh
diff -u /dev/null avida/current/source/main/inst_util.hh:1.10
--- /dev/null	Tue Nov 25 09:38:02 2003
+++ avida/current/source/main/inst_util.hh	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,39 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef INST_UTIL_HH
+#define INST_UTIL_HH
+
+#include <iostream>
+
+#ifndef GENOME_HH
+#include "genome.hh"
+#endif
+
+class cInitFile;
+class cInstSet;
+class cString;
+class cInstUtil {
+public:
+
+  // ========= Genome-File Interaction =========
+  // Saving and loading of files.  These functions assume that the genome is
+  // the only thing in the file unless 'Internal' is in the function name
+  // (Internal genomes must begin with a number that indicates genome length)
+
+  static cGenome LoadGenome(const cString &filename, const cInstSet &inst_set);
+  static cGenome LoadInternalGenome(std::istream & fp, const cInstSet &inst_set);
+  static void SaveGenome(std::ostream &fp, const cInstSet & inst_set,
+			 const cGenome &gen);
+  static void SaveInternalGenome(std::ostream &fp, const cInstSet &inst_set,
+				 const cGenome &gen);
+
+  // ========= Genome Construction =========
+  static cGenome RandomGenome(int length, const cInstSet & inst_set);
+};
+
+#endif
Index: avida/current/source/main/landscape.cc
diff -u /dev/null avida/current/source/main/landscape.cc:1.24
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/landscape.cc	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,830 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef LANDSCAPE_HH
+#include "landscape.hh"
+#endif
+
+#ifndef CPU_MEMORY_HH
+#include "cpu_memory.hh"
+#endif
+#ifndef ENVIRONMENT_HH
+#include "environment.hh"
+#endif
+#ifndef INST_SET_HH
+#include "inst_set.hh"
+#endif
+#ifndef ORGANISM_HH
+#include "organism.hh"
+#endif
+#ifndef PHENOTYPE_HH
+#include "phenotype.hh"
+#endif
+#ifndef STATS_HH
+#include "stats.hh"             // For GetUpdate in outputs...
+#endif
+#ifndef TEST_CPU_HH
+#include "test_cpu.hh"
+#endif
+#ifndef TEST_UTIL_HH
+#include "test_util.hh"
+#endif
+#ifndef TOOLS_HH
+#include "tools.hh"
+#endif
+
+using namespace std;
+
+
+////////////////
+//  cLandscape
+////////////////
+
+cLandscape::cLandscape(const cGenome & in_genome, const cInstSet & in_inst_set)
+  : inst_set(in_inst_set), base_genome(1), peak_genome(1)
+{
+  site_count = NULL;
+  Reset(in_genome);
+}
+
+cLandscape::~cLandscape()
+{
+  if (site_count != NULL) delete [] site_count;
+}
+
+void cLandscape::Reset(const cGenome & in_genome)
+{
+  base_genome       = in_genome;
+  peak_genome       = in_genome;
+  base_fitness    = 0.0;
+  base_merit      = 0.0;
+  base_gestation  = 0;
+  peak_fitness    = 0.0;
+  total_fitness   = 0.0;
+  total_sqr_fitness = 0.0;
+  distance        = 0;
+  del_distance    = 0;
+  ins_distance    = 0;
+  trials          = 0;
+
+  total_count   = 0;
+  dead_count    = 0;
+  neg_count     = 0;
+  neut_count    = 0;
+  pos_count     = 0;
+
+  if (site_count != NULL) delete [] site_count;
+  site_count = new int[base_genome.GetSize() + 1];
+  for (int i = 0; i <= base_genome.GetSize(); i++) site_count[i] = 0;
+
+  total_entropy = 0.0;
+  complexity = 0.0;
+  neut_min = 0.0;
+  neut_max = 0.0;
+}
+
+void cLandscape::ProcessGenome(cGenome & in_genome)
+{
+  cTestCPU::TestGenome(test_info, in_genome);
+
+  test_fitness = test_info.GetColonyFitness();
+
+  total_fitness += test_fitness;
+  total_sqr_fitness += test_fitness * test_fitness;
+
+  total_count++;
+  if (test_fitness == 0) {
+    dead_count++;
+  } else if (test_fitness < neut_min) {
+    neg_count++;
+  } else if (test_fitness <= neut_max) {
+    neut_count++;
+  } else {
+    pos_count++;
+    if (test_fitness > peak_fitness) {
+      peak_fitness = test_fitness;
+      peak_genome = in_genome;
+    }
+  }
+}
+
+void cLandscape::ProcessBase()
+{
+  // Collect info on base creature.
+
+  cTestCPU::TestGenome(test_info, base_genome);
+
+  cPhenotype & phenotype = test_info.GetColonyOrganism()->GetPhenotype();
+  base_fitness = phenotype.GetFitness();
+  base_merit = phenotype.GetMerit().GetDouble();
+  base_gestation = phenotype.GetGestationTime();
+   
+  peak_fitness = base_fitness;
+  peak_genome = base_genome;
+  
+  neut_min = base_fitness * FITNESS_NEUTRAL_MIN;
+  neut_max = base_fitness * FITNESS_NEUTRAL_MAX;
+  
+}
+
+void cLandscape::Process(int in_distance)
+{
+  distance = in_distance;
+
+  // Get the info about the base creature.
+  ProcessBase();
+
+  // Now Process the new creature at the proper distance.
+  Process_Body(base_genome, distance, 0);
+
+  // Calculate the complexity...
+
+  double max_ent = log((double) inst_set.GetSize());
+  for (int i = 0; i < base_genome.GetSize(); i++) {
+    total_entropy += (log((double) site_count[i] + 1) / max_ent);
+  }
+  complexity = base_genome.GetSize() - total_entropy;
+}
+
+
+// For distances greater than one, this needs to be called recursively.
+
+void cLandscape::Process_Body(cGenome & cur_genome, int cur_distance,
+			      int start_line)
+{
+  const int max_line = base_genome.GetSize() - cur_distance + 1;
+  const int inst_size = inst_set.GetSize();
+
+  cGenome mod_genome(cur_genome);
+
+  // Loop through all the lines of genome, testing trying all combinations.
+  for (int line_num = start_line; line_num < max_line; line_num++) {
+    int cur_inst = base_genome[line_num].GetOp();
+
+    // Loop through all instructions...
+    for (int inst_num = 0; inst_num < inst_size; inst_num++) {
+      if (cur_inst == inst_num) continue;
+
+      mod_genome[line_num].SetOp(inst_num);
+      if (cur_distance <= 1) {
+	ProcessGenome(mod_genome);
+	if (test_info.GetColonyFitness() >= neut_min) site_count[line_num]++;
+      } else {
+	Process_Body(mod_genome, cur_distance - 1, line_num + 1);
+      }
+    }
+
+    mod_genome[line_num].SetOp(cur_inst);
+  }
+
+}
+
+void cLandscape::ProcessDelete()
+{
+  // Get the info about the base creature.
+  ProcessBase();
+
+  const int max_line = base_genome.GetSize();
+  cCPUMemory mod_genome(base_genome);
+
+  // Loop through all the lines of genome, testing all deletions.
+  for (int line_num = 0; line_num < max_line; line_num++) {
+    int cur_inst = base_genome[line_num].GetOp();
+    mod_genome.Remove(line_num);
+    ProcessGenome(mod_genome);
+    if (test_info.GetColonyFitness() >= neut_min) site_count[line_num]++;
+    mod_genome.Insert(line_num, cInstruction(cur_inst));
+  }
+
+}
+
+void cLandscape::ProcessInsert()
+{
+  // Get the info about the base creature.
+  ProcessBase();
+
+  const int max_line = base_genome.GetSize();
+  const int inst_size = inst_set.GetSize();
+
+  cCPUMemory mod_genome(base_genome);
+
+  // Loop through all the lines of genome, testing all insertions.
+  for (int line_num = 0; line_num <= max_line; line_num++) {
+    // Loop through all instructions...
+    for (int inst_num = 0; inst_num < inst_size; inst_num++) {
+      mod_genome.Insert(line_num, cInstruction(inst_num));
+      ProcessGenome(mod_genome);
+      if (test_info.GetColonyFitness() >= neut_min) site_count[line_num]++;
+      mod_genome.Remove(line_num);
+    }
+  }
+
+}
+
+// Prediction for a landscape where n sites are _randomized_.
+void cLandscape::PredictWProcess(ostream & fp, int update)
+{
+  distance = 1;
+
+  // Get the info about the base creature.
+  ProcessBase();
+  if (base_fitness == 0.0) return;
+
+  BuildFitnessChart();
+  const int genome_size = fitness_chart.GetNumRows();
+  const int inst_size = fitness_chart.GetNumCols();
+  const double min_neut_fitness = 0.99;
+  const double max_neut_fitness = 1.01;
+
+  // Loop through the entries printing them and doing additional
+  // calculations.
+  int total_pos_found = 0;
+  int total_neut_found = 0;
+  int total_neg_found = 0;
+  int total_dead_found = 0;
+  double max_fitness = 1.0;
+  double total_fitness = 0.0;
+  double total_sqr_fitness = 0.0;
+
+  for (int row = 0; row < genome_size; row++) {
+    double max_line_fitness = 1.0;
+    for (int col = 0; col < inst_size; col++) {
+      double & cur_fitness = fitness_chart(row, col);
+      cur_fitness /= base_fitness;
+      total_fitness += cur_fitness;
+      total_sqr_fitness += cur_fitness * cur_fitness;
+      if (cur_fitness > max_neut_fitness) total_pos_found++;
+      else if (cur_fitness > min_neut_fitness) total_neut_found++;
+      else if (cur_fitness > 0.0) total_neg_found++;
+
+      if (cur_fitness > max_line_fitness) max_line_fitness = cur_fitness;
+    }
+    max_fitness *= max_line_fitness;
+  }
+
+  const int total_tests = genome_size * inst_size;
+  total_dead_found = total_tests - total_pos_found - total_neut_found - total_neg_found;
+  fp << update << " "
+     << "1 "
+     << ((double) total_dead_found / (double) total_tests) << " "
+     << ((double) total_neg_found / (double) total_tests)  << " "
+     << ((double) total_neut_found / (double) total_tests) << " "
+     << ((double) total_pos_found / (double) total_tests)  << " "
+     << total_tests                                        << " "
+     << total_neut_found + total_pos_found                 << " "
+     << total_fitness / (double) total_tests               << " "
+     << total_sqr_fitness / (double) total_tests           << " "
+     << endl;
+  fp.flush();
+
+  // Sample the table out to 10 mutations
+  const int max_muts = 10;
+  const int min_found = 100;
+  const int min_tests = 10000;
+  const int max_tests = 1000000000;
+
+  double test_fitness;
+  for (int num_muts = 2; num_muts <= max_muts; num_muts++) {
+    total_pos_found = 0;
+    total_neut_found = 0;
+    total_neg_found = 0;
+    total_fitness = 0.0;
+    total_sqr_fitness = 0.0;
+    tArray<int> mut_lines(num_muts);
+
+    int test_id = 0;
+    while ((test_id < min_tests) ||
+	   (test_id < max_tests && (total_neut_found + total_pos_found) < min_found)) {
+      g_random.Choose(genome_size, mut_lines);
+      test_fitness = 1.0;
+      for (int j = 0; j < num_muts && test_fitness != 0.0; j++) {	
+	test_fitness *=
+	  fitness_chart(mut_lines[j], g_random.GetUInt(inst_size));
+      }
+      total_fitness += test_fitness;
+      total_sqr_fitness += test_fitness * test_fitness;
+      if (test_fitness > max_neut_fitness) total_pos_found++;
+      else if (test_fitness > min_neut_fitness) total_neut_found++;
+      else if (test_fitness > 0.0) total_neg_found++;
+
+      test_id++;
+    }
+
+    total_dead_found = test_id - total_pos_found - total_neut_found - total_neg_found;
+    fp << update                                         << " " //  1
+       << num_muts                                       << " " //  2
+       << ((double) total_dead_found / (double) test_id) << " " //  3
+       << ((double) total_neg_found / (double) test_id)  << " " //  4
+       << ((double) total_neut_found / (double) test_id) << " " //  5
+       << ((double) total_pos_found / (double) test_id)  << " " //  6
+       << test_id                                        << " " //  7
+       << total_neut_found + total_pos_found             << " " //  8
+       << total_fitness / (double) test_id               << " " //  9
+       << total_sqr_fitness / (double) test_id           << " " // 10
+       << endl;
+    fp.flush();
+
+    if (total_pos_found + total_neut_found < min_found / 2) break;
+  }
+
+  // Calculate the complexity...
+
+  double max_ent = log((double) inst_set.GetSize());
+  for (int i = 0; i < base_genome.GetSize(); i++) {
+    total_entropy += (log((double) site_count[i] + 1) / max_ent);
+  }
+  complexity = base_genome.GetSize() - total_entropy;
+}
+
+
+// Prediction for a landscape where n sites are _mutated_.
+void cLandscape::PredictNuProcess(ostream & fp, int update)
+{
+  distance = 1;
+
+  // Get the info about the base creature.
+  ProcessBase();
+  if (base_fitness == 0.0) return;
+
+  BuildFitnessChart();
+  const int genome_size = fitness_chart.GetNumRows();
+  const int inst_size = fitness_chart.GetNumCols();
+  const double min_neut_fitness = 0.99;
+  const double max_neut_fitness = 1.01;
+
+  // Loop through the entries printing them and doing additional
+  // calculations.
+  int total_pos_found = 0;
+  int total_neut_found = 0;
+  int total_neg_found = 0;
+  int total_dead_found = 0;
+  int total_live_found = 0;
+  double max_fitness = 1.0;
+  double max_found_fitness = 0.0;
+  double total_fitness = 0.0;
+  double total_sqr_fitness = 0.0;
+
+  for (int row = 0; row < genome_size; row++) {
+    double max_line_fitness = 1.0;
+    int base_inst = base_genome[row].GetOp();
+    for (int col = 0; col < inst_size; col++) {
+      if (col == base_inst) continue; // Only consider changes to line!
+      double & cur_fitness = fitness_chart(row, col);
+      cur_fitness /= base_fitness;
+      total_fitness += cur_fitness;
+      total_sqr_fitness += cur_fitness * cur_fitness;
+      if (cur_fitness > max_neut_fitness) total_pos_found++;
+      else if (cur_fitness > min_neut_fitness) total_neut_found++;
+      else if (cur_fitness > 0.0) total_neg_found++;
+
+      if (cur_fitness > max_line_fitness) max_line_fitness = cur_fitness;
+    }
+    max_fitness *= max_line_fitness;
+    if (max_line_fitness > max_found_fitness) max_found_fitness = max_line_fitness;
+  }
+
+  const int total_tests = genome_size * inst_size;
+  total_live_found = total_pos_found + total_neut_found + total_neg_found;
+  total_dead_found = total_tests - total_live_found;
+  fp << update                                             << " "
+     << "1 "
+     << ((double) total_dead_found / (double) total_tests) << " "
+     << ((double) total_neg_found / (double) total_tests)  << " "
+     << ((double) total_neut_found / (double) total_tests) << " "
+     << ((double) total_pos_found / (double) total_tests)  << " "
+     << total_tests                                        << " "
+     << total_live_found                                   << " "
+     << total_fitness / (double) total_tests               << " "
+     << total_sqr_fitness / (double) total_tests           << " "
+     << max_found_fitness                                   << " "
+     << endl;
+  fp.flush();
+
+  // Sample the table out to 10 mutations
+  const int max_muts = 10;
+  const int min_found = 100;
+  const int min_tests = 10000;
+  const int max_tests = 1000000000;
+
+  double test_fitness;
+  for (int num_muts = 2; num_muts <= max_muts; num_muts++) {
+    total_pos_found = 0;
+    total_neut_found = 0;
+    total_neg_found = 0;
+    total_fitness = 0.0;
+    total_sqr_fitness = 0.0;
+    max_found_fitness = 0.0;
+    tArray<int> mut_lines(num_muts);
+
+    int test_id = 0;
+    while ((test_id < min_tests) ||
+	   (test_id < max_tests && (total_neg_found + total_neut_found + total_pos_found) < min_found)) {
+      g_random.Choose(genome_size, mut_lines);
+      test_fitness = 1.0;
+      for (int j = 0; j < num_muts && test_fitness != 0.0; j++) {	
+	int base_inst = base_genome[ mut_lines[j] ].GetOp();
+	int mut_inst = g_random.GetUInt(inst_size);
+	while (mut_inst == base_inst) mut_inst = g_random.GetUInt(inst_size);
+	test_fitness *= fitness_chart(mut_lines[j], mut_inst);
+	if (test_fitness == 0.0) break;
+      }
+      total_fitness += test_fitness;
+      total_sqr_fitness += test_fitness * test_fitness;
+      if (test_fitness > max_found_fitness) max_found_fitness = test_fitness;
+
+      if (test_fitness > max_neut_fitness) total_pos_found++;
+      else if (test_fitness > min_neut_fitness) total_neut_found++;
+      else if (test_fitness > 0.0) total_neg_found++;
+
+      test_id++;
+    }
+
+    total_live_found = total_neg_found + total_neut_found + total_pos_found;
+    total_dead_found = test_id - total_live_found;
+
+
+    fp << update                                         << " " //  1
+       << num_muts                                       << " " //  2
+       << ((double) total_dead_found / (double) test_id) << " " //  3
+       << ((double) total_neg_found / (double) test_id)  << " " //  4
+       << ((double) total_neut_found / (double) test_id) << " " //  5
+       << ((double) total_pos_found / (double) test_id)  << " " //  6
+       << test_id                                        << " " //  7
+       << total_live_found                               << " " //  8
+       << total_fitness / (double) test_id               << " " //  9
+       << total_sqr_fitness / (double) test_id           << " " // 10
+       << max_found_fitness                              << " " // 11
+       << endl;
+    fp.flush();
+
+    if (total_live_found < min_found / 2) break;
+  }
+
+  // Calculate the complexity...
+
+  double max_ent = log((double) inst_set.GetSize());
+  for (int i = 0; i < base_genome.GetSize(); i++) {
+    total_entropy += (log((double) site_count[i] + 1) / max_ent);
+  }
+  complexity = base_genome.GetSize() - total_entropy;
+}
+
+
+void cLandscape::SampleProcess(int in_trials)
+{
+  trials = in_trials;  // Trials _per line_
+  distance = 1;
+
+  cGenome mod_genome(base_genome);
+  int genome_size = base_genome.GetSize();
+
+  ProcessBase();
+
+  // Loop through all the lines of genome, testing each line.
+  for (int line_num = 0; line_num < genome_size; line_num++) {
+    cInstruction cur_inst( base_genome[line_num] );
+
+    for (int i = 0; i < trials; i++) {
+      // Choose the new instruction for that line...
+      cInstruction new_inst( inst_set.GetRandomInst() );
+      if (cur_inst == new_inst) { i--; continue; }
+
+      // Make the change, and test it!
+      mod_genome[line_num] = new_inst;
+      ProcessGenome(mod_genome);
+    }
+
+    mod_genome[line_num] = cur_inst;
+  }
+}
+
+
+int cLandscape::RandomProcess(int in_trials, int in_distance, int min_found,
+			       int max_trials, bool print_if_found)
+{
+  distance = in_distance;
+
+  cGenome mod_genome(base_genome);
+  int genome_size = base_genome.GetSize();
+
+  ProcessBase();
+
+  int mut_num;
+  tArray<int> mut_lines(distance);
+
+  // Loop through all the lines of genome, testing many combinations.
+  int cur_trial = 0;
+  int total_found = 0;
+
+  for (cur_trial = 0;
+       (cur_trial < in_trials) ||
+	 (total_found < min_found && cur_trial < max_trials);
+       cur_trial++) {
+    // Choose the lines to mutate...
+    g_random.Choose(genome_size, mut_lines);
+
+    // Choose the new instructions for those lines...
+    for (mut_num = 0; mut_num < distance; mut_num++) {
+      const cInstruction new_inst( inst_set.GetRandomInst() );
+      const cInstruction & cur_inst = base_genome[ mut_lines[mut_num] ];
+      if (cur_inst == new_inst) {
+	mut_num--;
+	continue;
+      }
+
+      mod_genome[ mut_lines[mut_num] ] = new_inst;
+    }
+
+    // And test it!
+
+    ProcessGenome(mod_genome);
+
+    // if (test_info.IsViable()) {
+    if (test_fitness >= neut_min) {
+      total_found++;
+      // If we are supposed to print those found, do so!
+      //  if (print_if_found) {
+      //    cString filename;
+      //    filename.Set("creature.land.%d.%d", distance, cur_trial);
+      //    cTestUtil::PrintGenome(mod_genome, filename);
+      //  }
+    }
+
+
+    // And reset the genome.
+    for (mut_num = 0; mut_num < distance; mut_num++) {
+      mod_genome[ mut_lines[mut_num] ] = base_genome[ mut_lines[mut_num] ];
+    }
+  }
+
+  trials = cur_trial;
+
+  return total_found;
+}
+
+void cLandscape::BuildFitnessChart()
+{
+  // First, resize the fitness_chart.
+  const int max_line = base_genome.GetSize();
+  const int inst_size = inst_set.GetSize();
+  fitness_chart.ResizeClear(max_line, inst_size);
+
+  cGenome mod_genome(base_genome);
+
+  // Loop through all the lines of genome, testing trying all combinations.
+  for (int line_num = 0; line_num < max_line; line_num++) {
+    int cur_inst = base_genome[line_num].GetOp();
+
+    // Loop through all instructions...
+    for (int inst_num = 0; inst_num < inst_size; inst_num++) {
+      if (cur_inst == inst_num) {
+	fitness_chart(line_num, inst_num) = base_fitness;
+	continue;
+      }
+
+      mod_genome[line_num].SetOp(inst_num);
+      ProcessGenome(mod_genome);
+      fitness_chart(line_num, inst_num) = test_info.GetColonyFitness();
+    }
+
+    mod_genome[line_num].SetOp(cur_inst);
+  }
+
+}
+
+void cLandscape::TestPairs(int in_trials, ostream & fp)
+{
+  trials = in_trials;
+
+  ProcessBase();
+  if (base_fitness == 0.0) return;
+
+  BuildFitnessChart();
+
+  cGenome mod_genome(base_genome);
+  const int genome_size = base_genome.GetSize();
+
+  tArray<int> mut_lines(2);
+  tArray<cInstruction> mut_insts(2);
+
+  // Loop through all the lines of genome, testing many combinations.
+  for (int i = 0; i < trials; i++) {
+    // Choose the lines to mutate...
+    g_random.Choose(genome_size, mut_lines);
+
+    // Choose the new instructions for those lines...
+    for (int mut_num = 0; mut_num < 2; mut_num++) {
+      const cInstruction new_inst( inst_set.GetRandomInst() );
+      const cInstruction & cur_inst = base_genome[ mut_lines[mut_num] ];
+      if (cur_inst == new_inst) {
+	mut_num--;
+	continue;
+      }
+
+      mut_insts[mut_num] = new_inst;
+    }
+
+    TestMutPair(mod_genome, mut_lines[0], mut_lines[1], mut_insts[0],
+		mut_insts[1], fp);
+
+  }
+
+}
+
+
+void cLandscape::TestAllPairs(ostream & fp)
+{
+  ProcessBase();
+  if (base_fitness == 0.0) return;
+
+  BuildFitnessChart();
+
+  const int max_line = base_genome.GetSize();
+  const int inst_size = inst_set.GetSize();
+  cGenome mod_genome(base_genome);
+  cInstruction inst1, inst2;
+
+  // Loop through all the lines of genome, testing trying all combinations.
+  for (int line1_num = 0; line1_num < max_line - 1; line1_num++) {
+    for (int line2_num = line1_num + 1; line2_num < max_line; line2_num++) {
+
+      // Loop through all instructions...
+      for (int inst1_num = 0; inst1_num < inst_size; inst1_num++) {
+	inst1.SetOp(inst1_num);
+	if (inst1 == base_genome[line1_num]) continue;
+	for (int inst2_num = 0; inst2_num < inst_size; inst2_num++) {
+	  inst2.SetOp(inst2_num);
+	  if (inst2 == base_genome[line2_num]) continue;
+	  TestMutPair(mod_genome, line1_num, line2_num, inst1, inst2, fp);
+	} // inst2_num loop
+      } //inst1_num loop;
+
+    } // line2_num loop
+  } // line1_num loop.
+
+}
+
+
+void cLandscape::HillClimb(ofstream & fp)
+{
+  cGenome cur_genome(base_genome);
+  int gen = 0;
+  HillClimb_Body(fp, cur_genome, gen);
+}
+
+void cLandscape::HillClimb_Body(ofstream & fp, cGenome & cur_genome,
+				int & gen)
+{
+  cCPUMemory mod_genome(base_genome);
+
+  const int inst_size = inst_set.GetSize();
+
+  double pos_frac = 1.0;
+
+  bool finished = false;
+  while (finished == false) {
+    if (pos_frac == 0.0) finished = true;
+
+    // Search the landscape for the next best.
+    Reset(cur_genome);
+    const int max_line = cur_genome.GetSize();
+
+    // Try all Mutations...
+    Process(1);
+
+    // Try Insertion Mutations.
+
+    mod_genome = cur_genome;
+    for (int line_num = 0; line_num <= max_line; line_num++) {
+      // Loop through all instructions...
+      for (int inst_num = 0; inst_num < inst_size; inst_num++) {
+	mod_genome.Insert(line_num, cInstruction(inst_num));
+	ProcessGenome(mod_genome);
+	mod_genome.Remove(line_num);
+      }
+    }
+
+    // Try all deletion mutations.
+
+    for (int line_num = 0; line_num < max_line; line_num++) {
+      int cur_inst = cur_genome[line_num].GetOp();
+      mod_genome.Remove(line_num);
+      ProcessGenome(mod_genome);
+      mod_genome.Insert(line_num, cInstruction(cur_inst));
+    }
+
+    pos_frac = GetProbPos();
+
+    // Print the information on the current best.
+    HillClimb_Print(fp, cur_genome, gen);
+
+    // Move on to the peak genome found.
+    cur_genome = GetPeakGenome();
+    gen++;
+  }
+}
+
+void cLandscape::HillClimb_Neut(ofstream & fp)
+{
+}
+
+void cLandscape::HillClimb_Rand(ofstream & fp)
+{
+}
+
+void cLandscape::HillClimb_Print(ofstream & fp, const cGenome & _genome, const int gen) const
+{
+  cCPUTestInfo test_info;
+  cTestCPU::TestGenome(test_info, _genome);
+  cPhenotype &colony_phenotype = test_info.GetColonyOrganism()->GetPhenotype();
+  fp << gen << " "
+     << colony_phenotype.GetMerit().GetDouble() << " "
+     << colony_phenotype.GetGestationTime() << " "
+     << colony_phenotype.GetFitness() << " "
+     << _genome.GetSize() << " "
+     << GetProbDead() << " "
+     << GetProbNeg() << " "
+     << GetProbNeut() << " "
+     << GetProbPos() << " "
+     << endl;
+}
+
+double cLandscape::TestMutPair(cGenome & mod_genome, int line1, int line2,
+    const cInstruction & mut1, const cInstruction & mut2, ostream & fp)
+{
+  mod_genome[line1] = mut1;
+  mod_genome[line2] = mut2;
+  cTestCPU::TestGenome(test_info, mod_genome);
+  double combo_fitness = test_info.GetColonyFitness() / base_fitness;
+  mod_genome[line1] = base_genome[line1];
+  mod_genome[line2] = base_genome[line2];
+
+  /*
+  fp << line1        << " "
+     << line2        << " "
+     << ( (int) mut1.GetOp() ) << " "
+     << ( (int) mut2.GetOp() ) << " ";
+  */
+
+  fp << ( fitness_chart(line1, mut1.GetOp()) / base_fitness ) << " "
+     << ( fitness_chart(line2, mut2.GetOp()) / base_fitness ) << " "
+     << combo_fitness << endl;
+
+  return combo_fitness;
+}
+
+
+void cLandscape::PrintStats(ofstream & fp, int update)
+{
+  fp << update                 << " "   // 1
+     << GetProbDead()          << " "   // 2
+     << GetProbNeg()           << " "   // 3
+     << GetProbNeut()          << " "   // 4
+     << GetProbPos()           << " "   // 5
+     << total_count            << " "   // 6
+     << distance               << " "   // 7
+     << base_fitness           << " "   // 8
+     << base_merit             << " "   // 9
+     << base_gestation         << " "   // 10
+     << peak_fitness           << " "   // 11
+     << GetAveFitness()        << " "   // 12
+     << GetAveSqrFitness()     << " "   // 13
+     << total_entropy          << " "   // 14
+     << complexity             << endl; // 15
+  fp.flush();
+}
+
+void cLandscape::PrintEntropy(ofstream & fp)
+{
+  double max_ent = log((double) inst_set.GetSize());
+  for (int j = 0; j < base_genome.GetSize(); j++) {
+    fp << (log((double) site_count[j] + 1) / max_ent) << " ";
+  }
+  fp << endl;
+  fp.flush();
+}
+
+void cLandscape::PrintSiteCount(ofstream & fp)
+{
+  for (int j = 0; j < base_genome.GetSize(); j++) {
+    fp << site_count[j] << " ";
+  }
+  fp << endl;
+  fp.flush();
+}
+
+
+void cLandscape::PrintBase(cString filename)
+{
+  cTestUtil::PrintGenome(base_genome, filename);
+}
+
+void cLandscape::PrintPeak(cString filename)
+{
+  cTestUtil::PrintGenome(peak_genome, filename);
+}
+
Index: avida/current/source/main/landscape.hh
diff -u /dev/null avida/current/source/main/landscape.hh:1.19
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/landscape.hh	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,124 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef LANDSCAPE_HH
+#define LANDSCAPE_HH
+
+#include <ostream>
+
+#ifndef CPU_TEST_INFO_HH
+#include "cpu_test_info.hh"
+#endif
+#ifndef GENOME_HH
+#include "genome.hh"
+#endif
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+#ifndef TMATRIX_HH
+#include "tMatrix.hh"
+#endif
+
+class cInstSet;
+class cGenome; // aggregate
+class cCPUTestInfo; // aggregate
+template <class T> class tMatrix; // aggregate
+class cInstruction;
+class cString; // aggregate
+
+struct cLandscape {
+private:
+  const cInstSet & inst_set;
+  cGenome base_genome;
+  cGenome peak_genome;
+  double base_fitness;
+  double base_merit;
+  double base_gestation;
+  double peak_fitness;
+  double total_fitness;
+  double total_sqr_fitness;
+
+  int distance;
+  int del_distance;
+  int ins_distance;
+
+  int trials;
+
+  int total_count;
+
+  int dead_count;
+  int neg_count;
+  int neut_count;
+  int pos_count;
+
+  double test_fitness;
+
+  int * site_count;
+
+  double total_entropy;
+  double complexity;
+
+  cCPUTestInfo test_info;  // Info used for all cpu calculations.
+  double neut_min;         // These two variables are a range around the base
+  double neut_max;         //   fitness to be counted as neutral mutations.
+  tMatrix<double> fitness_chart; // Chart of all one-step mutations.
+
+private:
+  void BuildFitnessChart();
+  void ProcessGenome(cGenome & in_genome);
+  void ProcessBase();
+  void Process_Body(cGenome & cur_genome, int cur_distance, int start_line);
+
+  void HillClimb_Body(std::ofstream & fp, cGenome & cur_genome, int & gen);
+  void HillClimb_Print(std::ofstream & fp, const cGenome & _genome,
+		       const int gen) const;
+
+  double TestMutPair(cGenome & mod_genome, int line1, int line2,
+    const cInstruction & mut1, const cInstruction & mut2, std::ostream & fp);
+public:
+  cLandscape(const cGenome & in_genome, const cInstSet & in_inst_set);
+  ~cLandscape();
+
+  void Reset(const cGenome & in_genome);
+
+  void Process(int in_distance=1);
+  void ProcessDelete();
+  void ProcessInsert();
+  void PredictWProcess(std::ostream & fp, int update=-1);
+  void PredictNuProcess(std::ostream & fp, int update=-1);
+
+  void SampleProcess(int in_trials);
+  int RandomProcess(int in_trials, int in_distance=1, int min_found=0,
+		     int max_trials=0, bool print_if_found=false);
+
+  void TestPairs(int in_trials, std::ostream & fp);
+  void TestAllPairs(std::ostream & fp);
+
+  void HillClimb(std::ofstream & fp);
+  void HillClimb_Neut(std::ofstream & fp);
+  void HillClimb_Rand(std::ofstream & fp);
+
+  void PrintStats(std::ofstream & fp, int update=-1);
+  void PrintEntropy(std::ofstream & fp);
+  void PrintSiteCount(std::ofstream & fp);
+  void PrintBase(cString filename);
+  void PrintPeak(cString filename);
+
+  inline const cGenome & GetPeakGenome() { return peak_genome; }
+  inline double GetAveFitness() { return total_fitness / total_count; }
+  inline double GetAveSqrFitness() { return total_sqr_fitness / total_count; }
+  inline double GetPeakFitness() { return peak_fitness; }
+
+  inline double GetProbDead() const { return ((double)dead_count)/total_count;}
+  inline double GetProbNeg()  const { return ((double)neg_count) /total_count;}
+  inline double GetProbNeut() const { return ((double)neut_count)/total_count;}
+  inline double GetProbPos()  const { return ((double)pos_count) /total_count;}
+
+  inline int GetNumTrials() const { return trials; }
+};
+
+#endif
Index: avida/current/source/main/lineage.cc
diff -u /dev/null avida/current/source/main/lineage.cc:1.18
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/lineage.cc	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,155 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef LINEAGE_HH
+#include "lineage.hh"
+#endif
+#ifndef GENOTYPE_HH
+#include "genotype.hh"
+#endif
+
+using namespace std;
+
+
+bool gt_gentype::operator()(const cGenotype * g1, const cGenotype * g2) const
+{
+  return g1->GetID() > g2->GetID();
+}
+
+int cLineage::m_max_id = 0;
+
+cLineage::cLineage(double start_fitness, int parent_id, int id, int update,
+		   double generation,  double lineage_stat1, double lineage_stat2)
+  : m_parent_id(parent_id)
+  , m_update_born(update)
+  , m_num_CPUs(0)
+  , m_total_CPUs(0)
+  , m_total_genotypes(0)
+  , m_generation_born(generation)
+  , m_lineage_stat1(lineage_stat1)
+  , m_lineage_stat2(lineage_stat2)
+{
+  if ( id < 0 )
+    m_id = m_max_id++;
+  else{
+    m_id = id;
+    if ( id >= m_max_id )
+      m_max_id = id + 1;
+  }
+  m_start_fitness = m_max_fitness = m_max_fitness_ever = start_fitness;
+  m_ave_fitness = 0;
+  m_ave_fitness_changed = true;
+  m_threshold = false;
+}
+
+cLineage::~cLineage()
+{
+}
+
+void cLineage::AddCreature(cGenotype * genotype)
+{
+  // add the new genotype to the map if necessary, otherwise
+  // find its position
+  pair<map<const cGenotype *, int, gt_gentype>::iterator, bool> p =
+    m_genotype_map.insert( pair<const cGenotype*, int>( genotype, 0 ) );
+
+  // did we add a new genotype?
+  if ( ( p.second ) == true )
+    m_total_genotypes += 1;
+
+  // increase the count for the given genotype by one.
+  (*(p.first)).second += 1;
+
+  // The above lines could be written like that:
+  //     m_genotype_map[ genotype ] += 1;
+  // if we didn't want to count how often we add a new genotype
+
+  double fitness = genotype->GetTestColonyFitness();
+
+  // adjust the current maximum fitness
+  if ( fitness > m_max_fitness )
+    m_max_fitness = fitness;
+   // adjust overall maxiumum fitness
+  if ( fitness> m_max_fitness_ever )
+    m_max_fitness_ever = fitness;
+  // the average fitness has changed as well
+  m_ave_fitness_changed = true;
+
+  m_num_CPUs++;
+  m_total_CPUs++;
+}
+
+bool cLineage::RemoveCreature(cGenotype * genotype)
+{
+  // we return true if the removal of this creature triggers a
+  // recalculation of the best lineage
+  bool result = false;
+
+  map<const cGenotype *, int, gt_gentype>::iterator cur = m_genotype_map.find( genotype );
+
+  // is the genotype part of the map?
+  if ( cur == m_genotype_map.end() ){
+    cerr << "Removing creature from lineage whose genotype is not part of the lineage!" << endl;
+    cerr << "  " << genotype->GetName()() << " " << GetID() << endl;
+    return false;
+  }
+
+  // yes, decrease the count
+  (*cur).second -= 1;
+  // and adjust the average fitness
+  m_ave_fitness_changed = true;
+
+  double fitness = genotype->GetTestColonyFitness();
+
+  // did we reach zero?
+  if ( (*cur).second == 0 ){
+    // yes, remove the entry
+    m_genotype_map.erase( cur );
+    // make sure that the maximum fitness is correct
+    if (fitness == m_max_fitness) CalcCurrentFitness();
+    // adjust the return value
+    result = true;
+  }
+
+  // and now the total cpu count
+  m_num_CPUs--;
+
+  return result;
+}
+
+int cLineage::CountNumCreatures() const
+{
+  int creature_count = 0;
+
+  map<const cGenotype *, int, gt_gentype>::const_iterator it =
+    m_genotype_map.begin();
+
+  for ( ; it!=m_genotype_map.end(); it++ )
+    creature_count += (*it).second;
+
+  return creature_count;
+}
+
+void cLineage::CalcCurrentFitness() const
+{
+  m_max_fitness = 0.0;
+  map<const cGenotype *, int, gt_gentype>::const_iterator it =
+    m_genotype_map.begin();
+
+  // we calculate the average fitness as well, since it is so easy.
+  m_ave_fitness = 0;
+  for ( ; it!=m_genotype_map.end(); it++ ){
+    double fitness = (*it).first->GetTestColonyFitness();
+    if (fitness > m_max_fitness) m_max_fitness = fitness;
+    if (fitness > m_max_fitness_ever) m_max_fitness_ever = fitness;
+    m_ave_fitness += fitness * (*it).second;
+  }
+  m_ave_fitness /= (double) m_num_CPUs;
+  m_ave_fitness_changed = false;
+}
+
+
Index: avida/current/source/main/lineage.hh
diff -u /dev/null avida/current/source/main/lineage.hh:1.16
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/lineage.hh	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,168 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef LINEAGE_HH
+#define LINEAGE_HH
+
+#include <map>
+
+class cGenotype;
+
+// struct to compare to genotypes
+struct gt_gentype
+{
+  bool operator()(const cGenotype * g1, const cGenotype * g2) const;
+};
+
+class cLineage {
+private:
+  static int m_max_id;
+  int m_id;
+  int m_parent_id;
+  int m_update_born;
+  int m_num_CPUs;
+  int m_total_CPUs;
+  int m_total_genotypes;
+  double m_start_fitness;
+  mutable double m_max_fitness;
+  mutable double m_ave_fitness;
+  double m_generation_born;
+
+  std::map<const cGenotype *, int, gt_gentype> m_genotype_map;
+  bool m_threshold;
+  mutable bool m_ave_fitness_changed;
+  mutable double m_max_fitness_ever;
+  double m_lineage_stat1;
+  double m_lineage_stat2;
+
+  void CalcCurrentFitness() const;
+public:
+  /**
+   * Creates a new lineage with a given start fitness and parent id.
+   * The first genotype has to be added with AddGenotype later.
+   *
+   * @param start_fitness The initial fitness of the lineage.
+   * @param parent_id The id of the parent's lineage.
+   * @param id The requested id for this lineage. If negative, a generated
+   * value is used. Attention: if you request lineage id's, it is your
+   * responsibility not to request two identical ones for different lineages
+   * (the class @ref cLineageControl does that correctly).
+   **/
+  cLineage(double start_fitness, int parent_id, int id,
+	   int update, double generation,
+	   double lineage_stat1 = 0.0, double lineage_stat2 = 0.0);
+  ~cLineage();
+
+  /**
+   * Adds one instance of the given genotype to the lineage.
+   **/
+  void AddCreature( cGenotype * genotype );
+
+  /**
+   * Removes on instance of the given genotype from the lineage.
+   *
+   * @return True if the removal of this creature potentially creates a new
+   * best lineage, otherwise false.
+   **/
+  bool RemoveCreature( cGenotype * genotype );
+  void SetThreshold() { m_threshold = true; }
+
+  /**
+   * @return The id of the lineage.
+   **/
+  int GetID() const { return m_id; }
+
+  /**
+   * @return The id of the parent lineage.
+   **/
+  int GetParentID() const { return m_parent_id; }
+
+  /**
+   * @return An integer that is one larger than the maximum id used so far.
+   **/
+  int GetMaxID() const { return m_max_id; }
+
+  /**
+   * @return The update at which the lineage was created.
+   **/
+  int GetUpdateBorn() const { return m_update_born; }
+
+  /**
+   * @return The generation at which the lineage was created.
+   **/
+  double GetGenerationBorn() const { return m_generation_born; }
+
+  /**
+   * @return The initial fitness of the lineage.
+   **/
+  double GetStartFitness() const { return m_start_fitness; }
+
+  /**
+   * @return The current maximum fitness of the lineage.
+   **/
+  double GetMaxFitness() const { return m_max_fitness; }
+  
+  /**
+   * @return The average fitness of the lineage.
+   **/
+  double GetAveFitness() const {
+    if ( m_ave_fitness_changed )
+      CalcCurrentFitness();
+    return m_ave_fitness; }
+
+  /**
+   * @return The current number of genotypes in the lineage.
+   **/
+  int GetNumGenotypes() const { return m_genotype_map.size(); }
+
+  /**
+   * @return The current number of creatures in the lineage.
+   **/
+  int GetNumCreatures() const { return m_num_CPUs; }
+
+  /**
+   * Counts the number of creatures in the lineage.
+   *
+   * Should always equal GetNumCreatures(), otherwise something
+   * is wrong.
+   **/
+  int CountNumCreatures() const;
+
+  /**
+   * @return The total number of creatures that have ever existed
+   * in this lineage.
+   **/
+  int GetTotalCreatures() const { return m_total_CPUs; }
+
+  /**
+   * @return The total number of genotypes that have ever been part
+   * of this lineage.
+   **/
+  int GetTotalGenotypes() const { return m_total_genotypes; }
+
+  bool GetThreshold() const { return m_threshold; }
+    
+  /**
+   * @return The maximum fitness ever attained by this lineage
+   **/
+  double GetMaxFitnessEver() const { return m_max_fitness_ever; }
+
+  /**
+   * @return The value of the first fitness criteria for
+   * the creation of this lineage
+   **/
+  double GetLineageStat1 () const { return m_lineage_stat1; }
+
+  /**
+   * @return The value of the second fitness criteria for
+   * the creation of this lineage
+   **/
+  double GetLineageStat2 () const { return m_lineage_stat2; }
+
+};
+
+#endif
Index: avida/current/source/main/lineage_control.cc
diff -u /dev/null avida/current/source/main/lineage_control.cc:1.20
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/lineage_control.cc	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,391 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#include "lineage_control.hh"
+
+#include "string.hh"
+
+#include "lineage.hh"
+#include "stats.hh"
+#include "config.hh"
+#include "genebank.hh"
+#include "genotype.hh"
+#include "organism.hh"
+
+#include "cpu_defs.hh"   // for macro FITNESS_NEUTRAL_MAX
+
+
+using namespace std;
+
+
+/////////////////////
+//  cLineageControl
+/////////////////////
+
+cLineageControl::cLineageControl( cGenebank & genebank, cStats & stats )
+  : m_best_lineage(NULL)
+  , m_max_fitness_lineage(NULL)
+  , m_dominant_lineage(NULL)
+  , m_genebank( genebank )
+  , m_stats( stats )
+{
+}
+
+cLineageControl::~cLineageControl()
+{
+}
+
+
+cLineage *
+cLineageControl::AddLineage( double start_fitness, int parent_lin_id, int id, double lineage_stat1, double lineage_stat2 )
+{
+  cLineage * new_lineage = new cLineage( start_fitness, parent_lin_id, id,
+            		 m_stats.GetUpdate(), m_stats.GetGeneration(), lineage_stat1, lineage_stat2 );
+
+  // the best/ dominant lineage are automatically corrected
+  // when a creature is added to this lineage
+  m_lineage_list.push_back(new_lineage);
+
+  m_stats.AddLineage();
+
+  return new_lineage;
+}
+
+
+void
+cLineageControl::AddCreaturePrivate( cGenotype *genotype,
+				     cLineage * lineage )
+{
+  assert( lineage != 0 );
+
+  // add to the lineage
+  lineage->AddCreature( genotype );
+
+  // This would be nice, but the current Avida code doesn't allow for it.
+  // Try to implement it in a new version...
+  // update the cpu
+  //  cpu->SetLineage( lineage );
+  //  cpu->SetLineageLabel( lineage->GetID() );
+
+  // test whether this makes the new lineage the best
+  if ( !m_best_lineage ||
+       lineage->GetAveFitness() > m_best_lineage->GetAveFitness() )
+    m_best_lineage = lineage;
+
+  // test whether this makes the new lineage the dominant
+  if ( !m_dominant_lineage ||
+       lineage->GetNumCreatures() > m_dominant_lineage->GetNumCreatures() )
+    m_dominant_lineage = lineage;
+
+  // test whether thiw makes the new lineage the one with the maximum fitness
+  if ( !m_max_fitness_lineage ||
+       lineage->GetMaxFitness() > m_max_fitness_lineage->GetMaxFitness() )
+    m_max_fitness_lineage = lineage;
+
+}
+
+void cLineageControl::UpdateLineages()
+{
+  m_best_lineage = NULL;
+  m_dominant_lineage = NULL;
+  m_max_fitness_lineage = NULL;
+
+  list<cLineage *>::iterator it = m_lineage_list.begin();
+  list<cLineage *>::iterator del_it;
+
+  while( it != m_lineage_list.end() ){
+    bool del = false;
+
+    // mark the lineage for removal if empty
+    if ( (*it)->GetNumCreatures() == 0 ){
+      del_it = it;
+      del = true;
+    }
+    else { // otherwise it is a candidate for the best/ dominant/... lineage
+      if ( !m_best_lineage ||
+	   (*it)->GetAveFitness() > m_best_lineage->GetAveFitness() )
+	m_best_lineage = (*it);
+
+      if ( !m_dominant_lineage ||
+	   (*it)->GetNumCreatures() > m_dominant_lineage->GetNumCreatures() )
+	m_dominant_lineage = (*it);
+
+      if ( !m_max_fitness_lineage ||
+	   (*it)->GetMaxFitness() > m_max_fitness_lineage->GetMaxFitness() )
+	m_max_fitness_lineage = (*it);
+
+    }
+    // proceed to the next lineage
+    it++;
+
+    // now do the removal if necessary
+    if ( del ){
+      delete (*del_it); // delete the lineage
+      m_lineage_list.erase( del_it ); // and remove its reference
+    }
+  }
+
+#ifdef DEBUG
+  if ( !m_lineage_list.empty() ){
+    assert( m_dominant_lineage != 0 );
+    assert( m_best_lineage != 0 );
+    assert( m_max_fitness_lineage != 0 );
+  }
+#endif
+
+}
+
+
+cLineage*
+cLineageControl::AddCreature( cGenotype * child_genotype, cGenotype *parent_genotype, cLineage * parent_lineage, int parent_lin_id )
+{
+  // Collect any information we can about the parent.
+  double parent_fitness = 0.0;
+  //  int parent_lin_id = 0;
+
+  // at this point, the cpu has still the lineage from the
+  // parent
+  //  cLineage * parent_lineage = cpu->GetLineage();
+
+#ifdef DEBUG
+  if (parent_lineage != NULL){
+    assert( parent_lin_id == parent_lineage->GetID() );
+  }
+#endif
+
+  if (parent_genotype != NULL) {
+    assert( parent_genotype->GetNumOrganisms() > 0 );
+    parent_fitness = parent_genotype->GetTestColonyFitness();
+  }
+  //cGenotype * child_genotype = cpu->GetActiveGenotype();
+  double child_fitness = child_genotype->GetTestColonyFitness();
+  cLineage * child_lineage = parent_lineage;
+  bool create_lineage = false;
+  double lineage_stat1 = child_fitness;
+  double lineage_stat2 = child_fitness;
+
+  // if we don't have a child lineage, we are probably dealing
+  // with manual assignement of the lineage label
+  if ( child_lineage == NULL ){
+    child_lineage = FindLineage( parent_lin_id );
+    // lineage doesn't exist...
+    if ( child_lineage == NULL ){
+      // create it
+      cout << "Creating new lineage 'by hand'!\nRequested lineage label: " << parent_lin_id;
+      child_lineage = AddLineage(child_fitness, -1, parent_lin_id, 0, 0);
+      cout << ", actual lineage label: " << child_lineage->GetID() << endl;
+
+    }
+  }
+  // otherwise, check for conditions that cause the creation of a new lineage
+  else {
+    switch ( cConfig::GetLineageCreationMethod() ) {
+    case 0: // manual creation only
+      break;
+    case 1: // new lineage whenever a parent has offspring of greater fitness
+      if ( child_fitness > parent_fitness ){
+	create_lineage = true;
+	lineage_stat1 = parent_fitness;
+	lineage_stat2 = 0;
+      }
+      break;
+    case 2: // new lineage whenever a new child exceeds the
+      // currently highest fitness in the population
+      if ( child_fitness > m_max_fitness_lineage->GetMaxFitness() ){
+	create_lineage = true;
+	lineage_stat1 = m_max_fitness_lineage->GetMaxFitness();
+	lineage_stat2 = 0;
+      }
+      break;
+    case 3: // new lineage whenever a new child exceeds the
+      // highest fitness, or when it is a child of the
+      // of the dominant lineage and exceeds that highest fitness
+      if ( child_fitness > m_max_fitness_lineage->GetMaxFitness() ||
+	   ( parent_lineage == m_dominant_lineage
+	     && child_fitness > m_dominant_lineage->GetMaxFitness() ) ){
+	create_lineage = true;
+	lineage_stat1 = m_max_fitness_lineage->GetMaxFitness();
+	lineage_stat2 = m_dominant_lineage->GetMaxFitness();
+      }
+      break;
+    case 4: // new lineage whenever a new child exceeds the
+      // fitness of the dominant creature (and the fitness of its own lineage)
+      if (child_fitness > m_genebank.GetBestGenotype()->GetTestColonyFitness()
+	  && child_fitness > parent_lineage->GetMaxFitness() ){
+	create_lineage = true;
+	lineage_stat1=m_genebank.GetBestGenotype()->GetTestColonyFitness();
+	lineage_stat2=parent_lineage->GetMaxFitness();
+      }
+      break;
+    case 5: // new lineage whenever a new child exceeds the
+      // fitness of the dominant lineage (and the fitness of its own lineage)
+      if ( child_fitness > m_dominant_lineage->GetMaxFitness()
+	   && child_fitness > parent_lineage->GetMaxFitness() ){
+	create_lineage = true;
+	lineage_stat1=m_dominant_lineage->GetMaxFitness();
+	lineage_stat2=parent_lineage->GetMaxFitness();
+      }
+      break;
+    case 6: // new lineage whenever a new child exceeds the
+      // fitness of its own lineage
+      if ( child_fitness > parent_lineage->GetMaxFitness() ){
+	create_lineage = true;
+	lineage_stat1=parent_lineage->GetMaxFitness();
+	lineage_stat2 = 0;
+      }
+      break;
+    case 7: // new lineage whenever a new child exceeds the
+      // maximum fitness ever attained by its parent lineage
+      if (child_fitness > parent_lineage->GetMaxFitnessEver() ) {
+	create_lineage = true;
+	lineage_stat1 = parent_lineage->GetMaxFitnessEver();
+	lineage_stat2 = 0;
+      }
+      break;
+    }
+  }
+  if ( create_lineage ){
+    child_lineage = AddLineage(child_fitness, parent_lin_id, -1, lineage_stat1, lineage_stat2);
+    //    cout << "Lineage " << child_lineage->GetID() << " created."
+    //	 << " Genotype: " << child_genotype->GetName()() << endl;
+  }
+
+  AddCreaturePrivate( child_genotype, child_lineage );
+
+  return child_lineage;
+}
+
+
+void
+cLineageControl::RemoveCreature( cOrganism * cpu )
+{
+  cLineage * cur_lineage = cpu->GetLineage();
+
+  if (cur_lineage) {
+    // remove the creature
+    if ( cur_lineage->RemoveCreature( cpu->GetGenotype() )
+    	 || cur_lineage == m_dominant_lineage
+	 || cur_lineage == m_best_lineage )
+      // If this lineage no longer exists, tell stats...
+      if (cur_lineage->GetNumCreatures() == 0) {
+	m_stats.RemoveLineage( cur_lineage->GetID(),
+			       cur_lineage->GetParentID(),
+			       cur_lineage->GetUpdateBorn(),
+			       cur_lineage->GetGenerationBorn(),
+			       cur_lineage->GetTotalCreatures(),
+			       cur_lineage->GetTotalGenotypes(),
+			       cur_lineage->GetStartFitness(),
+			       cur_lineage->GetLineageStat1(),
+			       cur_lineage->GetLineageStat2() );
+      }
+
+      // recalc the best/dominant lineage if necessary
+      UpdateLineages();
+    cpu->SetLineage( 0 );
+    cpu->SetLineageLabel( -1 );
+  }
+
+}
+
+
+cLineage *
+cLineageControl::FindLineage( int lineage_id ) const
+{
+  list<cLineage *>::const_iterator it = m_lineage_list.begin();
+
+  for ( ; it != m_lineage_list.end(); it++ )
+    if ( (*it)->GetID() == lineage_id )
+      break;
+
+  if ( it == m_lineage_list.end() ){
+    cout << "Lineage " << lineage_id << " not found." << endl;
+    return 0;
+  }
+  else
+    return ( *it );
+}
+
+
+void cLineageControl::PrintLineageTotals(const cString &filename, bool verbose)
+{
+  ofstream & fp = m_stats.GetDataFileOFStream(filename);
+  assert(fp.good());
+
+  fp << m_stats.GetUpdate();
+  const list<cLineage *> & lineage_list = GetLineageList();
+
+  if ( verbose ){ // in verbose format, we print only those
+    // lineages that are actually present, but
+    // we print much more info
+    fp << ": " << m_stats.SumGeneration().Average() << "\n";
+
+    // let's calculate the average fitness in the population also
+    double fitness_sum = 0;
+    double fitness = 0;
+    int total_num_organisms = 0;
+    int num_organisms = 0;
+
+
+    list<cLineage *>::const_iterator it = lineage_list.begin();
+    for ( ; it != lineage_list.end(); it++ ){
+      num_organisms = (*it)->GetNumCreatures();
+      fitness = (*it)->GetAveFitness();
+      fitness_sum += fitness * num_organisms;
+      total_num_organisms += num_organisms;
+      fp << " "
+	 << (*it)->GetID()           << " "
+	 << (*it)->GetParentID()     << " "
+	 << (*it)->GetStartFitness() << " "
+	 << (*it)->GetMaxFitness()   << " "
+	 << fitness                  << " "
+	 << num_organisms            << " "
+	 << (*it)->GetTotalCreatures()    << "\n";
+    }
+    fp << "#Dom: " << GetDominantLineage()->GetID()
+       << ", Max: " << GetMaxFitnessLineage()->GetID()
+       << ", Best: " << GetBestLineage()->GetID()
+       << "\n#Pop. fitness: " << fitness_sum / (double) total_num_organisms
+       << "\n" << endl;
+  }
+  else {
+    fp << " ";
+    int cur_id = 0;
+
+    list<cLineage *>::const_iterator it = lineage_list.begin();
+    for ( ; it != lineage_list.end(); it++ ){
+      int next_id = (*it)->GetID();
+      // wind up the current id to the next id
+      for ( ; cur_id < next_id; cur_id++ )
+	fp << "-1 "; // output -1 when we don't have the data
+      fp << (*it)->GetTotalCreatures() << " ";
+      cur_id += 1;
+    }
+    fp << endl;
+  }
+}
+
+
+void cLineageControl::PrintLineageCurCounts(const cString & filename)
+{
+  ofstream & fp = m_stats.GetDataFileOFStream(filename);
+  assert(fp.good());
+
+  fp << m_stats.GetUpdate() << " ";
+  const list<cLineage *> & lineage_list = GetLineageList();
+
+  list<cLineage *>::const_iterator it = lineage_list.begin();
+  int cur_id = 0;
+  for ( ; it != lineage_list.end(); it++ ){
+    int next_id = (*it)->GetID();
+    // wind up the current id to the next id
+    for ( ; cur_id < next_id; cur_id++ )
+      fp << "0 ";
+    fp << (*it)->GetNumCreatures() << " ";
+    cur_id += 1;
+  }	
+  fp << endl;
+}
Index: avida/current/source/main/lineage_control.hh
diff -u /dev/null avida/current/source/main/lineage_control.hh:1.12
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/lineage_control.hh	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,108 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef LINEAGE_CONTROL_HH
+#define LINEAGE_CONTROL_HH
+
+#include <list>
+
+class cLineage;
+class cGenebank;
+class cStats;
+class cGenotype;
+class cOrganism;
+class cString;
+
+class cLineageControl {
+private:
+  std::list<cLineage *> m_lineage_list;
+  cLineage * m_best_lineage;  // the lineage with the highest average fitness
+  cLineage * m_max_fitness_lineage; // lineage with the single highest fitness
+  cLineage * m_dominant_lineage; // the lineage with the largest number of creatures.
+
+  // references to the genebank and stats used by Avida
+  cGenebank & m_genebank;
+  cStats & m_stats;
+
+  /**
+   * Adds a new lineage to the control.
+   **/
+  cLineage * AddLineage( double start_fitness, int parent_lin_id, int id = -1, 
+			 double lineage_stat1 = 0.0, double lineage_stat2 = 0.0  );
+
+  /**
+   * Determines the best lineage (lineage with the highest fitness),
+   * the dominant lineage, and removes empty lineages.
+   **/
+  void UpdateLineages();
+
+  /**
+   * Does the actual adding of a creature to the lineage, after AddCreature
+   * has done all the preliminary work.
+   **/
+  void AddCreaturePrivate( cGenotype *genotype, cLineage * lineage );
+
+  cLineageControl();
+  cLineageControl( const cLineageControl & );
+  cLineageControl & operator=( const cLineageControl & );
+public:
+  cLineageControl( cGenebank & genebank, cStats & stats );
+  ~cLineageControl();
+
+
+  // manipulators
+  /**
+   * Adds a creature to the correct lineage. The parent genotype is necessary
+   * to determine when a new lineage should be created.
+   *
+   * Attention: the creature is not updated, this has to happen somewhere else!
+   **/
+  cLineage* AddCreature( cGenotype * child_genotype, cGenotype *parent_genotype, cLineage * parent_lineage, int parent_lin_id );
+
+  /**
+   * Removes a creature from the corresponding lineage.
+   **/
+  void RemoveCreature( cOrganism * cpu );
+
+  // accessors
+  /**
+   * Finds the lineage with the given id.
+   * Returns 0 if the lineage does not exist.
+   **/
+  cLineage * FindLineage( int lineage_id ) const;
+
+  /**
+   * @return The lineage with the fastest replicating genotype.
+   **/
+  cLineage * GetMaxFitnessLineage() const { return m_max_fitness_lineage; }
+
+  /**
+   * @return The lineage with the highest average fitness.
+   **/
+  cLineage * GetBestLineage() const { return m_best_lineage; }
+
+  /**
+   * @return The most abundant lineage.
+   **/
+  cLineage * GetDominantLineage() const { return m_dominant_lineage; }
+
+  /**
+   * @return The current number of lineages.
+   **/
+  int GetSize() const { return m_lineage_list.size(); }
+
+  /**
+   * @return A list of the single lineages.
+   **/
+  const std::list<cLineage *> & GetLineageList() const { return m_lineage_list; }
+
+
+  void PrintLineageTotals(const cString & filename, bool verbose=false);
+  void PrintLineageCurCounts(const cString & filename);
+};
+
+#endif
Index: avida/current/source/main/org_message.cc
diff -u /dev/null avida/current/source/main/org_message.cc:1.3
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/org_message.cc	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,27 @@
+#include "org_message.hh"
+#include <string>
+#include <sstream>
+
+void cOrgMessage::SetData(int in_data)
+{
+  std::stringstream ss;
+  ss << in_data;
+  ss >> data;
+}
+
+void cOrgMessage::SetData(double in_data)
+{
+  std::stringstream ss;
+  ss << in_data;
+  ss >> data;
+}
+
+void cOrgMessage::GetData(int & in_data)
+{
+  in_data=atoi(data.c_str());
+}
+
+void cOrgMessage::GetData(double & in_data)
+{
+  in_data=atof(data.c_str());
+}
Index: avida/current/source/main/org_message.hh
diff -u /dev/null avida/current/source/main/org_message.hh:1.3
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/org_message.hh	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,40 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef ORG_MESSAGE_HH
+#define ORG_MESSAGE_HH
+
+#include <string>
+
+class cOrgMessage {
+private:
+  int time;
+  int sender_id;
+  int recipient_id;
+  std::string label;
+  std::string data;
+
+public:
+  cOrgMessage() { time=sender_id=recipient_id=-1; label=data=""; }
+  cOrgMessage(std::string in_label, std::string in_data) 
+  { label = in_label; data = in_data; }
+  
+  void SetTime(int in_time) { time = in_time; }
+  void SetSenderID(int in_id) { sender_id = in_id; }
+  void SetRecipientID(int in_id) { recipient_id = in_id; }
+  void SetLabel(int in_label) { label = in_label; }
+  
+  void SetData(std::string in_data) { data = in_data; }
+  void SetData(int in_data);
+  void SetData(double in_data);
+
+  void GetData(std::string & in_data) { in_data=data; }
+  void GetData(int & in_data);
+  void GetData(double & in_data);
+};
+
+#endif
Index: avida/current/source/main/organism.cc
diff -u /dev/null avida/current/source/main/organism.cc:1.29
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/organism.cc	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,358 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef ORGANISM_HH
+#include "organism.hh"
+#endif
+
+#ifndef CONFIG_HH
+#include "config.hh"
+#endif
+#ifndef CPU_DEFS_HH
+#include "cpu_defs.hh"
+#endif
+#ifndef ENVIRONMENT_HH
+#include "environment.hh"
+#endif
+#ifndef FUNCTIONS_HH
+#include "functions.hh"
+#endif
+#ifndef GENOME_HH
+#include "genome.hh"
+#endif
+#ifndef GENOME_UTIL_HH
+#include "genome_util.hh"
+#endif
+#ifndef HARDWARE_BASE_HH
+#include "hardware_base.hh"
+#endif
+#ifndef INJECT_GENOTYPE_HH
+#include "inject_genotype.hh"
+#endif
+#ifndef INST_SET_HH
+#include "inst_set.hh"
+#endif
+#ifndef INST_UTIL_HH
+#include "inst_util.hh"
+#endif
+#ifndef ORG_MESSAGE_HH
+#include "org_message.hh"
+#endif
+#ifndef STRING_UTIL_HH
+#include "string_util.hh"
+#endif
+#ifndef TARRAY_HH
+#include "tArray.hh"
+#endif
+#ifndef TOOLS_HH
+#include "tools.hh"
+#endif
+
+#include <iomanip>
+
+using namespace std;
+
+///////////////
+//  cOrganism
+///////////////
+
+int cOrganism::instance_count(0);
+
+
+cOrganism::cOrganism(const cGenome & in_genome,
+		     const cPopulationInterface & in_interface,
+		     const cEnvironment & in_environment)
+  : genotype(NULL)
+  , phenotype(in_environment)
+  , initial_genome(in_genome)
+  , mut_info(in_environment.GetMutationLib(), in_genome.GetSize())
+  , pop_interface(in_interface)
+  , max_executed(-1)
+  , lineage_label(-1)
+  , lineage(NULL)
+    , inbox(0)
+    , sent(0)
+{
+  // Initialization of structures...
+  hardware = pop_interface.NewHardware(this);
+  cpu_stats.Setup(hardware->GetNumInst());
+  instance_count++;
+  pop_interface.SetCellID(-1);  // No cell at the moment...
+
+  if (cConfig::GetDeathMethod() > 0) {
+    max_executed = cConfig::GetAgeLimit();
+    if (cConfig::GetAgeDeviation() > 0.0) {
+      max_executed +=
+	(int) (g_random.GetRandNormal() * cConfig::GetAgeDeviation());
+    }
+    if (cConfig::GetDeathMethod() == DEATH_METHOD_MULTIPLE) {
+      max_executed *= initial_genome.GetSize();
+    }
+
+    // max_executed must be positive or an organism will not die!
+    if (max_executed < 1) max_executed = 1;
+  }
+}
+
+
+cOrganism::~cOrganism()
+{
+  pop_interface.RecycleHardware(hardware);
+  instance_count--;
+}
+
+
+double cOrganism::GetTestFitness()
+{
+  return pop_interface.TestFitness();
+}
+  
+void cOrganism::DoInput(const int value, tBuffer<int> & in_buf,
+			tBuffer<int> & out_buf)
+{
+  in_buf.Add(value);
+  phenotype.TestInput(in_buf, out_buf);
+}
+
+void cOrganism::DoOutput(const int value, tBuffer<int> & in_buf,
+			 tBuffer<int> & out_buf)
+{
+  const tArray<double> & resource_count = pop_interface.GetResources();
+  tArray<double> res_change(resource_count.GetSize());
+
+  out_buf.Add(value);
+  phenotype.TestOutput(in_buf, out_buf, resource_count, res_change);
+  pop_interface.UpdateResources(res_change);
+  //if(phenotype.GetToDie() == 1) Die();	//Final Effect Lethal Reaction
+}
+
+void cOrganism::SendMessage(cOrgMessage & mess)
+{
+  if(pop_interface.SendMessage(mess))
+    sent.Add(mess);
+  else
+    {
+      //perhaps some kind of message error buffer?
+    }
+}
+
+bool cOrganism::ReceiveMessage(cOrgMessage & mess)
+{
+  inbox.Add(mess);
+  return true;
+}
+
+bool cOrganism::InjectParasite(const cGenome & injected_code)
+{
+  return pop_interface.InjectParasite(this, injected_code);
+}
+
+bool cOrganism::InjectHost(const cCodeLabel & label, const cGenome & injected_code)
+{
+  return hardware->InjectHost(label, injected_code);
+}
+
+void cOrganism::AddParasite(cInjectGenotype * in_genotype)
+{
+  parasites.push_back(in_genotype);
+}
+
+cInjectGenotype & cOrganism::GetParasite(int x)
+{
+  return *parasites[x];
+}
+
+int cOrganism::GetNumParasites()
+{
+  return parasites.size();
+}
+
+void cOrganism::ClearParasites()
+{
+  parasites.clear();
+}
+
+int cOrganism::OK()
+{
+  if (!hardware->OK()) return false;
+  if (!phenotype.OK()) return false;
+
+  return true;
+}
+
+
+double cOrganism::CalcMeritRatio()
+{
+  const double age = (double) phenotype.GetAge();
+  const double merit = phenotype.GetMerit().GetDouble();
+  return (merit > 0.0) ? (age / merit ) : age;
+}
+
+
+bool cOrganism::GetTestOnDivide() const { return pop_interface.TestOnDivide();}
+bool cOrganism::GetFailImplicit() const { return cConfig::GetFailImplicit(); }
+
+bool cOrganism::GetRevertFatal() const { return cConfig::GetRevertFatal(); }
+bool cOrganism::GetRevertNeg()   const { return cConfig::GetRevertNeg(); }
+bool cOrganism::GetRevertNeut()  const { return cConfig::GetRevertNeut(); }
+bool cOrganism::GetRevertPos()   const { return cConfig::GetRevertPos(); }
+
+bool cOrganism::GetSterilizeFatal() const{return cConfig::GetSterilizeFatal();}
+bool cOrganism::GetSterilizeNeg()  const { return cConfig::GetSterilizeNeg(); }
+bool cOrganism::GetSterilizeNeut() const { return cConfig::GetSterilizeNeut();}
+bool cOrganism::GetSterilizePos()  const { return cConfig::GetSterilizePos(); }
+
+
+void cOrganism::PrintStatus(ostream & fp)
+{
+  hardware->PrintStatus(fp);
+  phenotype.PrintStatus(fp);
+}
+
+
+bool cOrganism::Divide_CheckViable()
+{
+  // Make sure required task (if any) has been performed...
+  const int required_task = cConfig::GetRequiredTask();
+  if (required_task != -1 &&
+      phenotype.GetCurTaskCount()[required_task] == 0) {
+    Fault(FAULT_LOC_DIVIDE, FAULT_TYPE_ERROR,
+	  cStringUtil::Stringf("Lacks required task (%d)",
+			       cConfig::GetRequiredTask()));
+    return false; //  (divide fails)
+  }
+
+  // Make sure the parent is fertile
+  if ( phenotype.IsFertile() == false ) {
+    Fault(FAULT_LOC_DIVIDE, FAULT_TYPE_ERROR, "Infertile organism");
+    return false; //  (divide fails)
+  }
+
+  return true;  // Organism has no problem with divide...
+}
+
+
+// This gets called after a successful divide to deal with the child. 
+// Returns true if parent lives through this process.
+
+bool cOrganism::ActivateDivide()
+{
+  // Activate the child!  (Keep Last: may kill this organism!)
+  return pop_interface.Divide(this, child_genome);
+}
+
+
+void cOrganism::Fault(int fault_loc, int fault_type, cString fault_desc)
+{
+  (void) fault_loc;
+  (void) fault_type;
+  (void) fault_desc;
+
+#ifdef FATAL_ERRORS
+  if (fault_type == FAULT_TYPE_ERROR) {
+    phenotype.IsFertile() = false;
+  }
+#endif
+
+#ifdef FATAL_WARNINGS
+  if (fault_type == FAULT_TYPE_WARNING) {
+    phenotype.IsFertile() = false;
+  }
+#endif
+
+#ifdef BREAKPOINTS
+  phenotype.SetFault(fault_desc);
+#endif
+
+  phenotype.IncErrors();
+}
+
+
+//// Save and Load ////
+void cOrganism::SaveState(ofstream & fp)
+{
+  assert(fp.good());
+
+  fp <<"cOrganism"<<endl;
+
+  //// Save If it is alive ////
+  if( genotype == NULL ){
+    fp <<false<<endl;
+  }else{
+    fp <<true<<endl;
+
+    //// Save Genotype Genome ////
+//    fp << genotype->GetLength() << endl;
+    
+//      cInstUtil::SaveInternalGenome(fp, hardware->GetInstSet(),
+//  				  genotype->GetGenome());
+
+    //// Save Actual Creature Memory & MemFlags ////
+//   fp <<hardware->GetMemory().GetSize()<<endl;
+//   cInstUtil::PrintGenome(hardware->GetInstSet(), hardware->GetMemory(), fp);
+//      fp <<"|"; // marker
+//      for( int i=0; i<hardware->GetMemory().GetSize(); ++i ){
+//        fp << hardware->GetMemory().GetFlags(i);
+//      }
+//      fp <<endl;
+
+    //// Save Hardware (Inst_Pointer, Stacks, and the like)
+    hardware->SaveState(fp);
+
+    //// Save Phenotype  ////
+    phenotype.SaveState(fp);
+
+  } // if there is a genotype here (ie. not dead)
+}
+
+
+void cOrganism::LoadState(ifstream & fp)
+{
+  hardware->Reset();
+
+  assert(fp.good());
+
+  cString foo;
+  fp >>foo;
+  assert( foo == "cOrganism" );
+
+  //// Is there a creature there ////
+  bool alive_flag = 0;
+  fp >>alive_flag;
+  if( alive_flag ){
+
+    //// Load Genotype ////
+    cGenome in_code =
+      cInstUtil::LoadInternalGenome(fp, hardware->GetInstSet());
+//    cGenotype * new_genotype = environment->AddGenotype(in_code);
+//    ChangeGenotype(new_genotype);
+
+    //// Load Actual Creature Memory & MemFlags ////
+//    {	
+//      in_code = cInstUtil::LoadInternalGenome(fp, hardware->GetInstSet());
+//      hardware->GetMemory() = in_code;
+//      CA_FLAG_TYPE flags;
+//      char marker;  fp >>marker;  assert( marker == '|' );
+//      for( int i=0; i<hardware->GetMemory().GetSize(); ++i ){
+//    	  fp.get(flags);
+//  	  hardware->SetMemFlags(i, flags);
+//      }
+//    }
+
+    //// Load Hardware (Inst_Pointer, Stacks, and the like)
+    hardware->LoadState(fp);
+
+    //// Load Phenotype  ////
+    assert(fp.good());
+//      phenotype.Clear(genotype->GetLength());
+    phenotype.LoadState(fp);
+
+    //// Adjust Time Slice ////
+//    environment->AdjustTimeSlice();
+
+  } // end if not a dead creature
+}
Index: avida/current/source/main/organism.hh
diff -u /dev/null avida/current/source/main/organism.hh:1.28
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/organism.hh	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,205 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef ORGANISM_HH
+#define ORGANISM_HH
+
+#include <fstream>
+#include <deque>
+
+#ifndef CPU_MEMORY_HH
+#include "cpu_memory.hh"
+#endif
+#ifndef CPU_STATS_HH
+#include "cpu_stats.hh"
+#endif
+#ifndef GENOME_HH
+#include "genome.hh"
+#endif
+#ifndef LOCAL_MUTATIONS_HH
+#include "local_mutations.hh"
+#endif
+#ifndef MUTATION_RATES_HH
+#include "mutation_rates.hh"
+#endif
+#ifndef PHENOTYPE_HH
+#include "phenotype.hh"
+#endif
+#ifndef POPULATION_INTERFACE_HH
+#include "population_interface.hh"
+#endif
+#ifndef TBUFFER_HH
+#include "tBuffer.hh"
+#endif
+
+/**
+ * The cOrganism class controls the running and manages all the statistics
+ * about a creature.  Effectively the chemistry acting on the genome.
+ **/
+
+class cHardwareBase;
+class cGenotype;
+class cPhenotype; // aggregate
+class cGenome; // aggregate
+class cInjectGenotype;
+class cMutationRates; // aggregate
+class cLocalMutations; // aggregate
+class cPopulationInterface; // aggregate
+class cCPUMemory; // aggregate
+class sCPUStats; // aggregate
+class cLineage;
+template <class T> class tBuffer; // aggregate
+class cOrgMessage;
+class cEnvironment;
+class cOrganism;
+class cCodeLabel;
+
+class cOrganism {
+protected:
+  cHardwareBase * hardware;  // The actual machinary running this organism.
+  cGenotype * genotype;      // Information about organisms with this genome.
+  cPhenotype phenotype;      // Descriptive attributes of organism.
+  const cGenome initial_genome;        // Initial genome; can never be changed!
+  std::deque<cInjectGenotype *> parasites; // List of all parasites associated with
+                                    // this organism.
+  cMutationRates mut_rates;            // Rate of all possible mutations.
+  cLocalMutations mut_info;            // Info about possible mutations;
+  cPopulationInterface pop_interface;  // Interface back to the population.
+
+  cCPUMemory child_genome; // Child genome, while under construction.
+  sCPUStats cpu_stats;     // Info for statistics
+
+  int max_executed;      // Max number of instruction executed before death.
+
+  int lineage_label;     // a lineages tag; inherited unchanged in offspring
+  cLineage * lineage;    // A lineage descriptor... (different from label)
+
+#ifdef DEBUG
+  bool initialized;      // Has this CPU been initialized yet, w/hardware.
+#endif
+  static int instance_count;
+
+  tBuffer<cOrgMessage> inbox;
+  tBuffer<cOrgMessage> sent;
+
+public:
+  void PrintStatus(std::ostream & fp);
+
+  // Divide functions
+  bool Divide_CheckViable();
+  bool ActivateDivide();
+
+  // Other Special Functions
+  void Fault(int fault_loc, int fault_type, cString fault_desc="");
+
+public:
+  cOrganism(const cGenome & in_genome,
+	    const cPopulationInterface & in_interface,
+	    const cEnvironment & in_environment);
+  ~cOrganism();
+
+  cHardwareBase & GetHardware() { return *hardware; }
+  cOrganism * GetNeighbor() { return pop_interface.GetNeighbor(); }
+  int GetNeighborhoodSize() { return pop_interface.GetNumNeighbors(); }
+  void Rotate(int direction) { pop_interface.Rotate(direction); }
+  void DoBreakpoint() { pop_interface.Breakpoint(); }
+  int GetInput() { return pop_interface.GetInput(); }
+  int GetInputAt(int & input_pointer) { return pop_interface.GetInputAt(input_pointer); }
+  void Die() { pop_interface.Die(); }
+  void Kaboom() {pop_interface.Kaboom();}
+  int GetCellID() { return pop_interface.GetCellID(); }
+  int GetDebugInfo() { return pop_interface.Debug(); }
+  
+  // Input & Output Testing
+  void DoInput(const int value, tBuffer<int> & in_buf, tBuffer<int> & out_buf);
+  void DoOutput(const int value, tBuffer<int> & in_buf, tBuffer<int> &out_buf);
+
+  // NEW - message stuff
+  void SendMessage(cOrgMessage & mess);
+  bool ReceiveMessage(cOrgMessage & mess);
+
+  bool InjectParasite(const cGenome & genome);
+  bool InjectHost(const cCodeLabel & in_label, const cGenome & genome);
+  void AddParasite(cInjectGenotype * cur);
+  cInjectGenotype & GetParasite(int x);
+  int GetNumParasites();
+  void ClearParasites();
+		      
+  int OK();
+
+  double GetTestFitness();
+  double CalcMeritRatio();
+
+  cCPUMemory & ChildGenome() { return child_genome; }
+  sCPUStats & CPUStats() { return cpu_stats; }
+
+  bool TestCopyMut() const { return MutationRates().TestCopyMut(); }
+  bool TestDivideMut() const { return MutationRates().TestDivideMut(); }
+  bool TestDivideIns() const { return MutationRates().TestDivideIns(); }
+  bool TestDivideDel() const { return MutationRates().TestDivideDel(); }
+  bool TestParentMut() const { return MutationRates().TestParentMut(); }
+  bool TestCrossover() const { return MutationRates().TestCrossover(); }
+  bool TestAlignedCrossover() const
+    { return MutationRates().TestAlignedCrossover(); }
+  
+  double GetCopyMutProb() const { return MutationRates().GetCopyMutProb(); }
+  void SetCopyMutProb(double _p) { return MutationRates().SetCopyMutProb(_p); }
+  void SetDivMutProb(double _p) { return MutationRates().SetDivMutProb(_p); }
+
+  double GetInsMutProb() const { return MutationRates().GetInsMutProb(); }
+  double GetDelMutProb() const { return MutationRates().GetDelMutProb(); }
+  double GetDivMutProb() const { return MutationRates().GetDivMutProb(); }
+  double GetParentMutProb() const { return MutationRates().GetParentMutProb();}
+
+
+  bool GetTestOnDivide() const;
+  bool GetFailImplicit() const;
+
+  bool GetRevertFatal() const;
+  bool GetRevertNeg() const;
+  bool GetRevertNeut() const;
+  bool GetRevertPos() const;
+
+  bool GetSterilizeFatal() const;
+  bool GetSterilizeNeg() const;
+  bool GetSterilizeNeut() const;
+  bool GetSterilizePos() const;
+
+
+  // Access to private variables
+  int GetMaxExecuted() const { return max_executed; }
+
+  void SetLineageLabel( int in_label ) { lineage_label = in_label; }
+  int GetLineageLabel() const { return lineage_label; }
+  
+  void SetLineage( cLineage * in_lineage ) { lineage = in_lineage; }
+  cLineage * GetLineage() const { return lineage; }
+
+  void SetGenotype(cGenotype * in_genotype) { genotype = in_genotype; }
+  cGenotype * GetGenotype() const { return genotype; }
+
+  const cMutationRates & MutationRates() const { return mut_rates; }
+  cMutationRates & MutationRates() { return mut_rates; }
+  const cLocalMutations & GetLocalMutations() const { return mut_info; }
+  cLocalMutations & GetLocalMutations() { return mut_info; }
+  const cPopulationInterface & PopInterface() const { return pop_interface; }
+  cPopulationInterface & PopInterface() { return pop_interface; }
+  
+  const cGenome & GetGenome() const { return initial_genome; }
+  
+  int GetCurGestation() const;
+  const cPhenotype & GetPhenotype() const { return phenotype; }
+  cPhenotype & GetPhenotype() { return phenotype; }
+
+  void SaveState(std::ofstream & fp);
+  void LoadState(std::ifstream & fp);
+
+  // --------  DEBUG ---------
+  static int GetInstanceCount() { return instance_count; }
+};
+
+#endif
Index: avida/current/source/main/phenotype.cc
diff -u /dev/null avida/current/source/main/phenotype.cc:1.38
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/phenotype.cc	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,614 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef PHENOTYPE_HH
+#include "phenotype.hh"
+#endif
+
+#ifndef CONFIG_HH
+#include "config.hh"
+#endif
+#ifndef ENVIRONMENT_HH
+#include "environment.hh"
+#endif
+#ifndef REACTION_RESULT_HH
+#include "reaction_result.hh"
+#endif
+#ifndef TOOLS_HH
+#include "tools.hh"
+#endif
+
+#include <fstream>
+
+using namespace std;
+
+
+cPhenotype::cPhenotype(const cEnvironment & _environment)
+  : environment(_environment)
+  , initialized(false)
+  , cur_task_count(environment.GetTaskLib().GetSize())
+  , cur_reaction_count(environment.GetReactionLib().GetSize())
+  , cur_inst_count(environment.GetInstSet().GetSize())
+  , last_task_count(environment.GetTaskLib().GetSize())
+  , last_reaction_count(environment.GetReactionLib().GetSize())
+  , last_inst_count(environment.GetInstSet().GetSize())
+  , sensed_resources(environment.GetResourceLib().GetSize())
+{
+}
+
+cPhenotype::~cPhenotype()
+{
+}
+
+bool cPhenotype::OK()
+{
+  assert(genome_length >= 0);
+  assert(copied_size >= 0);
+  assert(executed_size >= 0);
+  assert(gestation_time >= 0);
+  assert(gestation_start >= 0);
+  assert(fitness >= 0.0);
+  assert(div_type >= 0.0);
+  assert(cur_bonus >= 0.0);
+  assert(cur_num_errors >= 0);
+  assert(last_merit_base >= 0.0);
+  assert(last_bonus >= 0.0);
+  assert(last_num_errors >= 0);
+  assert(last_fitness >= 0.0);
+  assert(num_divides >= 0);
+  assert(generation >= 0);
+  assert(time_used >= 0);
+  assert(age >= 0);
+  assert(child_copied_size >= 0);
+  assert(to_die == false);
+  return true;
+}
+
+
+/**
+ * This function is run whenever a new organism is being constructed inside
+ * of its parent.
+ *
+ * Assumptions:
+ *     - parent_phenotype has had DivideReset run on it already!
+ *     - this is the first method run on an otherwise freshly built phenotype.
+ **/
+
+void cPhenotype::SetupOffspring(const cPhenotype & parent_phenotype,
+				int _length)
+{
+  // Copy divide values from parent, which should already be setup.
+  merit           = parent_phenotype.merit;
+  genome_length   = _length;
+  copied_size     = parent_phenotype.child_copied_size;
+  executed_size   = parent_phenotype.executed_size;
+  gestation_time  = parent_phenotype.gestation_time;
+  gestation_start = 0;
+  fitness         = parent_phenotype.fitness;
+  div_type        = parent_phenotype.div_type;
+
+  assert(genome_length > 0);
+  assert(copied_size > 0);
+  assert(executed_size > 0);
+  assert(gestation_time > 0);
+  assert(div_type > 0);
+
+  // Initialize current values, as neeeded.
+  cur_bonus       = 1;
+  cur_num_errors  = 0;
+  cur_task_count.SetAll(0);
+  cur_reaction_count.SetAll(0);
+  cur_inst_count.SetAll(0);
+  for (int j = 0; j < sensed_resources.GetSize(); j++)
+	      sensed_resources[j] =  parent_phenotype.sensed_resources[j];
+ 
+
+  // Copy last values from parent
+  last_merit_base     = parent_phenotype.last_merit_base;
+  last_bonus          = parent_phenotype.last_bonus;
+  last_num_errors     = parent_phenotype.last_num_errors;
+  last_task_count     = parent_phenotype.last_task_count;
+  last_reaction_count = parent_phenotype.last_reaction_count;
+  last_inst_count     = parent_phenotype.last_inst_count;
+  last_fitness        = last_merit_base * last_bonus / gestation_time;
+  
+  // Setup other miscellaneous values...
+  num_divides     = 0;
+  generation      = parent_phenotype.generation;
+  if (cConfig::GetGenerationIncMethod() != GENERATION_INC_BOTH) generation++;
+  time_used       = 0;
+  age             = 0;
+  fault_desc      = "";
+  neutral_metric  = parent_phenotype.neutral_metric + g_random.GetRandNormal();
+
+  // Setup flags...
+  is_injected   = false;
+  is_parasite   = false;
+  is_modifier   = false;
+  is_modified   = false;
+  is_fertile    = parent_phenotype.last_child_fertile;
+  is_mutated    = false;
+  is_multi_thread = parent_phenotype.is_multi_thread;
+  parent_true   = parent_phenotype.copy_true;
+  parent_sex    = parent_phenotype.divide_sex;
+  parent_cross_num    = parent_phenotype.cross_num;
+  to_die = false; 
+
+  // Setup child info...
+  copy_true          = false;
+  divide_sex         = false;
+  cross_num          = 0;
+  last_child_fertile = is_fertile;
+  child_fertile      = true;
+  child_copied_size  = 0;
+
+  initialized = true;
+}
+
+
+/**
+ * This function is run whenever a new organism is being constructed via
+ * some form of injection into the population, or in a test environment.
+ *
+ * Assumptions:
+ *     - Updates to these values (i.e. resetting of merit) will occur afterward
+ *     - This is the first method run on an otherwise freshly built phenotype.
+ **/
+
+void cPhenotype::SetupInject(int _length)
+{
+  // Setup reasonable initial values injected organism...
+  merit           = _length;
+  genome_length   = _length;
+  copied_size     = _length;
+  executed_size   = _length;
+  gestation_time  = 0;
+  gestation_start = 0;
+  fitness         = 0;
+  div_type	  = 1; 
+ 
+  // Initialize current values, as neeeded.
+  cur_bonus       = 1;
+  cur_num_errors  = 0;
+  cur_task_count.SetAll(0);
+  cur_reaction_count.SetAll(0);
+  cur_inst_count.SetAll(0);
+  sensed_resources.SetAll(0);
+
+  // Copy last values from parent
+  last_merit_base = _length;
+  last_bonus      = 1;
+  last_num_errors = 0;
+  last_task_count.SetAll(0);
+  last_reaction_count.SetAll(0);
+  last_inst_count.SetAll(0);
+    
+  // Setup other miscellaneous values...
+  num_divides     = 0;
+  generation      = 0;
+  time_used       = 0;
+  age             = 0;
+  fault_desc      = "";
+  neutral_metric  = 0;
+
+  // Setup flags...
+  is_injected   = true;
+  is_parasite   = false;
+  is_modifier   = false;
+  is_modified   = false;
+  is_fertile    = true;
+  is_mutated    = false;
+  is_multi_thread = false;
+  parent_true   = true;
+  parent_sex    = false;
+  parent_cross_num    = 0;
+  to_die = false;
+
+  // Setup child info...
+  copy_true         = false;
+  divide_sex        = false;
+  cross_num        = 0;
+  child_fertile     = true;
+  last_child_fertile = true;
+  child_copied_size = 0;
+
+  initialized = true;
+}
+
+
+/**
+ * This function is run whenever an organism executes a successful divide.
+ **/
+
+void cPhenotype::DivideReset(int _length)
+{
+  assert(time_used > 0);
+  assert(initialized == true);
+
+  // Update these values as needed...
+  int cur_merit_base = CalcSizeMerit(genome_length,copied_size,executed_size);
+  merit = cur_merit_base * cur_bonus;
+  assert(merit.GetDouble() >= 0.0);
+
+  genome_length   = _length;
+  (void) copied_size;          // Unchanged
+  (void) executed_size;        // Unchanged
+  gestation_time  = time_used - gestation_start;
+  gestation_start = time_used;
+  fitness         = merit.GetDouble() / gestation_time;
+
+  // Lock in cur values as last values.
+  last_merit_base     = cur_merit_base;
+  last_bonus          = cur_bonus;
+  last_num_errors     = cur_num_errors;
+  last_task_count     = cur_task_count;
+  last_reaction_count = cur_reaction_count;
+  last_inst_count     = cur_inst_count;
+  
+  // Reset cur values.
+  cur_bonus       = 1;
+  cur_num_errors  = 0;
+  cur_task_count.SetAll(0);
+  cur_reaction_count.SetAll(0);
+  cur_inst_count.SetAll(0);
+
+  // Setup other miscellaneous values...
+  num_divides++;
+  (void) generation;
+  (void) time_used;
+  age             = 0;
+  fault_desc      = "";
+  (void) neutral_metric;
+
+  // Leave flags alone...
+  (void) is_injected;
+  (void) is_parasite;
+  (void) is_modifier;
+  (void) is_modified;
+  (void) is_fertile;
+  (void) is_mutated;
+  (void) is_multi_thread;
+  (void) parent_true;
+  (void) parent_sex;
+  (void) parent_cross_num;
+
+  // Reset child info...
+  (void) copy_true;
+  (void) divide_sex;
+  (void) cross_num;
+  last_child_fertile = child_fertile;
+  child_fertile     = true;
+  (void) child_copied_size;;
+
+  // A few final changes if the parent was supposed to be be considered
+  // a second child on the divide.
+  if (cConfig::GetDivideMethod() == DIVIDE_METHOD_SPLIT) {
+    gestation_start = 0;
+    time_used = 0;
+    neutral_metric += g_random.GetRandNormal();
+  }
+
+  if (cConfig::GetGenerationIncMethod() == GENERATION_INC_BOTH) generation++;
+}
+
+
+/**
+ * This function runs whenever a *test* CPU divides. It processes much of
+ * the information for that CPU in order to actively reflect its executed
+ * and copied size in its merit.
+ **/
+
+void cPhenotype::TestDivideReset(int _length)
+{
+  assert(time_used > 0);
+  assert(initialized == true);
+
+  // Update these values as needed...
+  int cur_merit_base = CalcSizeMerit(genome_length,copied_size,executed_size);
+  merit           = cur_merit_base * cur_bonus;
+  genome_length   = _length;
+  (void) copied_size;                            // Unchanged
+  (void) executed_size;                          // Unchanged
+  gestation_time  = time_used - gestation_start;
+  gestation_start = time_used;
+  fitness         = merit.GetDouble() / gestation_time;
+  (void) div_type; 				// Unchanged
+
+  // Lock in cur values as last values.
+  last_merit_base     = cur_merit_base;
+  last_bonus          = cur_bonus;
+  last_num_errors     = cur_num_errors;
+  last_task_count     = cur_task_count;
+  last_reaction_count = cur_reaction_count;
+  last_inst_count     = cur_inst_count;
+    
+  // Reset cur values.
+  cur_bonus       = 1;
+  cur_num_errors  = 0;
+  cur_task_count.SetAll(0);
+  cur_reaction_count.SetAll(0);
+  cur_inst_count.SetAll(0);
+  sensed_resources.SetAll(-1.0);
+
+  // Setup other miscellaneous values...
+  num_divides++;
+  generation++;
+  (void) time_used;
+  (void) age;
+  (void) fault_desc;
+  (void) neutral_metric;
+
+  // Leave flags alone...
+  (void) is_injected;
+  (void) is_parasite;
+  (void) is_modifier;
+  (void) is_modified;
+  (void) is_fertile;
+  (void) is_mutated;
+  (void) is_multi_thread;
+  (void) parent_true;
+  (void) parent_sex;
+  (void) parent_cross_num;
+
+  // Reset child info...
+  (void) copy_true;
+  (void) divide_sex;
+  (void) cross_num;
+  (void) child_fertile;
+  (void) last_child_fertile;
+  (void) child_copied_size;
+}
+
+
+
+bool cPhenotype::TestInput(tBuffer<int> & inputs, tBuffer<int> & outputs)
+{
+  assert(initialized == true);
+  // For the moment, lets not worry about inputs...
+  return false; // Nothing happened...
+}
+
+bool cPhenotype::TestOutput(tBuffer<int> & inputs, tBuffer<int> & outputs,
+		    const tArray<double> & res_in, tArray<double> & res_change)
+{
+  assert(initialized == true);
+
+  const int num_resources = environment.GetResourceLib().GetSize();
+  const int num_tasks = environment.GetTaskLib().GetSize();
+  const int num_reactions = environment.GetReactionLib().GetSize();
+
+  cReactionResult result(num_resources, num_tasks, num_reactions);
+			 
+  // Run everything through the environment.
+  bool found = environment.TestOutput(result, inputs, outputs, cur_task_count,
+				      cur_reaction_count, res_in);
+
+  // If nothing was found, stop here.
+  if (found == false) {
+    res_change.SetAll(0.0);
+    return false;  // Nothing happened.
+  }
+
+  // Update the phenotype with the results...
+  // Start with updating task and reaction counters
+  for (int i = 0; i < num_tasks; i++) {
+    if (result.TaskDone(i) == true) cur_task_count[i]++;
+  }
+  for (int i = 0; i < num_reactions; i++) {
+    if (result.ReactionTriggered(i) == true) cur_reaction_count[i]++;
+  }
+
+  // Update the merit bonus
+  cur_bonus *= result.GetMultBonus();
+  cur_bonus += result.GetAddBonus();
+
+  // Bonus should never go negative...
+  if (cur_bonus < 0.0) cur_bonus = 0.0;
+
+  // Denote consumed resources...
+  for (int i = 0; i < res_in.GetSize(); i++) {
+    res_change[i] = result.GetProduced(i) - result.GetConsumed(i);
+  }
+
+  //Put in detected resources
+  for (int j = 0; j < res_in.GetSize(); j++)
+	  if(result.GetDetected(j) != -1.0)
+	      sensed_resources[j] = result.GetDetected(j);
+
+  //Kill any cells that did lethal reactions
+  //to_die = result.GetLethal();
+
+  return true;
+}
+
+
+///// For Loading and Saving State: /////
+
+
+bool cPhenotype::SaveState(ofstream & fp)
+{
+  assert(fp.good());
+  fp << "cPhenotype" << endl;
+
+  fp << merit.GetDouble()   << " ";
+  fp << genome_length       << " ";
+  fp << copied_size         << " ";
+  fp << executed_size       << " ";
+  fp << gestation_time      << " ";
+  fp << gestation_start     << " ";
+  fp << fitness             << " ";
+  fp << div_type            << " ";
+
+  fp << cur_bonus           << " ";
+  fp << cur_num_errors      << " ";
+  for (int i = 0; i < cur_task_count.GetSize(); i++) {
+    fp << cur_task_count[i] << " ";
+  }
+  for (int i = 0; i < cur_reaction_count.GetSize(); i++) {
+    fp << cur_reaction_count[i] << " ";
+  }
+  for (int i = 0; i < cur_inst_count.GetSize(); i++) {
+    fp << cur_inst_count[i] << " ";
+  }
+
+  fp << last_merit_base     << " ";
+  fp << last_bonus          << " ";
+  fp << last_num_errors     << " ";
+  for (int i = 0; i < last_task_count.GetSize(); i++) {
+    fp << last_task_count[i] << " ";
+  }
+  for (int i = 0; i < last_reaction_count.GetSize(); i++) {
+    fp << last_reaction_count[i] << " ";
+  }
+  for (int i = 0; i < last_inst_count.GetSize(); i++) {
+    fp << last_inst_count[i] << " ";
+  }
+
+  fp << num_divides         << " ";
+  fp << generation          << " ";
+  fp << time_used           << " ";
+  fp << age                 << " ";
+  fp << neutral_metric      << " ";
+
+  fp << is_injected         << " ";
+  fp << is_parasite         << " ";
+  fp << is_modifier         << " ";
+  fp << is_modified         << " ";
+  fp << is_fertile          << " ";
+  fp << is_mutated          << " ";
+  fp << parent_true         << " ";
+  fp << parent_sex          << " ";
+  fp << parent_cross_num    << " ";
+
+  fp << copy_true           << " ";
+  fp << divide_sex          << " ";
+  fp << cross_num          << " ";
+  fp << child_fertile       << " ";
+  fp << last_child_fertile  << " ";
+
+  fp << endl;
+  return true;
+}
+
+
+bool cPhenotype::LoadState(ifstream & fp)
+{
+  double tmp_merit;
+  assert(fp.good());
+  if( !fp.good() ) return false;
+
+  fp >> tmp_merit;  merit = tmp_merit;
+  fp >> genome_length;
+  fp >> copied_size;
+  fp >> executed_size;
+  fp >> gestation_time;
+  fp >> gestation_start;
+  fp >> fitness;
+  fp >> div_type;
+  
+  fp >> cur_bonus;
+  fp >> cur_num_errors;
+  for (int i = 0; i < cur_task_count.GetSize(); i++) {
+    fp >> cur_task_count[i];
+  }
+  for (int i = 0; i < cur_reaction_count.GetSize(); i++) {
+    fp >> cur_reaction_count[i];
+  }
+  for (int i = 0; i < cur_inst_count.GetSize(); i++) {
+    fp >> cur_inst_count[i];
+  }
+
+  fp >> last_merit_base;
+  fp >> last_bonus;
+  fp >> last_num_errors;
+  for (int i = 0; i < last_task_count.GetSize(); i++) {
+    fp >> last_task_count[i];
+  }
+  for (int i = 0; i < last_reaction_count.GetSize(); i++) {
+    fp >> last_reaction_count[i];
+  }
+  for (int i = 0; i < last_inst_count.GetSize(); i++) {
+    fp >> last_inst_count[i];
+  }
+
+  fp >> num_divides;
+  fp >> generation;
+  fp >> time_used;
+  fp >> age;
+  fp >> neutral_metric;
+
+  fp >> is_injected;
+  fp >> is_parasite;
+  fp >> is_modifier;
+  fp >> is_modified;
+  fp >> is_fertile;
+  fp >> is_mutated;
+  fp >> parent_true;
+  fp >> parent_sex;
+  fp >> parent_cross_num;
+
+  fp >> copy_true;
+  fp >> divide_sex;
+  fp >> cross_num;
+  fp >> child_fertile;
+  fp >> last_child_fertile;
+
+  return true;
+}
+
+void cPhenotype::PrintStatus(ostream & fp)
+{
+  fp << "  MeritBase:"
+     << CalcSizeMerit(genome_length,copied_size,executed_size)
+     << " Bonus: " << cur_bonus
+     << " Errors:" << cur_num_errors
+     << " Tasks:";
+
+  for (int i = 0; i < cur_task_count.GetSize(); i++) {
+    fp << " " << cur_task_count[i];
+  }
+
+  fp << endl;
+}
+
+int cPhenotype::CalcSizeMerit(int full_size, int copied_size, int exe_size)
+{
+  assert(full_size > 0);
+  assert(exe_size > 0);
+  assert(copied_size > 0);
+
+  int out_size = cConfig::GetBaseSizeMerit();
+
+  switch (cConfig::GetSizeMeritMethod()) {
+  case SIZE_MERIT_COPIED:
+    out_size = copied_size;
+    break;
+  case SIZE_MERIT_EXECUTED:
+    out_size = exe_size;
+    break;
+  case SIZE_MERIT_FULL:
+    out_size = full_size;
+    break;
+  case SIZE_MERIT_LEAST:
+    out_size = full_size;
+    if (out_size > copied_size) out_size = copied_size;
+    if (out_size > exe_size)    out_size = exe_size;
+    break;
+  case SIZE_MERIT_SQRT_LEAST:
+    out_size = full_size;
+    if (out_size > copied_size) out_size = copied_size;
+    if (out_size > exe_size)    out_size = exe_size;
+    out_size = (int) sqrt((double) out_size);
+    break;
+  case SIZE_MERIT_OFF:
+  default:
+    out_size = 100;
+    break;
+  }
+
+  return out_size;
+}
Index: avida/current/source/main/phenotype.hh
diff -u /dev/null avida/current/source/main/phenotype.hh:1.39
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/phenotype.hh	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,267 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef PHENOTYPE_HH
+#define PHENOTYPE_HH
+
+#include <fstream>
+
+#ifndef MERIT_HH
+#include "merit.hh"
+#endif
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+#ifndef TARRAY_HH
+#include "tArray.hh"
+#endif
+
+/*************************************************************************
+ *
+ * The cPhenotype object contains a general description of all the
+ * phenotypic characteristics an organism has displayed.  That is, it
+ * monitors all of the organisms behaviors.
+ *
+ * After a phenotype is created in organism and organism within a population,
+ * it must have either SetupOffspring() or SetupInject() run on it to prime
+ * it for that population.  After that, it must have DivideReset() run on it
+ * whenever it produces an offspring.
+ *
+ * If the phenotype is part of an organism in a test cpu, no initial priming
+ * is required, and SetupTestDivide() needs to be run once it finally has
+ * produced an offspring in order to properly lock in any final values.
+ *
+ * In addition to a reference to the relevent environment, the data
+ * contained within this class comes in six flavors:
+ *   1. Calculations made at the previous divide.
+ *   2. Stats which are accumulated over each gestation cycle.
+ *   3. The final result of accumulations over the previous gestation cycle.
+ *   4. Accumulations over the entire life of the genome.
+ *   5. A collection of flags to indicate the presence of characteristics.
+ *   6. Information about the child being constructed.
+ *
+ *************************************************************************/
+
+class cEnvironment;
+class cMerit; // aggregate
+template <class T> class tArray; // aggregate
+class cString; // aggregate
+template <class T> class tBuffer;
+
+class cPhenotype {
+private:
+  const cEnvironment & environment;
+  bool initialized;
+
+  // 1. These are values calculated at the last divide (of self or offspring)
+  cMerit merit;          // Relative speed of CPU
+  int genome_length;     // Number of instructions in genome.
+  int copied_size;       // Instructions copied into genome.
+  int executed_size;     // Instructions executed from genome.
+  int gestation_time;    // CPU cycles to produce offspring (or be produced)
+  int gestation_start;   // Total instructions executed at last divide.
+  double fitness;        // Relative efective replication rate...
+  double div_type;	     // Type of the divide command used
+
+  // 2. These are "in progress" variables, updated as the organism operates
+  double cur_bonus;               // Current Bonus
+  bool to_die;					  // Has executed a fatal reaction
+  int cur_num_errors;             // Total instructions executed illeagally.
+  tArray<int> cur_task_count;     // Total times each task was performed
+  tArray<int> cur_reaction_count; // Total times each reaction was triggered.
+  tArray<int> cur_inst_count;	  // Intruction exection counter
+  tArray<double> sensed_resources; // Resources of which the organism is explictly aware
+
+  // 3. These mark the status of "in progess" variables at the last divide.
+  double last_merit_base;         // Either constant or based on genome length.
+  double last_bonus;
+  int last_num_errors;
+  tArray<int> last_task_count;
+  tArray<int> last_reaction_count;
+  tArray<int> last_inst_count;	  // Intruction exection counter
+  double last_fitness;            // Used to determine sterilization.
+
+  // 4. Records from this organisms life...
+  int num_divides;       // Total successful divides organism has produced.
+  int generation;        // Number of birth events to original ancestor.
+  int time_used;         // Total CPU cycles consumed.
+  int age;               // Number of updates organism has survived for.
+  cString fault_desc;    // A description of the most recent error.
+  double neutral_metric; // Undergoes drift (gausian 0,1) per generation
+
+  // 5. Status Flags...  (updated at each divide)
+  bool is_injected;      // Was this organism injected into the population?
+  bool is_parasite;      // Has this organism ever executed outside code?
+  bool is_modifier;      // Has this organism modified another?
+  bool is_modified;      // Has this organism been modified by another?
+  bool is_fertile;       // Do we allow this organisms to produce offspring?
+  bool is_mutated;       // Has this organism been subject to any mutations?
+  bool is_multi_thread;  // Does this organism have 2 or more threads?
+  bool parent_true;      // Is this genome an exact copy of its parent's?
+  bool parent_sex;       // Did the parent divide with sex?
+  int  parent_cross_num; // How many corssovers did the parent do? 
+
+  // 6. Child information...
+  bool copy_true;        // Can this genome produce an exact copy of itself?
+  bool divide_sex;       // Was this child created with a sexual divide?
+  int  cross_num  ;      // How many crossovers should this child do?
+  bool child_fertile;    // Will this organism's next child be fertile?
+  bool last_child_fertile;  // Was the child being born to be fertile?
+  int child_copied_size; // Instruction copied into child.
+
+public:
+  cPhenotype(const cEnvironment & environment);
+  ~cPhenotype();
+
+  bool OK();
+
+  // Run when being setup *as* and offspring.
+  void SetupOffspring(const cPhenotype & parent_phenotype, int _length);
+
+  // Run when being setup as an injected organism.
+  void SetupInject(int _length);
+
+  // Run when this organism successfully executes a divide.
+  void DivideReset(int _length);
+  
+  // Same as DivideReset(), but only run in test CPUs.
+  void TestDivideReset(int _length);
+  
+  // Input and Output Reaction Tests
+  bool TestInput(tBuffer<int> & inputs, tBuffer<int> & outputs);
+  bool TestOutput(tBuffer<int> & inputs, tBuffer<int> & outputs,
+		  const tArray<double> & res_in, tArray<double> & res_change);
+
+  // State saving and loading, and printing...
+  bool SaveState(std::ofstream & fp);
+  bool LoadState(std::ifstream & fp);
+  void PrintStatus(std::ostream & fp);
+
+  // Some useful methods...
+  static int CalcSizeMerit(int full_size, int copied_size, int exe_size);
+  double CalcFitnessRatio() {
+    const int merit_base =
+      CalcSizeMerit(genome_length,copied_size,executed_size);
+    const double cur_fitness = merit_base * cur_bonus / time_used;
+    return cur_fitness / last_fitness;
+  }
+
+  /////////////////////  Accessors -- Retrieving  ////////////////////
+  const cEnvironment & GetEnvironment() const { return environment; };
+
+  const cMerit & GetMerit() const
+    { assert(initialized == true); return merit; }
+  int GetGenomeLength() const
+    { assert(initialized == true); return genome_length; }
+  int GetCopiedSize() const
+    { assert(initialized == true); return copied_size; }
+  int GetExecutedSize() const
+    { assert(initialized == true); return executed_size; }
+  int GetGestationTime() const
+    { assert(initialized == true); return gestation_time; }
+  int GetGestationStart() const
+    { assert(initialized == true); return gestation_start; }
+  double GetFitness() const
+    { assert(initialized == true); return fitness; }
+  double GetDivType() const
+    { assert(initialized == true); return div_type; }
+
+  double GetCurBonus() const
+    { assert(initialized == true); return cur_bonus; }
+  bool GetToDie() const
+    { assert(initialized == true); return to_die; }
+  int GetCurNumErrors()const
+    { assert(initialized == true); return cur_num_errors; }
+  const tArray<int> & GetCurTaskCount() const
+    { assert(initialized == true); return cur_task_count; }
+  const tArray<int> & GetCurReactionCount() const
+    { assert(initialized == true); return cur_reaction_count;}
+  const tArray<int> & GetCurInstCount() const
+    { assert(initialized == true); return cur_inst_count; }
+  
+  double GetSensedResource(int _in)
+  { assert(initialized == true); return sensed_resources[_in]; }
+
+  double GetLastMeritBase() const
+    { assert(initialized == true); return last_merit_base; }
+  double GetLastBonus() const
+    { assert(initialized == true); return last_bonus; }
+  int GetLastNumErrors() const
+    { assert(initialized == true); return last_num_errors; }
+  const tArray<int> & GetLastTaskCount() const
+    { assert(initialized == true); return last_task_count; }
+  const tArray<int> & GetLastReactionCount() const
+    { assert(initialized == true); return last_reaction_count; }
+  const tArray<int> & GetLastInstCount() const
+    { assert(initialized == true); return last_inst_count; }
+  double GetLastFitness() const
+    { assert(initialized == true); return last_fitness; }
+
+  int GetNumDivides() const { assert(initialized == true); return num_divides;}
+  int GetGeneration() const { assert(initialized == true); return generation; }
+  int GetTimeUsed()   const { assert(initialized == true); return time_used; }
+  int GetAge()        const { assert(initialized == true); return age; }
+  const cString & GetFault() const
+    { assert(initialized == true); return fault_desc; }
+  double GetNeutralMetric() const
+    { assert(initialized == true); return neutral_metric; }
+
+  bool IsInjected() const { assert(initialized == true); return is_injected; }
+  bool IsParasite() const { assert(initialized == true); return is_parasite; }
+  bool IsModifier() const { assert(initialized == true); return is_modifier; }
+  bool IsModified() const { assert(initialized == true); return is_modified; }
+  bool IsFertile() const  { assert(initialized == true); return is_fertile; }
+  bool IsMutated() const  { assert(initialized == true); return is_mutated; }
+  bool IsMultiThread() const { assert(initialized == true); return is_multi_thread; }
+  bool ParentTrue() const { assert(initialized == true); return parent_true; }
+  bool ParentSex() const  { assert(initialized == true); return parent_sex; }
+  int  ParentCrossNum() const  { assert(initialized == true); return parent_cross_num; }
+
+  bool CopyTrue() const   { assert(initialized == true); return copy_true; }
+  bool DivideSex() const  { assert(initialized == true); return divide_sex; }
+  int  CrossNum() const  { assert(initialized == true); return cross_num; }
+  bool  ChildFertile() const
+    { assert(initialized == true); return child_fertile;}
+  int GetChildCopiedSize() const
+    { assert(initialized == true); return child_copied_size; }
+
+
+  ////////////////////  Accessors -- Modifying  ///////////////////
+  void SetMerit(const cMerit & in_merit) { merit = in_merit; }
+  void SetGestationTime(int in_time) { gestation_time = in_time; }
+  void SetFault(const cString & in_fault) { fault_desc = in_fault; }
+  void SetNeutralMetric(double _in){ neutral_metric = _in; }
+  void SetLinesExecuted(int _exe_size) { executed_size = _exe_size; }
+  void SetLinesCopied(int _copied_size) { child_copied_size = _copied_size; }
+  void SetDivType(double _div_type) { div_type = _div_type; }  
+  void SetDivideSex(bool _divide_sex) { divide_sex = _divide_sex; }  
+  void SetCrossNum(int _cross_num) { cross_num = _cross_num; }
+
+  void IncCurInstCount(int _inst_num)  { assert(initialized == true); cur_inst_count[_inst_num]++; } 
+  void DecCurInstCount(int _inst_num)  { assert(initialized == true); cur_inst_count[_inst_num]--; } 
+
+  void IncAge()      { assert(initialized == true); age++; }
+  void IncTimeUsed() { assert(initialized == true); time_used++; }
+  void IncErrors()   { assert(initialized == true); cur_num_errors++; }
+  
+  bool & IsInjected() { assert(initialized == true); return is_injected; }
+  bool & IsParasite() { assert(initialized == true); return is_parasite; }
+  bool & IsModifier() { assert(initialized == true); return is_modifier; }
+  bool & IsModified() { assert(initialized == true); return is_modified; }
+  bool & IsFertile()  { assert(initialized == true); return is_fertile; }
+  bool & IsMutated()  { assert(initialized == true); return is_mutated; }
+  bool & ParentTrue() { assert(initialized == true); return parent_true; }
+  bool & ParentSex()  { assert(initialized == true); return parent_sex; }
+  int & ParentCrossNum()  { assert(initialized == true); return parent_cross_num; }
+  bool & CopyTrue()   { assert(initialized == true); return copy_true; }
+  bool & DivideSex()  { assert(initialized == true); return divide_sex; }
+  int & CrossNum()     { assert(initialized == true); return cross_num; }
+  bool & ChildFertile() { assert(initialized == true); return child_fertile; }
+  bool & IsMultiThread() { assert(initialized == true); return is_multi_thread; }
+};
+
+#endif
Index: avida/current/source/main/population.cc
diff -u /dev/null avida/current/source/main/population.cc:1.122
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/population.cc	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,1645 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef POPULATION_HH
+#include "population.hh"
+#endif
+
+
+#ifndef CONFIG_HH
+#include "config.hh"
+#endif
+#ifndef CONST_SCHEDULE_HH
+#include "const_schedule.hh"
+#endif
+#ifndef ENVIRONMENT_HH
+#include "environment.hh"
+#endif
+#ifndef FUNCTIONS_HH
+#include "functions.hh"
+#endif
+#ifndef GENEBANK_HH
+#include "genebank.hh"
+#endif
+#ifndef GENOME_UTIL_HH
+#include "genome_util.hh"
+#endif
+#ifndef GENOTYPE_HH
+#include "genotype.hh"
+#endif
+#ifndef HARDWARE_BASE_HH
+#include "hardware_base.hh"
+#endif
+#ifndef HARDWARE_FACTORY_HH
+#include "hardware_factory.hh"
+#endif
+#ifndef HARDWARE_4STACK_HH
+#include "hardware_4stack.hh"
+#endif
+#ifndef HARDWARE_UTIL_HH
+#include "hardware_util.hh"
+#endif
+#ifndef INIT_FILE_HH
+#include "init_file.hh"
+#endif
+#ifndef INJECT_GENEBANK_HH
+#include "inject_genebank.hh"
+#endif
+#ifndef INJECT_GENOTYPE_HH
+#include "inject_genotype.hh"
+#endif
+#ifndef INST_UTIL_HH
+#include "inst_util.hh"
+#endif
+#ifndef INTEGRATED_SCHEDULE_HH
+#include "integrated_schedule.hh"
+#endif
+#ifndef LINEAGE_HH
+#include "lineage.hh"
+#endif
+#ifndef LINEAGE_CONTROL_HH
+#include "lineage_control.hh"
+#endif
+#ifndef ORGANISM_HH
+#include "organism.hh"
+#endif
+#ifndef PHENOTYPE_HH
+#include "phenotype.hh"
+#endif
+#ifndef POPULATION_CELL_HH
+#include "population_cell.hh"
+#endif
+#ifndef PROB_SCHEDULE_HH
+#include "prob_schedule.hh"
+#endif
+#ifndef RESOURCE_HH
+#include "resource.hh"
+#endif
+#ifndef SPECIES_HH
+#include "species.hh"
+#endif
+#ifndef STATS_HH
+#include "stats.hh"
+#endif
+#ifndef TASK_ENTRY_HH
+#include "task_entry.hh"
+#endif
+
+#include <fstream>
+#include <vector>
+#include <algorithm>
+#include <set>
+
+using namespace std;
+
+
+cPopulation::cPopulation(const cPopulationInterface & in_interface,
+			 cEnvironment & in_environment)
+  : schedule(NULL)
+  , resource_count(in_environment.GetResourceLib().GetSize())
+  , environment(in_environment)
+  , default_interface(in_interface)
+  , num_organisms(0)
+  , sync_events(false)
+{
+  cout << "<cPopulation>" << endl;
+
+  // Setup the genebank.
+  genebank = new cGenebank(stats);
+  inject_genebank = new cInjectGenebank(stats);
+
+  // are we logging lineages?
+  if (cConfig::GetLogLineages()) {
+    lineage_control = new cLineageControl( *genebank, stats );
+  }
+  else lineage_control = NULL;    // no lineage logging
+
+  // Setup the default mutation rates...
+  cMutationRates & default_mut_rates = environment.GetMutRates();
+  default_mut_rates.SetCopyMutProb  ( cConfig::GetCopyMutProb()   );
+  default_mut_rates.SetInsMutProb   ( cConfig::GetInsMutProb()    );
+  default_mut_rates.SetDelMutProb   ( cConfig::GetDelMutProb()    );
+  default_mut_rates.SetDivMutProb   ( cConfig::GetDivMutProb()    );
+  default_mut_rates.SetPointMutProb ( cConfig::GetPointMutProb()  );
+  default_mut_rates.SetDivideMutProb( cConfig::GetDivideMutProb() );
+  default_mut_rates.SetDivideInsProb( cConfig::GetDivideInsProb() );
+  default_mut_rates.SetDivideDelProb( cConfig::GetDivideDelProb() );
+  default_mut_rates.SetParentMutProb( cConfig::GetParentMutProb() );
+
+  // Setup the default population interface...
+  default_interface.SetPopulation(this);
+
+  // Avida specific information.
+  world_x = cConfig::GetWorldX();
+  world_y = cConfig::GetWorldY();
+  int geometry = cConfig::GetWorldGeometry();
+  const int num_cells = world_x * world_y;
+  cout << "Building world " << world_x << "x" << world_y
+       << " = " << num_cells << " organisms." << endl;
+  if (geometry == GEOMETRY_GRID) {
+    cout << "Geometry: Bounded grid" << endl;
+  } else if (geometry == GEOMETRY_TORUS) {
+    cout << "Geometry: Torus" << endl;
+  } else {
+    cout << "Geometry: Unknown" << endl;
+  }
+
+  cell_array.Resize(num_cells);
+  resource_count.ResizeSpatialGrids(world_x, world_y);
+  
+  bool bottom_flag, top_flag, right_flag, left_flag;
+  for (int cell_id = 0; cell_id < num_cells; cell_id++) {
+    int x = cell_id % world_x;
+    int y = cell_id / world_x;
+    cell_array[cell_id].Setup(cell_id, default_mut_rates);
+
+
+    if ((y == 0) && (geometry == GEOMETRY_GRID)) {
+      bottom_flag = false;
+    } else {
+      bottom_flag = true;
+    }
+    if ((y == world_y-1) && (geometry == GEOMETRY_GRID)) {
+      top_flag = false;
+    } else {
+      top_flag = true;
+    }
+    if ((x == 0) && (geometry == GEOMETRY_GRID)) {
+      left_flag = false;
+    } else {
+      left_flag = true;
+    }
+    if ((x == world_x-1) && (geometry == GEOMETRY_GRID)) {
+      right_flag = false;
+    } else {
+      right_flag = true;
+    }
+
+    // Setup the connection list for each cell. (Clockwise from -1 to 1)
+
+    tList<cPopulationCell> & conn_list=cell_array[cell_id].ConnectionList();
+    if (bottom_flag && left_flag) {
+      conn_list.Push(&(cell_array[Neighbor(cell_id,world_x,world_y, -1, -1)]));
+    }
+    if (bottom_flag) {
+      conn_list.Push(&(cell_array[Neighbor(cell_id,world_x,world_y,  0, -1)]));
+    }
+    if (bottom_flag && right_flag) {
+      conn_list.Push(&(cell_array[Neighbor(cell_id,world_x,world_y, +1, -1)]));
+    }
+    if (right_flag) {
+      conn_list.Push(&(cell_array[Neighbor(cell_id,world_x,world_y, +1,  0)]));
+    }
+    if (top_flag && right_flag) {
+      conn_list.Push(&(cell_array[Neighbor(cell_id,world_x,world_y, +1, +1)]));
+    }
+    if (top_flag) {
+      conn_list.Push(&(cell_array[Neighbor(cell_id,world_x,world_y,  0, +1)]));
+    }
+    if (top_flag && left_flag) {
+      conn_list.Push(&(cell_array[Neighbor(cell_id,world_x,world_y, -1, +1)]));
+    }
+    if (left_flag) {
+      conn_list.Push(&(cell_array[Neighbor(cell_id,world_x,world_y, -1,  0)]));
+    }
+
+    // Setup the reaper queue...
+    if (cConfig::GetBirthMethod() == POSITION_CHILD_FULL_SOUP_ELDEST) {
+      reaper_queue.Push(&(cell_array[cell_id]));
+    }
+  }
+
+  BuildTimeSlicer();
+
+  // Setup the resources...
+  const cResourceLib & resource_lib = environment.GetResourceLib();
+  for (int i = 0; i < resource_lib.GetSize(); i++) {
+    cResource * res = resource_lib.GetResource(i);
+    const double decay = 1.0 - res->GetOutflow();
+    resource_count.Setup(i, res->GetName(), res->GetInitial(), 
+                           res->GetInflow(), decay,
+                           res->GetGeometry(), res->GetXDiffuse(),
+                           res->GetXGravity(), res->GetYDiffuse(), 
+                           res->GetYGravity(), res->GetInflowX1(), 
+                           res->GetInflowX2(), res->GetInflowY1(), 
+                           res->GetInflowY2(), res->GetOutflowX1(), 
+                           res->GetOutflowX2(), res->GetOutflowY1(), 
+                           res->GetOutflowY2() );
+    stats.SetResourceName(i, res->GetName());
+  }
+
+  // Give stats information about the environment...
+  const cTaskLib & task_lib = environment.GetTaskLib();
+  for (int i = 0; i < task_lib.GetSize(); i++) {
+    const cTaskEntry & cur_task = task_lib.GetTask(i);
+    stats.SetTaskName(i, cur_task.GetDesc());
+  }
+
+  const cInstSet & inst_set = environment.GetInstSet();
+  for (int i = 0; i < inst_set.GetSize(); i++) {
+    stats.SetInstName(i, inst_set.GetName(i));
+  }
+
+  // Load a clone if one is provided, otherwise setup start organism.
+  if (cConfig::GetCloneFilename() == "") {
+    Inject( cInstUtil::LoadGenome(cConfig::GetStartCreature(),
+				  environment.GetInstSet()) );
+  } else {
+    ifstream fp(cConfig::GetCloneFilename()());
+    LoadClone(fp);
+  }
+
+  // Load a saved population if one is provided.
+  cString fname(cConfig::GetLoadPopFilename());
+  if (fname != "") {
+    fprintf(stderr,"Loding Population from %s\n", fname());
+
+    // If last three chars of filename are ".gz" , gunzip it first
+    if (fname.Find(".gz") == fname.GetSize() - 3) {
+      cString cmd(fname);
+      cmd.Insert("gunzip ");
+      fname.ClipEnd(3);
+      system(cmd);
+
+      ifstream fp(fname);
+      if( !fp.good() ){
+	fprintf(stderr, "ERROR: Failed to load population file %s\n",fname());
+	exit(2);
+      }
+      LoadPopulation(fp);
+
+      cmd = fname;
+      cmd.Insert("gzip ");
+      system(cmd);
+    } else {
+      // load normally
+      ifstream fp(fname);
+      LoadPopulation(fp);
+    }
+  }
+
+}
+
+
+cPopulation::~cPopulation()
+{
+  for (int i = 0; i < cell_array.GetSize(); i++) KillOrganism(cell_array[i]);
+
+  if ( lineage_control != NULL ) delete lineage_control;
+  delete genebank;
+  delete inject_genebank;
+  delete schedule;
+}
+
+
+// Activate the child, given information from the parent.
+// Return true if parent lives through this process.
+
+bool cPopulation::ActivateOffspring(cGenome & child_genome,
+				    cOrganism & parent_organism)
+{
+  assert(&parent_organism != NULL);
+
+  tArray<cOrganism *> child_array;
+  tArray<cMerit> merit_array;
+  birth_chamber.SubmitOffspring(child_genome, parent_organism,
+				child_array, merit_array);
+
+  cPhenotype & parent_phenotype = parent_organism.GetPhenotype();
+
+  if (child_array.GetSize() == 0) {
+    // No children to be born.  Allow parent to think it happened anyway.
+    parent_phenotype.DivideReset(parent_organism.GetGenome().GetSize());
+    return true;
+  }
+
+  bool parent_alive = true;  // Will the parent live through this process?
+
+  // First, setup the genotype of all of the offspring.
+  cGenotype * parent_genotype = parent_organism.GetGenotype();
+  const int parent_id = parent_organism.PopInterface().GetCellID();
+  assert(parent_id >= 0 && parent_id < cell_array.GetSize());
+  cPopulationCell & parent_cell = cell_array[ parent_id ];
+
+  tArray<int> target_cells(child_array.GetSize());
+
+  for (int i = 0; i < child_array.GetSize(); i++) {
+    cGenotype * child_genotype = parent_genotype;
+
+    // If the parent genotype is not correct for the child, adjust it.
+    if (parent_phenotype.CopyTrue() == false ||
+	parent_phenotype.DivideSex() == true) {
+      child_genotype =
+	genebank->AddGenotype(child_array[i]->GetGenome(), parent_genotype);
+    }
+
+    // And set the genotype now that we know it.
+    child_array[i]->SetGenotype(child_genotype);
+    parent_genotype->SetBreedStats(*child_genotype);
+
+    // We want to make sure that the child's genotype is not delete from the
+    // genebank before the child is placed.
+    child_genotype->IncDeferAdjust();
+
+
+    // Do lineage tracking for the new creature, if necessary.  Must occur
+    // before old organism is removed.
+    LineageSetupOrganism( child_array[i], parent_organism.GetLineage(),
+			  parent_organism.GetLineageLabel(), parent_genotype );
+
+    // If we are not on the last offspring, don't replace the parent!
+    if (i < child_array.GetSize() - 1) {
+      target_cells[i] = PositionChild( parent_cell, false ).GetID();
+    } else {
+      target_cells[i] = PositionChild( parent_cell, true ).GetID();
+      // If we did, in fact, replace the parent, make a note of this.
+      if (target_cells[i] == parent_cell.GetID()) parent_alive = false;      
+    }
+
+    child_array[i]->MutationRates().
+      Copy(GetCell(target_cells[i]).MutationRates());
+  }
+
+  // Update the parent's and child's phenotype.  Previous work in this function
+  // may require old phenotype information; don't unpdate sooner!
+  parent_phenotype.DivideReset(parent_organism.GetGenome().GetSize());
+
+  // Go back into a for-loop and continue to deal with the children.
+  for (int i = 0; i < child_array.GetSize(); i++) {
+    const int child_length = child_array[i]->GetGenome().GetSize();
+    child_array[i]->GetPhenotype().
+      SetupOffspring(parent_phenotype,child_length);
+    child_array[i]->GetPhenotype().SetMerit(merit_array[i]);
+  }
+
+  // If we're not about to kill the parent, do some extra work on it.
+  if (parent_alive == true) {
+    schedule->Adjust(parent_cell.GetID(), parent_phenotype.GetMerit());
+
+    // In a local run, face the child toward the parent. 
+    if (cConfig::GetBirthMethod() < NUM_LOCAL_POSITION_CHILD) {
+      for (int i = 0; i < child_array.GetSize(); i++) {
+	GetCell(target_cells[i]).Rotate(parent_cell);
+      }
+    }
+  }
+
+  // Do any statistics on the parent that just gave birth...
+  parent_genotype->AddGestationTime( parent_phenotype.GetGestationTime() );
+  parent_genotype->AddFitness(       parent_phenotype.GetFitness()       );
+  parent_genotype->AddMerit(         parent_phenotype.GetMerit()         );
+  parent_genotype->AddCopiedSize(    parent_phenotype.GetCopiedSize()    );
+  parent_genotype->AddExecutedSize(  parent_phenotype.GetExecutedSize()  );
+
+  // Place all of the offspring...
+  for (int i = 0; i < child_array.GetSize(); i++) {
+    ActivateOrganism(child_array[i], GetCell(target_cells[i]));
+    cGenotype * child_genotype = child_array[i]->GetGenotype();
+    child_genotype->DecDeferAdjust();
+    genebank->AdjustGenotype(*child_genotype);
+  }
+
+  return parent_alive;
+}
+
+bool cPopulation::ActivateInject(cOrganism & parent, const cGenome & injected_code)
+{
+  assert(&parent != NULL);
+  
+  if(injected_code.GetSize() ==0)
+    return false;
+
+  cHardware4Stack & parent_cpu = (cHardware4Stack &) parent.GetHardware();
+  cInjectGenotype * parent_genotype = parent_cpu.GetCurThreadOwner();
+  
+  const int parent_id = parent.PopInterface().GetCellID();
+  assert(parent_id >= 0 && parent_id < cell_array.GetSize());
+  cPopulationCell & parent_cell = cell_array[ parent_id ];
+
+  int num_neighbors = parent.GetNeighborhoodSize();
+  cOrganism * target_organism = 
+    parent_cell.connection_list.GetPos(g_random.GetUInt(num_neighbors))->GetOrganism();
+
+  if(target_organism==NULL)
+    return false;
+
+  cHardware4Stack & child_cpu = (cHardware4Stack &) target_organism->GetHardware();
+  
+  if(child_cpu.GetNumThreads()==cConfig::GetMaxCPUThreads())
+    return false;
+
+  cInjectGenotype * child_genotype = parent_genotype;
+
+  if(target_organism->InjectHost(parent_cpu.GetLabel(), injected_code)) {
+    // If the parent genotype is not correct for the child, adjust it.
+    if (parent_genotype == NULL || parent_genotype->GetGenome() != injected_code) {
+      child_genotype = inject_genebank->AddInjectGenotype(injected_code, parent_genotype);
+    }
+    
+    target_organism->AddParasite(child_genotype);
+    child_genotype->AddParasite();
+    child_cpu.SetThreadOwner(child_genotype);
+    //if(parent_genotype!=NULL)
+    //  parent_genotype->RemoveParasite();
+    inject_genebank->AdjustInjectGenotype(*child_genotype);
+  }
+  else
+    return false;
+
+  return true;
+
+  // And set the genotype now that we know it.
+  //child_array[i]->SetGenotype(child_genotype);
+  //parent_genotype->SetBreedStats(*child_genotype);
+  
+  // We want to make sure that the child's genotype is not deleted from the
+  // genebank before the child is placed.
+  //child_genotype->IncDeferAdjust();
+  
+  // **THIS WILL BE NECESSARY IF/WHEN WE IMPLEMENT PARASITE LINEAGES.**
+  // Do lineage tracking for the new creature, if necessary.  Must occur
+  // before old organism is removed.
+  //LineageSetupOrganism( child_array[i], parent_organism.GetLineage(),
+  //			  parent_organism.GetLineageLabel(), parent_genotype );
+  
+  // **THIS WILL BE NECESSARY ONCE WE IMPLEMENT PARASITE MUTATION RATES.**
+  //child_array[i]->MutationRates().
+  //  Copy(GetCell(target_cells[i]).MutationRates());
+  
+  // Do any statistics on the parent that just gave birth...
+  //parent_genotype->AddGestationTime( parent_phenotype.GetGestationTime() );
+  //parent_genotype->AddFitness(       parent_phenotype.GetFitness()       );
+  //parent_genotype->AddMerit(         parent_phenotype.GetMerit()         );
+  //parent_genotype->AddCopiedSize(    parent_phenotype.GetCopiedSize()    );
+  //parent_genotype->AddExecutedSize(  parent_phenotype.GetExecutedSize()  );
+
+  // Place all of the offspring...
+  /*for (int i = 0; i < child_array.GetSize(); i++) {
+    ActivateOrganism(child_array[i], GetCell(target_cells[i]));
+    cGenotype * child_genotype = child_array[i]->GetGenotype();
+    child_genotype->DecDeferAdjust();
+    genebank->AdjustGenotype(*child_genotype);
+    }*/
+}
+
+bool cPopulation::ActivateInject(const int cell_id, const cGenome & injected_code)
+{
+  cInjectGenotype * child_genotype = inject_genebank->AddInjectGenotype(injected_code);
+  cHardware4Stack & child_cpu = (cHardware4Stack &) cell_array[cell_id].GetOrganism()->GetHardware();
+  if(cell_array[cell_id].GetOrganism()->InjectHost(cCodeLabel(), injected_code))
+    {
+      cell_array[cell_id].GetOrganism()->AddParasite(child_genotype);
+      child_genotype->AddParasite();
+      child_cpu.SetThreadOwner(child_genotype);
+      inject_genebank->AdjustInjectGenotype(*child_genotype);
+    }
+  else
+    return false;
+
+  return true;
+}
+
+void cPopulation::ActivateOrganism(cOrganism * in_organism,
+				   cPopulationCell & target_cell)
+{
+  assert(in_organism != NULL);
+  assert(in_organism->GetGenome().GetSize() > 1);
+
+  // If the organism does not have a genotype, give it one!
+  if (in_organism->GetGenotype() == NULL) {
+    cGenotype * new_genotype = genebank->AddGenotype(in_organism->GetGenome());
+    in_organism->SetGenotype(new_genotype);
+  }
+  cGenotype * in_genotype = in_organism->GetGenotype();
+
+  // Save the old genotype from this cell...
+  cGenotype * old_genotype = NULL;
+  if (target_cell.IsOccupied()) {
+    old_genotype = target_cell.GetOrganism()->GetGenotype();
+
+    // Sometimes a new organism will kill off the last member of its genotype
+    // in the population.  Normally this would remove the genotype, so we 
+    // want to defer adjusting that genotype until the new one is placed.
+    old_genotype->IncDeferAdjust();
+  }
+
+  // Update the contents of the target cell.
+  KillOrganism(target_cell);
+  target_cell.InsertOrganism(*in_organism);
+
+  // Setup the inputs in the target cell.
+  environment.SetupInputs(target_cell.input_array);
+
+  // Update the genebank...
+  in_genotype->AddOrganism();
+
+  if (old_genotype != NULL) {
+    old_genotype->DecDeferAdjust();
+    genebank->AdjustGenotype(*old_genotype);
+  }
+  genebank->AdjustGenotype(*in_genotype);
+
+  // Initialize the time-slice for this new organism.
+  schedule->Adjust(target_cell.GetID(),in_organism->GetPhenotype().GetMerit());
+
+  // Special handling for certain birth methods.
+  if (cConfig::GetBirthMethod() == POSITION_CHILD_FULL_SOUP_ELDEST) {
+    reaper_queue.Push(&target_cell);
+  }
+
+  num_organisms++;
+
+  // Statistics...
+  stats.RecordBirth(target_cell.GetID(), in_genotype->GetID(),
+		      in_organism->GetPhenotype().ParentTrue());
+}
+
+void cPopulation::KillOrganism(cPopulationCell & in_cell)
+{
+  // do we actually have something to kill?
+  if (in_cell.IsOccupied() == false) {
+    return;
+  }
+
+  // Statistics...
+  cOrganism * organism = in_cell.GetOrganism();
+  cGenotype * genotype = organism->GetGenotype();
+  stats.RecordDeath(in_cell.GetID(), genotype->GetID(),
+		    organism->GetPhenotype().GetAge());
+
+
+  // Do the lineage handling
+  if (lineage_control != NULL) {
+    lineage_control->RemoveCreature( organism );
+  }
+
+  // Do statistics
+  num_organisms--;
+
+  //if (organism->GetPhenotype().IsParasite() == true) {
+  //  genotype->AddParasite();
+  //}
+  genotype->RemoveOrganism();
+  
+  for(int i=0; i<organism->GetNumParasites(); i++) {
+    organism->GetParasite(i).RemoveParasite();
+  }
+      
+  // And clear it!
+  in_cell.RemoveOrganism();
+  delete organism;
+
+  // Alert the scheduler that this cell has a 0 merit.
+  schedule->Adjust( in_cell.GetID(), cMerit(0) );
+
+  // Update the genebank (note: genotype adjustment may be defered)
+  genebank->AdjustGenotype(*genotype);
+}
+
+void cPopulation::Kaboom(cPopulationCell & in_cell)
+{
+  cOrganism * organism = in_cell.GetOrganism();
+  cGenotype * genotype = organism->GetGenotype();
+  cGenome genome = genotype->GetGenome();
+  int id = genotype->GetID();
+  
+  int radius = 2;
+  int distance = 0;
+  int count = 0;
+  
+  for (int i=-1*radius; i<=radius; i++) {
+    for (int j=-1*radius; j<=radius; j++) {
+      cPopulationCell & death_cell =
+	cell_array[Neighbor(in_cell.GetID(), world_x, world_y, i, j)];
+      //do we actually have something to kill?
+      if (death_cell.IsOccupied() == false) continue;
+      
+      cOrganism * org_temp = death_cell.GetOrganism();
+      cGenotype * gene_temp = org_temp->GetGenotype();
+      
+      if (distance == 0) {
+	int temp_id = gene_temp->GetID();
+	if (temp_id != id) {
+	  KillOrganism(death_cell);
+	  count++;
+	}
+      }
+      else {	
+	cGenome genome_temp = gene_temp->GetGenome();
+	int diff=0;
+	for (int i=0; i<genome_temp.GetSize(); i++)
+	  if (genome_temp.AsString()[i] != genome.AsString()[i])
+	    diff++;
+	if (diff > distance)
+	  {
+	    KillOrganism(death_cell);
+	    count++;
+	  }
+      }
+    }
+  }
+  KillOrganism(in_cell);
+  // @SLG my prediction = 92% and, 28 get equals
+}
+
+/**
+ * This function is responsible for adding an organism to a given lineage,
+ * and setting the organism's lineage label and the lineage pointer.
+ **/
+
+void cPopulation::LineageSetupOrganism(cOrganism * organism, cLineage * lin,
+				     int lin_label, cGenotype *parent_genotype)
+{
+  // If we have some kind of lineage control, adjust the default values
+  // passed in.
+  if ( lineage_control ){
+    lin = lineage_control->
+      AddCreature(organism->GetGenotype(), parent_genotype, lin, lin_label);
+    lin_label = lin->GetID();
+  }
+
+  organism->SetLineageLabel( lin_label );
+  organism->SetLineage( lin );
+}
+
+
+/**
+ * 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,
+ * and it gives a centralized function to work with.  The parent_ok flag asks
+ * if it is okay to replace the parent.
+ **/
+
+cPopulationCell & cPopulation::PositionChild(cPopulationCell & parent_cell,
+					     bool parent_ok)
+{
+  assert(parent_cell.IsOccupied());
+  
+  // Try out global birth methods first...
+
+  if (cConfig::GetBirthMethod() == POSITION_CHILD_FULL_SOUP_RANDOM) {
+    int out_pos = g_random.GetUInt(cell_array.GetSize());
+    while (parent_ok == false && out_pos == parent_cell.GetID()) {
+      out_pos = g_random.GetUInt(cell_array.GetSize());
+    }
+    return GetCell(out_pos);
+  }
+  else if (cConfig::GetBirthMethod() == POSITION_CHILD_FULL_SOUP_ELDEST) {
+    cPopulationCell * out_cell = reaper_queue.PopRear();
+    if (parent_ok == false && out_cell->GetID() == parent_cell.GetID()) {
+      out_cell = reaper_queue.PopRear();
+      reaper_queue.PushRear(&parent_cell);
+    }
+    return *out_cell;
+  }
+
+  // Construct a list of equally viable locations to place the child...
+  tList<cPopulationCell> found_list;
+
+  // First, check if there is an empty organism to work with (always preferred)
+  tList<cPopulationCell> & conn_list = parent_cell.ConnectionList();
+  FindEmptyCell(conn_list, found_list);
+
+  // If we have not found an empty organism, we must use the specified function
+  // to determine how to choose among the filled organisms.
+  if (found_list.GetSize() == 0) {
+    switch(cConfig::GetBirthMethod()) {
+    case POSITION_CHILD_AGE:
+      PositionAge(parent_cell, found_list, parent_ok);
+      break;
+    case POSITION_CHILD_MERIT:
+      PositionMerit(parent_cell, found_list, parent_ok);
+      break;
+    case POSITION_CHILD_RANDOM:
+      found_list.Append(conn_list);
+      if (parent_ok == true) found_list.Push(&parent_cell);
+      break;
+    case POSITION_CHILD_EMPTY:
+      // Nothing is in list if no empty cells are found...
+      break;
+    }
+  }
+
+  // If there are no possibilities, return NULL.
+  if (found_list.GetSize() == 0) return parent_cell;
+
+  // Choose the organism randomly from those in the list, and return it.
+  int choice = g_random.GetUInt(found_list.GetSize());
+  return *( found_list.GetPos(choice) );
+}
+
+
+int cPopulation::ScheduleOrganism()
+{
+  return schedule->GetNextID();
+}
+
+void cPopulation::ProcessStep(double step_size, int cell_id)
+{
+  assert(step_size > 0.0);
+  assert(cell_id >= 0 && cell_id < cell_array.GetSize());
+
+  cPopulationCell & cell = GetCell(cell_id);
+  assert(cell.IsOccupied()); // Unoccupied cell getting processor time!
+
+//    static ofstream debug_fp("debug.trace");
+//    debug_fp << stats.GetUpdate() << " "
+//  	   << cell.GetOrganism()->GetCellID() << " "
+//  	   << cell.GetOrganism()->GetGenotype()->GetID() << " "
+//  	   << g_random.GetDouble() << " "
+//      	   << cell.GetOrganism()->GetHardware().GetMemory().AsString() << " "
+//  	   << endl;
+
+  cell.GetOrganism()->GetHardware().SingleProcess();
+  stats.IncExecuted();
+  resource_count.Update(step_size);
+}
+
+
+void cPopulation::ProcessStep(double step_size)
+{
+  ProcessStep( step_size, ScheduleOrganism() );
+}
+
+
+void cPopulation::UpdateOrganismStats()
+{
+  // Loop through all the cells getting stats and doing calculations
+  // which must be done on a creature by creature basis.
+
+  // Clear out organism sums...
+  stats.SumFitness().Clear();
+  stats.SumGestation().Clear();
+  stats.SumMerit().Clear();
+  stats.SumCreatureAge().Clear();
+  stats.SumGeneration().Clear();
+  stats.SumNeutralMetric().Clear();
+  stats.SumLineageLabel().Clear();
+  stats.SumCopyMutRate().Clear();
+  stats.SumDivMutRate().Clear();
+  stats.SumCopySize().Clear();
+  stats.SumExeSize().Clear();
+  stats.SumMemSize().Clear();
+
+
+  stats.ZeroTasks();
+
+#ifdef INSTRUCTION_COUNT
+  stats.ZeroInst();
+#endif
+
+  // Counts...
+  int num_breed_true = 0;
+  int num_parasites = 0;
+  int num_no_birth = 0;
+  int num_multi_thread = 0;
+  int num_single_thread = 0;
+  int num_modified = 0;
+
+  // Maximums...
+  cMerit max_merit(0);
+  double max_fitness = 0;
+
+  for (int i = 0; i < cell_array.GetSize(); i++) {
+    // Only look at cells with organisms in them.
+    if (cell_array[i].IsOccupied() == false) continue;
+
+    cOrganism * organism = cell_array[i].GetOrganism();
+    const cPhenotype & phenotype = organism->GetPhenotype();
+    const cMerit cur_merit = phenotype.GetMerit();
+    const double cur_fitness = phenotype.GetFitness();
+
+    stats.SumFitness().Add(cur_fitness);
+    stats.SumMerit().Add(cur_merit.GetDouble());
+    stats.SumGestation().Add(phenotype.GetGestationTime());
+    stats.SumCreatureAge().Add(phenotype.GetAge());
+    stats.SumGeneration().Add(phenotype.GetGeneration());
+    stats.SumNeutralMetric().Add(phenotype.GetNeutralMetric());
+    stats.SumLineageLabel().Add(organism->GetLineageLabel());
+    stats.SumCopyMutRate().Add(organism->MutationRates().GetCopyMutProb());
+    stats.SumLogCopyMutRate().Add(log(organism->MutationRates().GetCopyMutProb()));
+    stats.SumDivMutRate().Add(organism->MutationRates().GetDivMutProb() / organism->GetPhenotype().GetDivType());
+    stats.SumLogDivMutRate().Add(log(organism->MutationRates().GetDivMutProb() /organism->GetPhenotype().GetDivType()));
+    stats.SumCopySize().Add(phenotype.GetCopiedSize());
+    stats.SumExeSize().Add(phenotype.GetExecutedSize());
+    stats.SetGenoMapElement(i, organism->GetGenotype()->GetID());
+
+#ifdef INSTRUCTION_COUNT
+//    for (int j=0; j < environment.GetInstSet().GetSize(); j++) {
+    for (int j=0; j < cConfig::GetNumInstructions(); j++) {
+	stats.SumExeInst()[j].Add(organism->GetPhenotype().GetLastInstCount()[j]);
+    }
+#endif
+
+    if (cur_merit > max_merit) max_merit = cur_merit;
+    if (cur_fitness > max_fitness) max_fitness = cur_fitness;
+
+    // Test what tasks this creatures has completed.
+    for (int j=0; j < phenotype.GetEnvironment().GetTaskLib().GetSize(); j++) {
+      if (phenotype.GetCurTaskCount()[j] > 0)  stats.AddCurTask(j);
+      if (phenotype.GetLastTaskCount()[j] > 0) stats.AddLastTask(j);
+    }
+
+    // Increment the counts for all qualities the organism has...
+    if (phenotype.ParentTrue()) num_breed_true++;
+    if (phenotype.IsParasite()) num_parasites++;
+    if( phenotype.GetNumDivides() == 0 ) num_no_birth++;
+    if(phenotype.IsMultiThread()) num_multi_thread++;
+    else num_single_thread++;
+    if(phenotype.IsModified()) num_modified++;
+
+    // Hardware specific collections...
+    if (organism->GetHardware().GetType() == HARDWARE_TYPE_CPU_ORIGINAL) {
+      cHardwareBase & hardware = organism->GetHardware();
+      stats.SumMemSize().Add(hardware.GetMemory().GetSize());
+    }
+
+    // Increment the age of this organism.
+    organism->GetPhenotype().IncAge();
+  }
+
+  stats.SetBreedTrueCreatures(num_breed_true);
+  stats.SetNumNoBirthCreatures(num_no_birth);
+  stats.SetNumParasites(num_parasites);
+  stats.SetNumSingleThreadCreatures(num_single_thread);
+  stats.SetNumMultiThreadCreatures(num_multi_thread);
+  stats.SetNumModified(num_modified);
+
+  stats.SetMaxMerit(max_merit.GetDouble());
+  stats.SetMaxFitness(max_fitness);
+
+  stats.SetResources(resource_count.GetResources());
+  stats.SetSpatialRes(resource_count.GetSpatialRes());
+  stats.SetResourcesGeometry(resource_count.GetResourcesGeometry());
+}
+
+
+void cPopulation::UpdateGenotypeStats()
+{
+  // Loop through all genotypes, finding stats and doing calcuations.
+
+  // Clear out genotype sums...
+  stats.SumGenotypeAge().Clear();
+  stats.SumAbundance().Clear();
+  stats.SumGenotypeDepth().Clear();
+  stats.SumSize().Clear();
+  stats.SumThresholdAge().Clear();
+
+  double entropy = 0.0;
+
+  cGenotype * cur_genotype = genebank->GetBestGenotype();
+  for (int i = 0; i < genebank->GetSize(); i++) {
+    const int abundance = cur_genotype->GetNumOrganisms();
+
+    // If we're at a dead genotype, we've hit the end of the list!
+    if (abundance == 0) break;
+
+    // Update stats...
+    const int age = stats.GetUpdate() - cur_genotype->GetUpdateBorn();
+    stats.SumGenotypeAge().Add(age, abundance);
+    stats.SumAbundance().Add(abundance);
+    stats.SumGenotypeDepth().Add(cur_genotype->GetDepth(), abundance);
+    stats.SumSize().Add(cur_genotype->GetLength(), abundance);
+
+    // Calculate this genotype's contribution to entropy
+    const double p = ((double) abundance) / (double) num_organisms;
+    const double partial_ent = -(p * Log(p));
+    entropy += partial_ent;
+
+    // Do any special calculations for threshold genotypes.
+    if (cur_genotype->GetThreshold()) {
+      stats.SumThresholdAge().Add(age, abundance);
+    }
+
+    // ...and advance to the next genotype...
+    cur_genotype = cur_genotype->GetNext();
+  }
+
+  stats.SetEntropy(entropy);
+}
+
+
+void cPopulation::UpdateSpeciesStats()
+{
+  double species_entropy = 0.0;
+
+  stats.SumSpeciesAge().Clear();
+
+  // Loop through all species that need to be reset prior to calculations.
+  cSpecies * cur_species = genebank->GetFirstSpecies();
+  for (int i = 0; i < genebank->GetNumSpecies(); i++) {
+    cur_species->ResetStats();
+    cur_species = cur_species->GetNext();
+  }
+
+  // Collect info from genotypes and send it to their species.
+  cGenotype * genotype = genebank->GetBestGenotype();
+  for (int i = 0; i < genebank->GetSize(); i++) {
+    if (genotype->GetSpecies() != NULL) {
+      genotype->GetSpecies()->AddOrganisms(genotype->GetNumOrganisms());
+    }
+    genotype = genotype->GetNext();
+  }
+
+  // Loop through all of the species in the soup, taking info on them.
+  cur_species = genebank->GetFirstSpecies();
+  for (int i = 0; i < genebank->GetNumSpecies(); i++) {
+    const int abundance = cur_species->GetNumOrganisms();
+    // const int num_genotypes = cur_species->GetNumGenotypes();
+
+    // Basic statistical collection...
+    const int species_age = stats.GetUpdate() - cur_species->GetUpdateBorn();
+    stats.SumSpeciesAge().Add(species_age, abundance);
+
+    // Caculate entropy on the species level...
+    if (abundance > 0) {
+      double p = ((double) abundance) / (double) num_organisms;
+      double partial_ent = -(p * Log(p));
+      species_entropy += partial_ent;
+    }
+
+    // ...and advance to the next species...
+    cur_species = cur_species->GetNext();
+  }
+
+  stats.SetSpeciesEntropy(species_entropy);
+}
+
+void cPopulation::UpdateDominantStats()
+{
+  cGenotype * dom_genotype = genebank->GetBestGenotype();
+  if (dom_genotype == NULL) return;
+
+  stats.SetDomGenotype(dom_genotype);
+  stats.SetDomMerit(dom_genotype->GetMerit());
+  stats.SetDomGestation(dom_genotype->GetGestationTime());
+  stats.SetDomReproRate(dom_genotype->GetReproRate());
+  stats.SetDomFitness(dom_genotype->GetFitness());
+  stats.SetDomCopiedSize(dom_genotype->GetCopiedSize());
+  stats.SetDomExeSize(dom_genotype->GetExecutedSize());
+
+  stats.SetDomSize(dom_genotype->GetLength());
+  stats.SetDomID(dom_genotype->GetID());
+  stats.SetDomName(dom_genotype->GetName());
+  stats.SetDomBirths(dom_genotype->GetThisBirths());
+  stats.SetDomBreedTrue(dom_genotype->GetThisBreedTrue());
+  stats.SetDomBreedIn(dom_genotype->GetThisBreedIn());
+  stats.SetDomBreedOut(dom_genotype->GetThisBreedOut());
+  stats.SetDomAbundance(dom_genotype->GetNumOrganisms());
+  stats.SetDomGeneDepth(dom_genotype->GetDepth());
+  stats.SetDomSequence(dom_genotype->GetGenome().AsString());
+}
+
+void cPopulation::UpdateDominantParaStats()
+{
+  cInjectGenotype * dom_inj_genotype = inject_genebank->GetBestInjectGenotype();
+  if (dom_inj_genotype == NULL) return;
+
+  stats.SetDomInjGenotype(dom_inj_genotype);
+  //stats.SetDomMerit(dom_genotype->GetMerit());
+  //stats.SetDomGestation(dom_genotype->GetGestationTime());
+  //stats.SetDomReproRate(dom_genotype->GetReproRate());
+  //stats.SetDomFitness(dom_genotype->GetFitness());
+  //stats.SetDomCopiedSize(dom_genotype->GetCopiedSize());
+  //stats.SetDomExeSize(dom_genotype->GetExecutedSize());
+
+  stats.SetDomInjSize(dom_inj_genotype->GetLength());
+  stats.SetDomInjID(dom_inj_genotype->GetID());
+  stats.SetDomInjName(dom_inj_genotype->GetName());
+  //stats.SetDomInjBirths(dom_inj_genotype->GetThisBirths());
+  //stats.SetDomBreedTrue(dom_genotype->GetThisBreedTrue());
+  //stats.SetDomBreedIn(dom_genotype->GetThisBreedIn());
+  //stats.SetDomBreedOut(dom_genotype->GetThisBreedOut());
+  stats.SetDomInjAbundance(dom_inj_genotype->GetNumInjected());
+  //stats.SetDomInjGeneDepth(dom_inj_genotype->GetDepth());
+  stats.SetDomInjSequence(dom_inj_genotype->GetGenome().AsString());
+}
+
+void cPopulation::CalcUpdateStats()
+{
+  // Reset the Genebank to prepare it for stat collection.
+  genebank->UpdateReset();
+
+  UpdateOrganismStats();
+  UpdateGenotypeStats();
+  UpdateSpeciesStats();
+  UpdateDominantStats();
+  UpdateDominantParaStats();
+
+  // Do any final calculations...
+  stats.SetNumCreatures(GetNumOrganisms());
+  stats.SetNumGenotypes(genebank->GetSize());
+  stats.SetNumThreshSpecies(genebank->GetNumSpecies());
+
+  // Have stats calculate anything it now can...
+  stats.CalcEnergy();
+  stats.CalcFidelity();
+}
+
+
+bool cPopulation::SaveClone(ofstream & fp)
+{
+  if (fp.good() == false) return false;
+
+  // Save the current update
+  fp << stats.GetUpdate() << " ";
+
+  // Save the genebank info.
+  genebank->SaveClone(fp);
+
+  // Save the genotypes manually.
+  fp << genebank->GetSize() << " ";
+
+  cGenotype * cur_genotype = genebank->GetBestGenotype();
+  for (int i = 0; i < genebank->GetSize(); i++) {
+    cur_genotype->SaveClone(fp);
+
+    // Advance...
+    cur_genotype = cur_genotype->GetNext();
+  }
+
+  // Save the organim layout...
+  fp << cell_array.GetSize() << " ";
+  for (int i = 0; i < cell_array.GetSize(); i++) {
+    if (cell_array[i].IsOccupied() == true) {
+      fp <<  cell_array[i].GetOrganism()->GetGenotype()->GetID() << " ";
+    }
+    else fp << "-1 ";
+  }
+
+  return true;
+}
+
+
+bool cPopulation::LoadClone(ifstream & fp)
+{
+  if (fp.good() == false) return false;
+
+  // Pick up the update where it was left off.
+  int cur_update;
+  fp >> cur_update;
+
+  stats.SetCurrentUpdate(cur_update);
+
+  // Clear out the population
+  for (int i = 0; i < cell_array.GetSize(); i++) KillOrganism(cell_array[i]);
+
+  // Load the genebank info.
+  genebank->LoadClone(fp);
+
+  // Load up the genotypes.
+  int num_genotypes = 0;
+  fp >> num_genotypes;
+
+  cGenotype * genotype_array = new cGenotype[num_genotypes];
+  for (int i = 0; i < num_genotypes; i++) genotype_array[i].LoadClone(fp);
+
+  // Now load them into the organims.  @CAO make sure cell_array.GetSize() is right!
+  int in_num_cells;
+  int genotype_id;
+  fp >> in_num_cells;
+  if (cell_array.GetSize() != in_num_cells) return false;
+
+  for (int i = 0; i < cell_array.GetSize(); i++) {
+    fp >> genotype_id;
+    if (genotype_id == -1) continue;
+    int genotype_index = -1;
+    for (int j = 0; j < num_genotypes; j++) {
+      if (genotype_array[j].GetID() == genotype_id) {
+	genotype_index = j;
+	break;
+      }
+    }
+
+    assert(genotype_index != -1);
+    InjectGenome(i, genotype_array[genotype_index].GetGenome());
+  }
+
+  sync_events = true;
+
+  return true;
+}
+
+// This class is needed for the next function
+class cTmpGenotype {
+public:
+  int id_num;
+  int parent_id;
+  int num_cpus;
+  int total_cpus;
+  double merit;
+  int update_born;
+  int update_dead;
+
+  cGenotype *genotype;
+
+  bool operator<( const cTmpGenotype rhs ) const {
+    return id_num < rhs.id_num; }
+};	
+
+
+bool cPopulation::LoadDumpFile(cString filename, int update)
+{
+  // set the update if requested
+  if ( update >= 0 )
+    stats.SetCurrentUpdate(update);
+
+  // Clear out the population
+  for (int i = 0; i < cell_array.GetSize(); i++) KillOrganism(cell_array[i]);
+
+  cout << "Loading: " << filename << endl;
+
+  cInitFile input_file(filename);
+  if (!input_file.IsOpen()) {
+    cerr << "Error: Cannot load file: \"" << filename << "\"." << endl;
+    exit(1);
+  }
+  input_file.Load();
+  input_file.Compress();
+  input_file.Close();
+
+  // First, we read in all the genotypes and store them in a list
+
+  vector<cTmpGenotype> genotype_vect;
+
+  for (int line_id = 0; line_id < input_file.GetNumLines(); line_id++) {
+    cString cur_line = input_file.GetLine(line_id);
+
+    // Setup the genotype for this line...
+    cTmpGenotype tmp;
+    tmp.id_num      = cur_line.PopWord().AsInt();
+    tmp.parent_id   = cur_line.PopWord().AsInt();
+    /*parent_dist =*/          cur_line.PopWord().AsInt();
+    tmp.num_cpus    = cur_line.PopWord().AsInt();
+    tmp.total_cpus  = cur_line.PopWord().AsInt();
+    /*length      =*/          cur_line.PopWord().AsInt();
+    tmp.merit 	    = cur_line.PopWord().AsDouble();
+    /*gest_time   =*/ cur_line.PopWord().AsInt();
+    /*fitness     =*/ cur_line.PopWord().AsDouble();
+    tmp.update_born = cur_line.PopWord().AsInt();
+    tmp.update_dead = cur_line.PopWord().AsInt();
+    /*depth       =*/ cur_line.PopWord().AsInt();
+    cString name = cStringUtil::Stringf("org-%d", tmp.id_num);
+    cGenome genome( cur_line.PopWord() );
+
+    // we don't allow birth or death times larger than the current update
+    if ( stats.GetUpdate() > tmp.update_born )
+      tmp.update_born = stats.GetUpdate();
+    if ( stats.GetUpdate() > tmp.update_dead )
+      tmp.update_dead = stats.GetUpdate();
+
+    tmp.genotype =
+      new cGenotype(tmp.update_born, tmp.id_num);
+    tmp.genotype->SetGenome( genome );
+    tmp.genotype->SetName( name );
+
+    genotype_vect.push_back( tmp );
+  }
+
+  // now, we sort them in ascending order according to their id_num
+  sort( genotype_vect.begin(), genotype_vect.end() );
+  // set the parents correctly
+
+  vector<cTmpGenotype>::const_iterator it = genotype_vect.begin();
+  for ( ; it != genotype_vect.end(); it++ ){
+    vector<cTmpGenotype>::const_iterator it2 = it;
+    cGenotype *parent = 0;
+    // search backwards till we find the parent
+    if ( it2 != genotype_vect.begin() )
+      do{
+	it2--;
+	if ( (*it).parent_id == (*it2).id_num ){
+	  parent = (*it2).genotype;
+	  break;
+	}	
+      }
+      while ( it2 != genotype_vect.begin() );
+    (*it).genotype->SetParent( parent );
+  }
+
+  int cur_update = stats.GetUpdate(); 
+  int current_cell = 0;
+  bool soup_full = false;
+  it = genotype_vect.begin();
+  for ( ; it != genotype_vect.end(); it++ ){
+    genebank->AddGenotype( (*it).genotype );
+    if ( (*it).num_cpus == 0 ){ // historic organism
+      // remove immediately, so that it gets transferred into the
+      // historic database. We change the update temporarily to the
+      // true death time of this organism, so that all stats are correct.
+      stats.SetCurrentUpdate( (*it).update_dead );
+      genebank->RemoveGenotype( *(*it).genotype );
+      stats.SetCurrentUpdate( cur_update );
+    }
+    else{ // otherwise, we insert as many organisms as we need
+      for ( int i=0; i<(*it).num_cpus; i++ ){
+	if ( current_cell >= cell_array.GetSize() ){
+	  soup_full = true;
+	  break;
+	}	  
+	InjectGenotype( current_cell, (*it).genotype );
+	cPhenotype & phenotype = GetCell(current_cell).GetOrganism()->GetPhenotype();
+	if ( (*it).merit > 0) phenotype.SetMerit( cMerit((*it).merit) );
+	schedule->Adjust(current_cell, phenotype.GetMerit());
+
+	int lineage_label = 0;
+	LineageSetupOrganism(GetCell(current_cell).GetOrganism(),
+			     0, lineage_label,
+			     (*it).genotype->GetParentGenotype());
+	current_cell += 1;
+      }
+    }
+    cout << (*it).id_num << " "
+	 << (*it).parent_id << " "
+	 << (*it).genotype->GetParentID() << " "
+	 << (*it).genotype->GetNumOffspringGenotypes() << " "
+	 << (*it).num_cpus << " "
+	 << (*it).genotype->GetNumOrganisms() << endl;
+    if (soup_full){
+      cout << "cPopulation::LoadDumpFile: You are trying to load more organisms than there is space!" << endl;
+      cout << "cPopulation::LoadDumpFile: Remaining organisms are ignored." << endl;
+      break;
+    }
+  }
+  sync_events = true;
+
+  return true;
+}
+
+//// Save And Load Populations ////
+bool cPopulation::SavePopulation(ofstream & fp)
+{
+  if (fp.good() == false) return false;
+
+  // Save the update
+  fp << stats.GetUpdate() << endl;
+
+  // looping through all cells saving state.
+  for (int i = 0; i < cell_array.GetSize(); i++)  cell_array[i].SaveState(fp);
+
+  return true;
+}
+
+
+bool cPopulation::LoadPopulation(ifstream & fp)
+{
+  if(fp.good() == false) return false;
+
+  // Load Update...
+  int cur_update;
+  fp >> cur_update;
+  stats.SetCurrentUpdate(cur_update);
+
+  // Clear out the current population
+  for (int i = 0; i < cell_array.GetSize(); i++) KillOrganism( cell_array[i] );
+
+  // looping through all organims
+  for (int i = 0; i < cell_array.GetSize(); i++) cell_array[i].LoadState(fp);
+
+  sync_events = true;
+
+  return true;
+}
+
+
+bool cPopulation::DumpMemorySummary(ofstream & fp)
+{
+  if (fp.good() == false) return false;
+
+  // Dump the memory...
+
+  for (int i = 0; i < cell_array.GetSize(); i++) {
+    fp << i << " ";
+    if (cell_array[i].IsOccupied() == false) {
+      fp << "EMPTY" << endl;
+    }
+    else {
+      cGenome & mem = cell_array[i].GetOrganism()->GetHardware().GetMemory();
+      fp << mem.GetSize() << " "
+	 << mem.AsString() << endl;
+    }
+  }
+  return true;
+}
+
+bool cPopulation::OK()
+{
+  // First check all sub-objects...
+  if (!genebank->OK() || !schedule->OK()) return false;
+
+  // Next check organisms...
+  for (int i = 0; i < cell_array.GetSize(); i++) {
+    if (cell_array[i].OK() == false) return false;
+    assert(cell_array[i].GetID() == i);
+  }
+
+  // And stats...
+  assert(world_x * world_y == cell_array.GetSize());
+
+  return true;
+}
+
+
+/**
+ * This function loads a genome from a given file, and initializes
+ * a cpu with it.
+ *
+ * @param filename The name of the file to load.
+ * @param in_cpu The grid-position into which the genome should be loaded.
+ * @param merit An initial merit value.
+ * @param lineage_label A value that allows to track the daughters of
+ * this organism.
+ **/
+
+void cPopulation::Inject(const cGenome & genome, int cell_id, double merit, 
+			 int lineage_label, double neutral, int mem_space )
+{
+  // If an invalid cell was given, choose a new ID for it.
+  if (cell_id < 0) {
+    switch (cConfig::GetBirthMethod()) {
+    case POSITION_CHILD_FULL_SOUP_ELDEST:
+      cell_id = reaper_queue.PopRear()->GetID();
+    default:
+      cell_id = 0;
+    }
+  }
+
+  if(mem_space==0) {
+    InjectGenome( cell_id, genome);
+    cPhenotype & phenotype = GetCell(cell_id).GetOrganism()->GetPhenotype();
+    phenotype.SetNeutralMetric(neutral);
+    
+    if (merit > 0) phenotype.SetMerit( cMerit(merit) );
+    schedule->Adjust(cell_id, phenotype.GetMerit());
+    
+    LineageSetupOrganism(GetCell(cell_id).GetOrganism(), 0, lineage_label);
+  }
+  else
+    {
+      ActivateInject(cell_id, genome);
+    }
+      
+}
+
+cPopulationCell & cPopulation::GetCell(int in_num)
+{
+  return cell_array[in_num];
+}
+
+
+void cPopulation::UpdateResources(const tArray<double> & res_change)
+{
+  resource_count.Modify(res_change);
+}
+
+void cPopulation::UpdateResource(int id, double change)
+{
+  resource_count.Modify(id, change);
+}
+
+void cPopulation::UpdateCellResources(const tArray<double> & res_change, 
+                                      const int cell_id)
+{
+  resource_count.ModifyCell(res_change, cell_id);
+}
+
+void cPopulation::SetResource(int id, double new_level)
+{
+  resource_count.Set(id, new_level);
+}
+
+void cPopulation::BuildTimeSlicer()
+{
+  switch (cConfig::GetSlicingMethod()) {
+  case SLICE_CONSTANT:
+    cout << "...Building Constant Time Slicer..." << endl;
+    schedule = new cConstSchedule(cell_array.GetSize());
+    break;
+  case SLICE_PROB_MERIT:
+    cout << "...Building Probablistic Time Slicer..." << endl;
+    schedule = new cProbSchedule(cell_array.GetSize());
+    break;
+  case SLICE_INTEGRATED_MERIT:
+    cout << "...Building Integrated Time Slicer..." << endl;
+    schedule = new cIntegratedSchedule(cell_array.GetSize());
+    break;
+  default:
+    cout << "...Requested Time Slicer not found, defaulting to Integrated..."
+	 << endl;
+    schedule = new cIntegratedSchedule(cell_array.GetSize());
+    break;
+  }
+
+}
+
+
+void cPopulation::PositionAge(cPopulationCell & parent_cell,
+			      tList<cPopulationCell> & found_list,
+			      bool parent_ok)
+{
+  // Start with the parent organism as the replacement, and see if we can find
+  // anything equivilent or better.
+
+  found_list.Push(&parent_cell);
+  int max_age = parent_cell.GetOrganism()->GetPhenotype().GetAge();
+  if (parent_ok == false) max_age = -1;
+
+  // Now look at all of the neighbors.
+  tListIterator<cPopulationCell> conn_it( parent_cell.ConnectionList() );
+
+  cPopulationCell * test_cell;
+  while ( (test_cell = conn_it.Next()) != NULL) {
+    const int cur_age = test_cell->GetOrganism()->GetPhenotype().GetAge();
+    if (cur_age > max_age) {
+      max_age = cur_age;
+      found_list.Clear();
+      found_list.Push(test_cell);
+    }
+    else if (cur_age == max_age) {
+      found_list.Push(test_cell);
+    }
+  }
+}
+
+void cPopulation::PositionMerit(cPopulationCell & parent_cell,
+				tList<cPopulationCell> & found_list,
+				bool parent_ok)
+{
+  // Start with the parent organism as the replacement, and see if we can find
+  // anything equivilent or better.
+
+  found_list.Push(&parent_cell);
+  double max_ratio = parent_cell.GetOrganism()->CalcMeritRatio();
+  if (parent_ok == false) max_ratio = -1;
+
+  // Now look at all of the neighbors.
+  tListIterator<cPopulationCell> conn_it( parent_cell.ConnectionList() );
+
+  cPopulationCell * test_cell;
+  while ( (test_cell = conn_it.Next()) != NULL) {
+    const double cur_ratio = test_cell->GetOrganism()->CalcMeritRatio();
+    if (cur_ratio > max_ratio) {
+      max_ratio = cur_ratio;
+      found_list.Clear();
+      found_list.Push(test_cell);
+    }
+    else if (cur_ratio == max_ratio) {
+      found_list.Push(test_cell);
+    }
+  }
+}
+
+void cPopulation::FindEmptyCell(tList<cPopulationCell> & cell_list,
+				tList<cPopulationCell> & found_list)
+{
+  tListIterator<cPopulationCell> cell_it(cell_list);
+  cPopulationCell * test_cell;
+
+  while ( (test_cell = cell_it.Next()) != NULL) {
+    // If this cell is empty, add it to the list...
+    if (test_cell->IsOccupied() == false) found_list.Push(test_cell);
+  }
+}
+
+
+
+void cPopulation::InjectGenotype(int cell_id, cGenotype *new_genotype)
+{
+  assert(cell_id >= 0 && cell_id < cell_array.GetSize());
+
+  cOrganism * new_organism = new cOrganism(new_genotype->GetGenome(),
+					   default_interface,
+					   environment);
+
+  // Set the genotype...
+  new_organism->SetGenotype(new_genotype);
+
+  // Setup the phenotype...
+  cPhenotype & phenotype = new_organism->GetPhenotype();
+  phenotype.SetupInject(new_genotype->GetLength());
+  phenotype.SetMerit( cMerit(new_genotype->GetTestMerit()) );
+
+  // @CAO are these really needed?
+  phenotype.SetLinesCopied( new_genotype->GetTestCopiedSize() );
+  phenotype.SetLinesExecuted( new_genotype->GetTestExecutedSize() );
+  phenotype.SetGestationTime( new_genotype->GetTestGestationTime() );
+
+  // Prep the cell..
+  if (cConfig::GetBirthMethod() == POSITION_CHILD_FULL_SOUP_ELDEST &&
+      cell_array[cell_id].IsOccupied() == true) {
+    // Have to manually take this cell out of the reaper Queue.
+    reaper_queue.Remove( &(cell_array[cell_id]) );
+  }
+
+  // Setup the child's mutation rates.  Since this organism is being injected
+  // and has no parent, we should always take the rate from the environment.
+  new_organism->MutationRates().Copy(cell_array[cell_id].MutationRates());
+
+
+  // Activate the organism in the population...
+  ActivateOrganism(new_organism, cell_array[cell_id]);
+}
+
+
+void cPopulation::InjectGenome(int cell_id, const cGenome & genome)
+{
+  // Setup the genotype...
+  cGenotype * new_genotype = genebank->AddGenotype(genome);
+
+  // The rest is done by InjectGenotype();
+  InjectGenotype( cell_id, new_genotype );
+}
+
+
+void cPopulation::SerialTransfer(int transfer_size, bool ignore_deads)
+{
+  assert(transfer_size > 0);
+
+  // If we are ignoring all dead organisms, remove them from the population.
+  if (ignore_deads == true) {
+    for (int i = 0; i < GetSize(); i++) {
+      cPopulationCell & cell = cell_array[i];
+      if (cell.IsOccupied() && cell.GetOrganism()->GetTestFitness() == 0.0) {
+	KillOrganism(cell);
+      }
+    }
+  }
+
+  // If removing the dead was enough, stop here.
+  if (num_organisms <= transfer_size) return;
+
+  // Collect a vector of the occupied cells...
+  vector<int> transfer_pool;
+  transfer_pool.reserve(num_organisms);
+  for (int i = 0; i < GetSize(); i++) {
+    if (cell_array[i].IsOccupied()) transfer_pool.push_back(i);
+  }
+
+  // Remove the proper number of cells.
+  const int removal_size = num_organisms - transfer_size;
+  for (int i = 0; i < removal_size; i++) {
+    int j = (int) g_random.GetUInt(transfer_pool.size());
+    KillOrganism(cell_array[transfer_pool[j]]);
+    transfer_pool[j] = transfer_pool.back();
+    transfer_pool.pop_back();
+  }
+}
+
+void cPopulation::ParasiteDebug()
+{
+  ofstream outfile;
+  outfile.open("debug.out", ofstream::app);
+  outfile << stats.GetUpdate() << endl;
+  int total=0;
+  cInjectGenotype * temp;
+  for(int x=0; x<cell_array.GetSize(); x++)
+    {
+      if(cell_array[x].GetOrganism()!=NULL)
+	{
+	  assert(cell_array[x].GetOrganism()->GetNumParasites()>=0 && 
+		 cell_array[x].GetOrganism()->GetNumParasites()<=1);
+	  total+=cell_array[x].GetOrganism()->GetNumParasites();
+	  if(cell_array[x].GetOrganism()->GetNumParasites())
+	    {
+	      cHardware4Stack & cpu = (cHardware4Stack &) cell_array[x].GetOrganism()->GetHardware();
+	      outfile << x << " ";
+	      outfile << cell_array[x].GetOrganism()->GetGenotype()->GetID() << " ";
+	      temp = cpu.GetThreadOwner(1);
+	      assert(temp!=NULL);
+	      outfile << temp->GetID() << endl;	      
+	    }
+	}
+    }
+  outfile << total << endl;
+  outfile.close();
+}
+
+void cPopulation::PrintPhenotypeData(const cString & filename)
+{
+  set<int> ids;
+  for (int i = 0; i < cell_array.GetSize(); i++) 
+  {
+    // Only look at cells with organisms in them.
+    if (cell_array[i].IsOccupied() == false) continue;
+
+    cOrganism * organism = cell_array[i].GetOrganism();
+    const cPhenotype & phenotype = organism->GetPhenotype();
+    
+    int id = 0;
+    for (int j = 0; j < phenotype.GetLastTaskCount().GetSize(); j++)
+    {
+      if (phenotype.GetLastTaskCount().ElementAt(j) > 0)
+        id += (1 << j);
+    }
+    ids.insert(id);
+  }
+  ofstream outfile;
+  outfile.open(filename, ofstream::app);
+  outfile << stats.GetUpdate() << "\t" << ids.size() << endl;
+  outfile.close();
+}
Index: avida/current/source/main/population.hh
diff -u /dev/null avida/current/source/main/population.hh:1.62
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/population.hh	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,185 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef POPULATION_HH
+#define POPULATION_HH
+
+#include <fstream>
+
+#ifndef BIRTH_CHAMBER_HH
+#include "birth_chamber.hh"
+#endif
+#ifndef POPULATION_INTERFACE_HH
+#include "population_interface.hh"
+#endif
+#ifndef RESOURCE_COUNT_HH
+#include "resource_count.hh"
+#endif
+#ifndef STATS_HH
+#include "stats.hh"
+#endif
+#ifndef STRING_hH
+#include "string.hh"
+#endif
+#ifndef TARRAY_HH
+#include "tArray.hh"
+#endif
+#ifndef TLIST_HH
+#include "tList.hh"
+#endif
+
+class cSchedule;
+template <class T> class tArray; // aggregate
+class cPopulationCell;
+class cResourceCount; // aggregate
+class cBirthChamber; // aggregate
+class cStats; // aggregate
+class cGenebank;
+class cInjectGenebank;
+class cLineageControl;
+template <class T> class tList; // aggregate
+class cEnvironment;
+class cPopulationInterface; // aggregate
+class cOrganism;
+class cLineage;
+class cGenotype;
+class cGenome;
+class cString; // aggregate
+
+class cPopulation {
+private:
+  // Components...
+  cSchedule * schedule;                // Handles allocation of CPU cycles
+  tArray<cPopulationCell> cell_array;  // Local cells composing the population
+  cResourceCount resource_count;       // Global resources available
+  cBirthChamber birth_chamber;         // Global birth chamber.
+
+  // Data Tracking...
+  cStats stats;                      // Main statistics object...
+  cGenebank * genebank;                // Tracks genotypes
+  cInjectGenebank * inject_genebank;   // Tracks all injected code
+  cLineageControl * lineage_control;   // Tracks Linages
+  tList<cPopulationCell> reaper_queue; // Death order in some mass-action runs
+
+  // Default organism setups...
+  cEnvironment & environment;          // Physics & Chemestry description
+  cPopulationInterface default_interface;  // Organism interface to population
+
+  // Other data...
+  int world_x;                         // Structured population width.
+  int world_y;                         // Structured population
+  int num_organisms;                   // Cell count with living organisms
+
+  // Outside interactions...
+  bool sync_events;   // Do we need to sync up the event list with population?
+
+  ///////////////// Private Methods ////////////////////
+  void BuildTimeSlicer(); // Build the schedule object
+
+  // Methods to place offspring in the population.
+  cPopulationCell & PositionChild(cPopulationCell & parent_cell,
+				  bool parent_ok);
+  void PositionAge(cPopulationCell & parent_cell,
+		   tList<cPopulationCell> & found_list, bool parent_ok);
+  void PositionMerit(cPopulationCell & parent_cell,
+		     tList<cPopulationCell> & found_list, bool parent_ok);
+  void FindEmptyCell(tList<cPopulationCell> & cell_list,
+		     tList<cPopulationCell> & found_list);
+
+  // Update statistics collecting...
+  void UpdateOrganismStats();
+  void UpdateGenotypeStats();
+  void UpdateSpeciesStats();
+  void UpdateDominantStats();
+  void UpdateDominantParaStats();
+
+  /**
+   * Attention: InjectGenotype does *not* add the genotype to the genebank.
+   * You have to do that yourself!
+   **/ 
+  void InjectGenotype(int pos, cGenotype *genotype);
+  void InjectGenome(int pos, const cGenome & genome);
+
+  void LineageSetupOrganism(cOrganism * organism, cLineage * lineage,
+			    int lin_label, cGenotype * parent_genotype=NULL);
+
+  // Must be called to activate *any* organism in the population.
+  void ActivateOrganism(cOrganism * in_organism, cPopulationCell &target_cell);
+
+public:
+  cPopulation(const cPopulationInterface & in_interface,
+	      cEnvironment & in_environment);
+  ~cPopulation();
+
+  // Activate the offspring of an organism in the population
+  bool ActivateOffspring(cGenome & child_genome, cOrganism & parent_organism);
+
+  bool ActivateInject(cOrganism & parent, const cGenome & injected_code);
+  bool ActivateInject(const int cell_id, const cGenome & injected_code);
+
+  // Inject an organism from the outside world.
+  void Inject(const cGenome & genome, int cell_id=-1, double merit=-1,
+	      int lineage_label=0, double neutral_metric=0, int mem_space=0 );
+
+  // Deactivate an organism in the population (required for deactivations)
+  void KillOrganism(cPopulationCell & in_cell);
+  void Kaboom(cPopulationCell & in_cell);
+
+  // Process a single organism one instruction...
+  int ScheduleOrganism();          // Determine next organism to be processed.
+  void ProcessStep(double step_size);
+  void ProcessStep(double step_size, int cell_id);
+
+  // Calculate the statistics from the most recent update.
+  void CalcUpdateStats();
+
+  // Clear all but a subset of cells...
+  void SerialTransfer( int transfer_size, bool ignore_deads );
+
+  // Saving and loading...
+  bool SaveClone(std::ofstream & fp);
+  bool LoadClone(std::ifstream & fp);
+  bool LoadDumpFile(cString filename, int update);
+  bool SavePopulation(std::ofstream & fp);
+  bool LoadPopulation(std::ifstream & fp);
+  bool DumpMemorySummary(std::ofstream & fp);
+
+  bool OK();
+
+  int GetSize() { return cell_array.GetSize(); }
+  int GetWorldX() { return world_x; }
+  int GetWorldY() { return world_y; }
+  int GetUpdate() { return stats.GetUpdate(); }
+  double GetGeneration() { return stats.SumGeneration().Average(); }
+
+  cPopulationCell & GetCell(int in_num);
+  const tArray<double> & GetResources() const
+    { return resource_count.GetResources(); }
+  const tArray<double> & GetCellResources(int cell_id) const
+    { return resource_count.GetCellResources(cell_id); }
+  cBirthChamber & GetBirthChamber(int id) { (void) id; return birth_chamber; }
+
+  void UpdateResources(const tArray<double> & res_change);
+  void UpdateResource(int id, double change);
+  void UpdateCellResources(const tArray<double> & res_change, 
+                           const int cell_id);
+  void SetResource(int id, double new_level);
+
+  cStats & GetStats() { return stats; }
+  cGenebank & GetGenebank() { return *genebank; }
+  cInjectGenebank & GetInjectGenebank() { return *inject_genebank; }
+  cLineageControl * GetLineageControl() { return lineage_control; }
+  cEnvironment & GetEnvironment() { return environment; }
+  int GetNumOrganisms() { return num_organisms; }
+
+  bool GetSyncEvents() { return sync_events; }
+  void SetSyncEvents(bool _in) { sync_events = _in; }
+  void ParasiteDebug();
+  void PrintPhenotypeData(const cString & filename);
+};
+
+#endif
Index: avida/current/source/main/population_cell.cc
diff -u /dev/null avida/current/source/main/population_cell.cc:1.11
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/population_cell.cc	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,146 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef POPULATION_CELL_HH
+#include "population_cell.hh"
+#endif
+
+#ifndef CONFIG_HH
+#include "config.hh"
+#endif
+#ifndef CPU_DEFS_HH
+#include "cpu_defs.hh"
+#endif
+#ifndef ORGANISM_HH
+#include "organism.hh"
+#endif
+#ifndef TOOLS_HH
+#include "tools.hh"
+#endif
+
+using namespace std;
+
+cPopulationCell::cPopulationCell()
+  : organism(NULL)
+  , cur_input(0)
+  , organism_count(0)
+{
+}
+
+cPopulationCell::cPopulationCell(const cPopulationCell & in_cell)
+  : organism(in_cell.organism)
+  , cur_input(in_cell.cur_input)
+  , cell_id(in_cell.cell_id)
+  , organism_count(in_cell.organism_count)
+{
+  for (int i = 0; i < IO_SIZE; i++) input_array[i] = in_cell.input_array[i];
+  mutation_rates.Copy(in_cell.mutation_rates);
+  tConstListIterator<cPopulationCell> conn_it(in_cell.connection_list);
+  cPopulationCell * test_cell;
+  while ( (test_cell = (cPopulationCell *) conn_it.Next()) != NULL) {
+    connection_list.PushRear(test_cell);
+  }
+}
+
+void cPopulationCell::operator=(const cPopulationCell & in_cell)
+{
+  organism = in_cell.organism;
+  for (int i = 0; i < IO_SIZE; i++) input_array[i] = in_cell.input_array[i];
+  cur_input = in_cell.cur_input;
+  cell_id = in_cell.cell_id;
+  organism_count = in_cell.organism_count;
+  mutation_rates.Copy(in_cell.mutation_rates);
+  tConstListIterator<cPopulationCell> conn_it(in_cell.connection_list);
+  cPopulationCell * test_cell;
+  while ( (test_cell = (cPopulationCell *) conn_it.Next()) != NULL) {
+    connection_list.PushRear(test_cell);
+  }
+}
+
+void cPopulationCell::Setup(int in_id, const cMutationRates & in_rates)
+{
+  cell_id = in_id;
+  mutation_rates.Copy(in_rates);
+}
+
+void cPopulationCell::Rotate(cPopulationCell & new_facing)
+{
+  // @CAO Note, this breaks avida if new_facing is not in connection_list
+
+#ifdef DEBUG
+  int scan_count = 0;
+#endif
+  while (connection_list.GetFirst() != &new_facing) {
+    connection_list.CircNext();
+#ifdef DEBUG
+    assert(++scan_count < connection_list.GetSize());
+#endif
+  }
+}
+
+
+int cPopulationCell::GetInput()
+{
+  if (cur_input >= IO_SIZE) cur_input = 0;
+  return input_array[cur_input++];
+}
+
+int cPopulationCell::GetInputAt(int & input_pointer)
+{
+  if (input_pointer >= IO_SIZE) input_pointer = 0;
+  return input_array[input_pointer++];
+}
+
+int cPopulationCell::GetInput(int id)
+{
+  assert(id >= 0 && id < IO_SIZE);
+  return input_array[id];
+}
+
+void cPopulationCell::InsertOrganism(cOrganism & new_org)
+{
+  assert(&new_org != NULL);
+  assert(new_org.GetGenotype() != NULL);
+  assert(organism == NULL);
+
+  // Adjust this cell's attributes to account for the new organism.
+  organism = &new_org;
+  organism_count++;
+
+  // Adjust the organism's attributes to match this cell.
+  organism->PopInterface().SetCellID(cell_id);
+}
+
+cOrganism * cPopulationCell::RemoveOrganism()
+{
+  if (organism == NULL) return NULL;   // Nothing to do!
+
+  // For the moment, the cell doesn't keep track of much...
+  cOrganism * out_organism = organism;
+  organism = NULL;
+  return out_organism;
+}
+
+
+bool cPopulationCell::OK()
+{
+  // Nothing for the moment...
+  return true;
+}
+
+bool cPopulationCell::SaveState(ofstream & fp)
+{
+  // Nothing for the moment...
+  return false;
+}
+
+
+bool cPopulationCell::LoadState(ifstream & fp)
+{
+  // Nothing for the moment...
+  return false;
+}
Index: avida/current/source/main/population_cell.hh
diff -u /dev/null avida/current/source/main/population_cell.hh:1.10
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/population_cell.hh	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,75 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef POPULATION_CELL_HH
+#define POPULATION_CELL_HH
+
+#include <fstream>
+
+#ifndef MUTATION_RATES_HH
+#include "mutation_rates.hh"
+#endif
+#ifndef TARRAY_HH
+#include "tArray.hh"
+#endif
+#ifndef TLIST_HH
+#include "tList.hh"
+#endif
+
+class cPopulation;
+class cOrganism;
+template <class T> class tList; // aggregate
+class cPopulationCell;
+class cMutationRates; // aggregate
+template <class T> class tArray; // aggregate
+
+class cPopulationCell {
+  friend class cPopulation;
+private:
+  cOrganism * organism;                    // The occupent of this cell.
+  tList<cPopulationCell> connection_list;  // A list of neighboring cells.
+  cMutationRates mutation_rates;           // Mutation rates at this cell.
+  tArray<int> input_array;                 // Environmental Inputs...
+  int cur_input;                           // Next input to give organism.
+
+  int cell_id;           // Unique id for position of cell in population.
+  int organism_count;    // Total number of orgs to ever inhabit this cell.
+
+private:  // Organism changes should only occur through population...
+  void InsertOrganism(cOrganism & new_org);
+  cOrganism * RemoveOrganism();
+
+public:
+  cPopulationCell();
+  cPopulationCell(const cPopulationCell & in_cell);
+  ~cPopulationCell() { ; }
+
+  void operator=(const cPopulationCell & in_cell);
+
+  void Setup(int in_id, const cMutationRates & in_rates);
+  void Rotate(cPopulationCell & new_facing);
+
+  cOrganism * GetOrganism() const { return organism; }
+  tList<cPopulationCell> & ConnectionList() { return connection_list; }
+  const cMutationRates & MutationRates() const { return mutation_rates; }
+  cMutationRates & MutationRates() { return mutation_rates; }
+  int GetInput();
+  int GetInput(int);
+  int GetInputAt(int & input_pointer);
+
+  int GetID() const { return cell_id; }
+  int GetOrganismCount() const { return organism_count; }
+
+  bool IsOccupied() const { return organism != NULL; }
+
+  bool OK();
+
+  bool SaveState(std::ofstream & fp);
+  bool LoadState(std::ifstream & fp);
+};
+
+#endif
Index: avida/current/source/main/primitive.cc
diff -u /dev/null avida/current/source/main/primitive.cc:1.5
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/primitive.cc	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,31 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef PRIMITIVE_HH
+#include "primitive.hh"
+#endif
+
+using namespace std;
+
+int main(int argc, char * argv[])
+{
+  cEnvironment environment;
+  cPopulationInterface test_interface;
+  SetupAvida( argc, argv, environment, test_interface );
+
+  if (cConfig::GetAnalyzeMode() == true) {
+    cAvidaDriver_Base::main_driver = new cAvidaDriver_Analyze();
+  }
+  else {
+    cAvidaDriver_Base::main_driver = new cAvidaDriver_Population(environment);
+  }
+
+  cAvidaDriver_Base::main_driver->Run();
+
+  // Exit Nicely
+  ExitAvida(0);
+}
Index: avida/current/source/main/reaction.cc
diff -u /dev/null avida/current/source/main/reaction.cc:1.9
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/reaction.cc	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,52 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef REACTION_HH
+#include "reaction.hh"
+#endif
+
+#ifndef REACTION_PROCESS_HH
+#include "reaction_process.hh"
+#endif
+#ifndef REACTION_REQUISITE_HH
+#include "reaction_requisite.hh"
+#endif
+
+using namespace std;
+
+///////////////
+//  cReaction
+///////////////
+
+cReaction::cReaction(const cString & _name, int _id)
+  : name(_name)
+  , id(_id)
+  , task(NULL)
+  , active(true)
+{
+}
+
+cReaction::~cReaction()
+{
+  while (process_list.GetSize() != 0) delete process_list.Pop();
+  while (requisite_list.GetSize() != 0) delete requisite_list.Pop();
+}
+
+cReactionProcess * cReaction::AddProcess()
+{
+  cReactionProcess * new_process = new cReactionProcess();
+  process_list.PushRear(new_process);
+  return new_process;
+}
+
+cReactionRequisite * cReaction::AddRequisite()
+{
+  cReactionRequisite * new_requisite = new cReactionRequisite();
+  requisite_list.PushRear(new_requisite);
+  return new_requisite;
+}
+
Index: avida/current/source/main/reaction.hh
diff -u /dev/null avida/current/source/main/reaction.hh:1.8
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/reaction.hh	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,50 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef REACTION_HH
+#define REACTION_HH
+
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+#ifndef TLIST_HH
+#include "tList.hh"
+#endif
+
+class cString; // aggregate
+class cTaskEntry;
+template <class T> class tList; // aggregate
+class cReactionProcess;
+class cReactionRequisite;
+
+class cReaction {
+private:
+  cString name;
+  int id;
+  cTaskEntry * task;
+  tList<cReactionProcess> process_list;
+  tList<cReactionRequisite> requisite_list;
+  bool active;
+public:
+  cReaction(const cString & _name, int _id);
+  ~cReaction();
+
+  const cString & GetName() const { return name; }
+  int GetID() const { return id; }
+  cTaskEntry * GetTask() { return task; }
+  const tList<cReactionProcess> & GetProcesses() { return process_list; }
+  const tList<cReactionRequisite> & GetRequisites()
+    { return requisite_list; }
+  bool GetActive() const { return active; }
+
+  void SetTask(cTaskEntry * _task) { task = _task; }
+  cReactionProcess * AddProcess();
+  cReactionRequisite * AddRequisite();
+  void SetActive(bool in_active=true) { active = in_active; }
+};
+
+#endif
Index: avida/current/source/main/reaction_result.cc
diff -u /dev/null avida/current/source/main/reaction_result.cc:1.6
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/reaction_result.cc	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,161 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#include "reaction_result.hh"
+
+
+cReactionResult::cReactionResult(const int num_resources,
+				 const int num_tasks,
+				 const int num_reactions)
+  : resources_consumed(num_resources)
+  , resources_produced(num_resources)
+  , resources_detected(num_resources)
+  , tasks_done(num_tasks)
+  , reactions_triggered(num_reactions)
+  , bonus_add(0.0)
+  , bonus_mult(1.0)
+  , lethal(false)
+  , active_reaction(false)
+{
+}
+
+//  cReactionResult::cReactionResult(const cReactionResult & _in)
+//    : resources_consumed(_in.resources_consumed)
+//    , resources_produced(_in.resources_produced)
+//    , tasks_done(_in.tasks_done)
+//    , reactions_triggered(_in.reactions_triggered)
+//    , bonus_add(_in.bonus_add)
+//    , bonus_mult(_in.bonus_mult)
+//    , active_reaction(_in.active_reaction)
+//  {
+//  }
+
+cReactionResult::~cReactionResult()
+{
+}
+
+
+void cReactionResult::ActivateReaction()
+{
+  // If this reaction is already active, don't worry about it.
+  if (active_reaction == true) return;
+
+  // To activate the reaction, we must initialize all counter settings.
+  resources_consumed.SetAll(0.0);
+  resources_produced.SetAll(0.0);
+  resources_detected.SetAll(-1.0);
+  tasks_done.SetAll(false);
+  reactions_triggered.SetAll(false);
+
+  // And finally note that this is indeed already active.
+  active_reaction = true;
+}
+
+
+void cReactionResult::Consume(int id, double num)
+{
+  ActivateReaction();
+  resources_consumed[id] += num;
+}
+
+
+void cReactionResult::Produce(int id, double num)
+{
+  ActivateReaction();
+  resources_produced[id] += num;
+}
+
+
+void cReactionResult::Detect(int id, double num)
+{
+  ActivateReaction();
+  resources_detected[id] += num;
+}
+
+void cReactionResult::Lethal(bool flag)
+{
+ ActivateReaction();
+ lethal = flag;
+}
+
+void cReactionResult::MarkTask(int id)
+{
+  ActivateReaction();
+  tasks_done[id] = true;
+}
+
+
+void cReactionResult::MarkReaction(int id)
+{
+  ActivateReaction();
+  reactions_triggered[id] = true;
+}
+
+
+void cReactionResult::AddBonus(double value)
+{
+  ActivateReaction();
+  bonus_add += value;
+}
+
+
+void cReactionResult::MultBonus(double value)
+{
+  ActivateReaction();
+  bonus_mult *= value;
+}
+
+
+double cReactionResult::GetConsumed(int id)
+{
+  if (GetActive() == false) return 0.0;
+  return resources_consumed[id];
+}
+
+
+double cReactionResult::GetProduced(int id)
+{
+  if (GetActive() == false) return 0.0;
+  return resources_produced[id];
+}
+
+double cReactionResult::GetDetected(int id)
+{
+  if (GetActive() == false) return 0.0;
+  return resources_detected[id];
+}
+
+bool cReactionResult::GetLethal()
+{
+  if (GetActive() == false) return false;
+  return lethal;
+}
+
+bool cReactionResult::ReactionTriggered(int id)
+{
+  if (GetActive() == false) return false;
+  return reactions_triggered[id];
+}
+
+bool cReactionResult::TaskDone(int id)
+{
+  if (GetActive() == false) return false;
+  return tasks_done[id];
+}
+
+double cReactionResult::GetAddBonus()
+{
+  if (GetActive() == false) return 0.0;
+  return bonus_add;
+}
+
+double cReactionResult::GetMultBonus()
+{
+  if (GetActive() == false) return 1.0;
+  return bonus_mult;
+}
+
Index: avida/current/source/main/reaction_result.hh
diff -u /dev/null avida/current/source/main/reaction_result.hh:1.5
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/reaction_result.hh	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,55 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef REACTION_RESULT_HH
+#define REACTION_RESULT_HH
+
+#ifndef TARRAY_HH
+#include "tArray.hh"
+#endif
+
+template <class T> class tArray; // aggregate
+
+class cReactionResult {
+private:
+  tArray<double> resources_consumed;
+  tArray<double> resources_produced;
+  tArray<double> resources_detected;  //Initialize to -1.0
+  tArray<bool> tasks_done;
+  tArray<bool> reactions_triggered;
+  double bonus_add;
+  double bonus_mult;
+  bool lethal;
+  bool active_reaction;
+  inline void ActivateReaction();
+public:
+  cReactionResult(const int num_resources, const int num_tasks,
+		  const int num_reactions);
+  ~cReactionResult();
+
+  bool GetActive() { return active_reaction; }
+
+  void Consume(int id, double num);
+  void Produce(int id, double num);
+  void Detect(int id, double num);
+  void Lethal(bool num);
+  void MarkTask(int id);
+  void MarkReaction(int id);
+  void AddBonus(double value);
+  void MultBonus(double value);
+
+  double GetConsumed(int id);
+  double GetProduced(int id);
+  double GetDetected(int id);
+  bool GetLethal();
+  bool ReactionTriggered(int id);
+  bool TaskDone(int id);
+  double GetAddBonus();
+  double GetMultBonus();
+};
+
+#endif
Index: avida/current/source/main/resource.cc
diff -u /dev/null avida/current/source/main/resource.cc:1.8
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/resource.cc	Tue Nov 25 09:37:57 2003
@@ -0,0 +1,55 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef RESOURCE_HH
+#include "resource.hh"
+#endif
+
+#ifndef CONFIG_HH
+#include "config.hh"
+#endif
+
+using namespace std;
+
+cResource::cResource(const cString & _name, int _id)
+  : name(_name)
+  , id(_id)
+  , initial(0.0)
+  , inflow(0.0)
+  , outflow(0.0)
+  , geometry(GEOMETRY_GLOBAL)
+  , inflowX1(-99)
+  , inflowX2(-99)
+  , inflowY1(-99)
+  , inflowY2(-99)
+  , outflowX1(-99)
+  , outflowX2(-99)
+  , outflowY1(-99)
+  , outflowY2(-99)
+  , xdiffuse(1.0)
+  , xgravity(0.0)
+  , ydiffuse(1.0)
+  , ygravity(0.0)
+{
+}
+
+bool cResource::SetGeometry(cString _geometry)
+{
+     _geometry.ToLower();
+     if (_geometry == "global") {
+          geometry = GEOMETRY_GLOBAL;
+          return true;
+     } else if (_geometry == "grid") {
+          geometry = GEOMETRY_GRID;
+          return true;
+     } else if (_geometry == "torus") {
+          geometry = GEOMETRY_TORUS;
+          return true;
+     } else {
+          return false;
+     }
+}
Index: avida/current/source/main/resource.hh
diff -u /dev/null avida/current/source/main/resource.hh:1.6
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/resource.hh	Tue Nov 25 09:37:58 2003
@@ -0,0 +1,80 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef RESOURCE_HH
+#define RESOURCE_HH
+
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+
+class cString; // aggregate
+
+class cResource {
+private:
+  cString name;
+  int id;
+  double initial;
+  double inflow;
+  double outflow;
+  int geometry;
+  int inflowX1;
+  int inflowX2;
+  int inflowY1;
+  int inflowY2;
+  int outflowX1;
+  int outflowX2;
+  int outflowY1;
+  int outflowY2;
+  double xdiffuse;
+  double xgravity;
+  double ydiffuse;
+  double ygravity;
+ 
+public:
+  cResource(const cString & _name, int _id);
+  ~cResource() { ; }
+
+  const cString & GetName() const { return name; }
+  int GetID() const { return id; }
+  double GetInitial() const { return initial; }
+  double GetInflow() const { return inflow; }
+  double GetOutflow() const { return outflow; }
+  int GetGeometry() const { return geometry; }
+  int GetInflowX1() const { return inflowX1; }
+  int GetInflowX2() const { return inflowX2; }
+  int GetInflowY1() const { return inflowY1; }
+  int GetInflowY2() const { return inflowY2; }
+  int GetOutflowX1() const { return outflowX1; }
+  int GetOutflowX2() const { return outflowX2; }
+  int GetOutflowY1() const { return outflowY1; }
+  int GetOutflowY2() const { return outflowY2; }
+  double GetXDiffuse() const { return xdiffuse; }
+  double GetXGravity() const { return xgravity; }
+  double GetYDiffuse() const { return ydiffuse; }
+  double GetYGravity() const { return ygravity; }
+
+
+  void SetInitial(double _initial) { initial = _initial; }
+  void SetInflow (double _inflow ) { inflow  = _inflow; }
+  void SetOutflow(double _outflow) { outflow = _outflow; }
+  bool SetGeometry(cString _geometry);
+  void SetInflowX1(int _inflowX1) { inflowX1 = _inflowX1; }
+  void SetInflowX2(int _inflowX2) { inflowX2 = _inflowX2; }
+  void SetInflowY1(int _inflowY1) { inflowY1 = _inflowY1; }
+  void SetInflowY2(int _inflowY2) { inflowY2 = _inflowY2; }
+  void SetOutflowX1(int _outflowX1) { outflowX1 = _outflowX1; }
+  void SetOutflowX2(int _outflowX2) { outflowX2 = _outflowX2; }
+  void SetOutflowY1(int _outflowY1) { outflowY1 = _outflowY1; }
+  void SetOutflowY2(int _outflowY2) { outflowY2 = _outflowY2; }
+  void SetXDiffuse(double _xdiffuse) { xdiffuse = _xdiffuse; }
+  void SetXGravity(double _xgravity) { xgravity = _xgravity; }
+  void SetYDiffuse(double _ydiffuse) { ydiffuse = _ydiffuse; }
+  void SetYGravity(double _ygravity) { ygravity = _ygravity; }
+};
+
+#endif
Index: avida/current/source/main/resource_count.cc
diff -u /dev/null avida/current/source/main/resource_count.cc:1.10
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/resource_count.cc	Tue Nov 25 09:37:58 2003
@@ -0,0 +1,332 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef RESOURCE_COUNT_HH
+#include "resource_count.hh"
+#endif
+
+#ifndef CONFIG_HH
+#include "config.hh"
+#endif
+
+using namespace std;
+
+const double cResourceCount::UPDATE_STEP(1.0 / 10000.0);
+const int cResourceCount::PRECALC_DISTANCE(100);
+
+void FlowMatter(cSpatialCountElem &elem1, cSpatialCountElem &elem2, double inxdiffuse, 
+                double inydiffuse, double inxgravity, double inygravity,
+                int xdist, int ydist, double dist) {
+
+  /* Routine to calculate the amount of flow from one Element to another.
+     Amount of flow is a function of:
+
+       1) Amount of material in each cell (will try to equalize)
+       2) Distance between each cell
+       3) x and y "gravity"
+
+     This method only effect the delta amount of each element.  The State
+     method will need to be called at the end of each time step to complete
+     the movement of material.
+  */
+
+  double  diff, flowamt, xgravity, xdiffuse, ygravity,  ydiffuse;
+
+  if (((elem1.amount == 0.0) && (elem2.amount == 0.0)) && (dist < 0.0)) return;
+  diff = (elem1.amount - elem2.amount);
+  if (xdist != 0) {
+
+    /* if there is material to be effected by x gravity */
+
+    if (((xdist>0) && (inxgravity>0.0)) || ((xdist<0) && (inxgravity<0.0))) {
+      xgravity = elem1.amount * fabs(inxgravity)/3.0;
+    } else {
+      xgravity = -elem2.amount * fabs(inxgravity)/3.0;
+    }
+    
+    /* Diffusion uses the diffusion constant x half the difference (as the 
+       elements attempt to equalize) / the number of possible neighbors (8) */
+
+    xdiffuse = inxdiffuse * diff / 16.0;
+  } else {
+    xdiffuse = 0.0;
+    xgravity = 0.0;
+  }  
+  if (ydist != 0) {
+
+    /* if there is material to be effected by y gravity */
+
+    if (((ydist>0) && (inygravity>0.0)) || ((ydist<0) && (inygravity<0.0))) {
+      ygravity = elem1.amount * fabs(inygravity)/3.0;
+    } else {
+      ygravity = -elem2.amount * fabs(inygravity)/3.0;
+    }
+    ydiffuse = inydiffuse * diff / 16.0;
+  } else {
+    ydiffuse = 0.0;
+    ygravity = 0.0;
+  }  
+
+  flowamt = ((xdiffuse + ydiffuse + xgravity + ygravity)/
+             (fabs(xdist*1.0) + fabs(ydist*1.0)))/dist;
+  elem1.delta -= flowamt;
+  elem2.delta += flowamt;
+}
+
+
+cResourceCount::cResourceCount(int num_resources)
+  : resource_count(num_resources)
+  , decay_rate(num_resources)
+  , inflow_rate(num_resources)
+  , decay_precalc(num_resources, PRECALC_DISTANCE+1)
+  , inflow_precalc(num_resources, PRECALC_DISTANCE+1)
+  , spatial_resource_count(num_resources)
+  , geometry(num_resources)
+  , curr_grid_res_cnt(num_resources)
+  , curr_spatial_res_cnt(num_resources)
+  , update_time(0.0)
+  , spatial_update_time(0.0)
+{
+  resource_count.SetAll(0.0);
+  decay_rate.SetAll(0.0);
+  inflow_rate.SetAll(0.0);
+  decay_precalc.SetAll(0.0);
+  inflow_precalc.SetAll(0.0);
+  geometry.SetAll(GEOMETRY_GLOBAL);
+  curr_grid_res_cnt.SetAll(0.0);
+}
+
+cResourceCount::~cResourceCount()
+{
+}
+
+void cResourceCount::Setup(int id, cString name, double initial, double inflow,
+                           double decay, int in_geometry, double in_xdiffuse,
+                           double in_xgravity, double in_ydiffuse, 
+                           double in_ygravity, int in_inflowX1, 
+                           int in_inflowX2, int in_inflowY1, 
+                           int in_inflowY2, int in_outflowX1, 
+                           int in_outflowX2, int in_outflowY1, 
+                           int in_outflowY2)
+{
+  assert(id >= 0 && id < resource_count.GetSize());
+  assert(initial >= 0.0);
+  assert(decay >= 0.0);
+  assert(inflow >= 0.0);
+  assert(spatial_resource_count[id].GetSize() > 0);
+
+  cString geo_name;
+  if (in_geometry == GEOMETRY_GLOBAL) {
+    geo_name = "GLOBAL";
+  } else if (in_geometry == GEOMETRY_GRID) {
+    geo_name = "GRID";
+  } else if (in_geometry == GEOMETRY_TORUS) {
+    geo_name = "TORUS";
+  }
+  cerr << "Setting up resource " << name
+       << "(" << geo_name 
+       << ") with initial quatity=" << initial
+       << ", decay=" << decay
+       << ", inflow=" << inflow
+       << endl;
+  if ((in_geometry == GEOMETRY_GRID) || (in_geometry == GEOMETRY_TORUS)) {
+    cerr << "  Inflow rectangle (" << in_inflowX1 
+         << "," << in_inflowY1 
+         << ") to (" << in_inflowX2 
+         << "," << in_inflowY2 
+         << ")" << endl; 
+    cerr << "  Outflow rectangle (" << in_outflowX1 
+         << "," << in_outflowY1 
+         << ") to (" << in_outflowX2 
+         << "," << in_outflowY2 
+         << ")" << endl;
+    cerr << "  xdiffuse=" << in_xdiffuse
+         << ", xgravity=" << in_xgravity
+         << ", ydiffuse=" << in_ydiffuse
+         << ", ygravity=" << in_ygravity
+         << endl;
+  }   
+
+  resource_count[id] = initial;
+  spatial_resource_count[id].RateAll
+                              (initial/spatial_resource_count[id].GetSize());
+  spatial_resource_count[id].StateAll();  
+  decay_rate[id] = decay;
+  inflow_rate[id] = inflow;
+  geometry[id] = in_geometry;
+  spatial_resource_count[id].SetGeometry(in_geometry);
+  spatial_resource_count[id].SetPointers();
+
+  double step_decay = pow(decay, UPDATE_STEP);
+  double step_inflow = inflow * UPDATE_STEP;
+
+  decay_precalc(id, 0) = 1.0;
+  inflow_precalc(id, 0) = 0.0;
+  for (int i = 1; i <= PRECALC_DISTANCE; i++) {
+    decay_precalc(id, i)  = decay_precalc(id, i-1) * step_decay;
+    inflow_precalc(id, i) = inflow_precalc(id, i-1) * step_decay + step_inflow;
+  }
+  spatial_resource_count[id].SetXdiffuse(in_xdiffuse);
+  spatial_resource_count[id].SetXgravity(in_xgravity);
+  spatial_resource_count[id].SetYdiffuse(in_ydiffuse);
+  spatial_resource_count[id].SetYgravity(in_ygravity);
+  spatial_resource_count[id].SetInflowX1(in_inflowX1);
+  spatial_resource_count[id].SetInflowX2(in_inflowX2);
+  spatial_resource_count[id].SetInflowY1(in_inflowY1);
+  spatial_resource_count[id].SetInflowY2(in_inflowY2);
+  spatial_resource_count[id].SetOutflowX1(in_outflowX1);
+  spatial_resource_count[id].SetOutflowX2(in_outflowX2);
+  spatial_resource_count[id].SetOutflowY1(in_outflowY1);
+  spatial_resource_count[id].SetOutflowY2(in_outflowY2);
+}
+
+void cResourceCount::Update(double in_time) 
+{ 
+  update_time += in_time;
+  spatial_update_time += in_time;
+ }
+
+ 
+const tArray<double> & cResourceCount::GetResources() const
+{
+  DoUpdates();
+  return resource_count;
+}
+ 
+const tArray<double> & cResourceCount::GetCellResources(int cell_id) const
+
+  // Get amount of the resource for a given cell in the grid.  If it is a
+  // global resource pass out the entire content of that resource.
+
+{
+  int num_resources = resource_count.GetSize();
+  DoUpdates();
+  for (int i = 0; i < num_resources; i++) {
+    if (geometry[i] == GEOMETRY_GLOBAL) {
+      curr_grid_res_cnt[i] = resource_count[i];
+    } else {
+      curr_grid_res_cnt[i] = spatial_resource_count[i].GetAmount(cell_id);
+    }
+  }
+  return curr_grid_res_cnt;
+
+}
+
+const tArray<int> & cResourceCount::GetResourcesGeometry() const
+{
+  return geometry;
+}
+
+const tArray< tArray<double> > &  cResourceCount::GetSpatialRes()
+{
+  const int num_spatial_resources = spatial_resource_count.GetSize();
+  if (num_spatial_resources > 0) {
+    const int num_cells = spatial_resource_count[0].GetSize();
+    DoUpdates();
+    for (int i = 0; i < num_spatial_resources; i++) {
+      for (int j = 0; j < num_cells; j++) {
+	curr_spatial_res_cnt[i][j] = spatial_resource_count[i].GetAmount(j);
+      }
+    }
+  }
+
+  return curr_spatial_res_cnt;
+}
+
+void cResourceCount::Modify(const tArray<double> & res_change)
+{
+  assert(resource_count.GetSize() == res_change.GetSize());
+
+  for (int i = 0; i < resource_count.GetSize(); i++) {
+    resource_count[i] += res_change[i];
+    assert(resource_count[i] >= 0.0);
+  }
+}
+
+
+void cResourceCount::Modify(int id, double change)
+{
+  assert(id < resource_count.GetSize());
+
+  resource_count[id] += change;
+  assert(resource_count[id] >= 0.0);
+}
+
+void cResourceCount::ModifyCell(const tArray<double> & res_change, int cell_id)
+{
+  assert(resource_count.GetSize() == res_change.GetSize());
+
+  for (int i = 0; i < resource_count.GetSize(); i++) {
+    if (geometry[i] == GEOMETRY_GLOBAL) {
+      resource_count[i] += res_change[i];
+      assert(resource_count[i] >= 0.0);
+    } else {
+      spatial_resource_count[i].Rate(cell_id, res_change[i]);
+    }
+  }
+}
+
+
+void cResourceCount::Set(int id, double new_level)
+{
+  assert(id < resource_count.GetSize());
+
+  resource_count[id] = new_level;
+}
+
+void cResourceCount::ResizeSpatialGrids(int in_x, int in_y)
+{
+  for (int i = 0; i < resource_count.GetSize(); i++) {
+    spatial_resource_count[i].ResizeClear(in_x, in_y);
+    curr_spatial_res_cnt[i].Resize(in_x * in_y);
+  }
+}
+///// Private Methods /////////
+
+void cResourceCount::DoUpdates() const
+{ 
+  assert(update_time >= 0);
+
+  // Determine how many update steps have progressed
+  int num_steps = (int) (update_time / UPDATE_STEP);
+
+  // Preserve remainder of update_time
+  update_time -= num_steps * UPDATE_STEP;
+
+
+  while (num_steps > PRECALC_DISTANCE) {
+    for (int i = 0; i < resource_count.GetSize(); i++) {
+      if (geometry[i] == GEOMETRY_GLOBAL) {
+        resource_count[i] *= decay_precalc(i, PRECALC_DISTANCE);
+        resource_count[i] += inflow_precalc(i, PRECALC_DISTANCE);
+      }
+    }
+    num_steps -= PRECALC_DISTANCE;
+  }
+
+  for (int i = 0; i < resource_count.GetSize(); i++) {
+    if (geometry[i] == GEOMETRY_GLOBAL) {
+      resource_count[i] *= decay_precalc(i, num_steps);
+      resource_count[i] += inflow_precalc(i, num_steps);
+    }
+  }
+
+  // If one (or more) complete update has occured update the spatial resources
+
+  while (spatial_update_time >= 1.0) { 
+    spatial_update_time -= 1.0;
+    for (int i = 0; i < resource_count.GetSize(); i++) {
+      if (geometry[i] != GEOMETRY_GLOBAL) {
+        spatial_resource_count[i].Source(inflow_rate[i]);
+        spatial_resource_count[i].Sink(decay_rate[i]);
+        spatial_resource_count[i].FlowAll();
+        spatial_resource_count[i].StateAll();
+        resource_count[i] = spatial_resource_count[i].SumAll();
+      }
+    }
+  }
+}
Index: avida/current/source/main/resource_count.hh
diff -u /dev/null avida/current/source/main/resource_count.hh:1.6
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/resource_count.hh	Tue Nov 25 09:37:58 2003
@@ -0,0 +1,76 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef RESOURCE_COUNT_HH
+#define RESOURCE_COUNT_HH
+
+#ifndef SPATIAL_RES_COUNT_HH
+#include "spatial_res_count.hh"
+#endif
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+#ifndef TARRAY_HH
+#include "tArray.hh"
+#endif
+#ifndef TMATRIX_HH
+#include "tMatrix.hh"
+#endif
+
+template <class T> class tArray; // aggregate
+template <class T> class tMatrix; // aggregate
+class cSpatialResCount; // aggregate
+class cString; // aggregate
+
+class cResourceCount {
+private:
+  mutable tArray<double> resource_count;  // Current quantity of each resource
+  tArray<double> decay_rate;      // Multiplies resource count at each step
+  tArray<double> inflow_rate;     // An increment for resource at each step
+  tMatrix<double> decay_precalc;  // Precalculation of decay values
+  tMatrix<double> inflow_precalc; // Precalculation of inflow values
+  tArray<int> geometry;           // Spatial layout of each resource
+  mutable tArray<cSpatialResCount> spatial_resource_count;
+  mutable tArray<double> curr_grid_res_cnt;
+  mutable tArray< tArray<double> > curr_spatial_res_cnt;
+
+  // Setup the update process to use lazy evaluation...
+  mutable double update_time;     // Portion of an update compleated...
+  mutable double spatial_update_time; 
+  void DoUpdates() const;         // Update resource count based on update time
+
+  // A few constants to describe update process...
+  static const double UPDATE_STEP;   // Fraction of an update per step
+  static const int PRECALC_DISTANCE; // Number of steps to precalculate
+public:
+  cResourceCount(int num_resources);
+  ~cResourceCount();
+
+  void Setup(int id, cString name, double initial, double inflow, 
+             double decay, int in_geometry, double in_xdiffuse,
+             double in_xgravity, double in_ydiffuse, 
+             double in_ygravity, int in_inflowX1, 
+             int in_inflowX2, int in_inflowY1, 
+             int in_inflowY2, int in_outflowX1, 
+             int in_outflowX2, int in_outflowY1, 
+             int in_outflowY);
+  void Update(double in_time);
+
+  const tArray<double> & GetResources() const;
+  const tArray<double> & GetCellResources(int cell_id) const;
+  const tArray<int> & GetResourcesGeometry() const;
+  const tArray< tArray<double> > & GetSpatialRes();
+  void Modify(const tArray<double> & res_change);
+  void Modify(int id, double change);
+  void ModifyCell(const tArray<double> & res_change, int cell_id);
+  void Set(int id, double new_level);
+  void ResizeSpatialGrids(int in_x, int in_y);
+  cSpatialResCount GetSpatialResource(int id) 
+       { return spatial_resource_count[id]; }
+};
+
+#endif
Index: avida/current/source/main/species.cc
diff -u /dev/null avida/current/source/main/species.cc:1.16
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/species.cc	Tue Nov 25 09:37:58 2003
@@ -0,0 +1,189 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef SPECIES_HH
+#include "species.hh"
+#endif
+
+#ifndef CPU_TEST_INFO_HH
+#include "cpu_test_info.hh"
+#endif
+#ifndef FUNCTIONS_HH
+#include "functions.hh"
+#endif
+#ifndef GENOTYPE_HH
+#include "genotype.hh"
+#endif
+#ifndef GENOME_UTIL_HH
+#include "genome_util.hh"
+#endif
+#ifndef TEST_CPU_HH
+#include "test_cpu.hh"
+#endif
+
+using namespace std;
+
+
+/////////////////
+//  cSpecies
+/////////////////
+
+cSpecies::cSpecies(const cGenome & in_genome, int update )
+  : genome(in_genome)
+  , update_born(update)
+{
+  static int species_count = 0;
+  id_num = species_count++;
+  parent_id = -1;
+  symbol = '+';
+
+  num_genotypes = 0;
+  num_threshold = 0;
+  total_organisms = 0;
+  total_genotypes = 0;
+
+  queue_type = SPECIES_QUEUE_NONE;
+
+  next = NULL;
+  prev = NULL;
+
+  // Track distance of each genome as it is passed in...
+
+  for (int i = 0; i < SPECIES_MAX_DISTANCE; i++) {
+    genotype_distance[i] = 0;
+  }
+}
+
+cSpecies::~cSpecies()
+{
+  int i, total_count = 0;
+  for (i = 0; i < SPECIES_MAX_DISTANCE; i++) {
+    total_count += genotype_distance[i];
+  }
+
+#ifdef TEST
+  // Only print out the non-trivial species.
+
+  if (total_count > 1) {
+    FILE * fp = stats.GetTestFP();
+
+    fprintf(fp, "Species %3d: ", id_num);
+    for (i = 0; i < SPECIES_MAX_DISTANCE; i++) {
+      fprintf(fp, "%2d ", genotype_distance[i]);
+    }
+    fprintf(fp, "\n");
+    fflush(fp);
+  }
+#endif
+}
+
+// This method compares a second genome to this species and determines
+// how different it is.  A -1 indicates a critical failure (like one of
+// the genomes being considered is not viable), otherwise the count
+// Of failed crossovers is returned.
+// @CAO Todo: Check phenotypes, allow failure proportional to size.
+
+int cSpecies::Compare(const cGenome & test_genome, int max_fail_count)
+{
+  cCPUTestInfo test_info;
+
+  // First, make some phenotypic comparisons between organisms.
+  // For now, just check that they both copy-true.
+
+  cTestCPU::TestGenome(test_info, test_genome);
+
+  // If the organisms aren't viable, return a -1...
+  if (test_info.IsViable() == false) {
+    return -1;
+  }
+
+  // Find the optimal offset between organisms, and related variables.
+  // @CAO: For the moment, lets not worry about offsets...
+  // The first line of B is at line 'offset' of A. 
+  //int offset = cGenomeUtil::FindBestOffset(genome, test_genome);
+
+
+  // Figure out how much of the organisms overlap, and how much doesn't.
+  int overlap = Min(genome.GetSize(), test_genome.GetSize());
+  int fail_count = Max(genome.GetSize(), test_genome.GetSize()) - overlap;
+
+
+  // Do the crossovers at all posible points.
+  // Start with the first direction crossover...
+
+  bool cross1_viable = true;
+  bool cross2_viable = true;
+  cGenome cross_genome1(genome);
+  cGenome cross_genome2(test_genome);
+
+  for (int i = 0; i < overlap; i++) {
+    // If this position has changed, check if crossovers here are viable.
+    if (test_genome[i] != genome[i]) {
+      // Continue crossing over on each side...
+      cross_genome1[i] = test_genome[i];
+      cross_genome2[i] = genome[i];
+   
+      // Run each side, and determine viability...
+      cTestCPU::TestGenome(test_info, cross_genome1);
+      cross1_viable = test_info.IsViable();
+
+      cTestCPU::TestGenome(test_info, cross_genome2);
+      cross2_viable = test_info.IsViable();
+    }
+
+    if (cross1_viable == false) fail_count++;
+    if (cross2_viable == false) fail_count++;
+
+    if (max_fail_count != -1 && fail_count > max_fail_count) break;
+  }
+
+
+  return fail_count;
+}
+
+bool cSpecies::OK()
+{
+  assert(id_num >= 0);  // Species has negative ID value!
+  assert(genome.OK());  // Species genome not registering as OK!
+
+  // Assert valid statistics in species.
+  assert(total_organisms >= 0 && total_genotypes >= 0 &&
+	 num_threshold >= 0 && num_genotypes >= 0);
+
+  // Finally, make sure the species is registered as being in a queue.
+
+  assert(queue_type >= 0 && queue_type <= 3); // Species not in a proper queue
+
+  return true;
+}
+
+void cSpecies::AddThreshold(cGenotype & in_genotype)
+{
+  const int distance = 
+    cGenomeUtil::FindEditDistance(genome, in_genotype.GetGenome());
+
+  if (distance >= 0 && distance < SPECIES_MAX_DISTANCE)
+    genotype_distance[distance]++;
+
+  num_threshold++;
+}
+
+void cSpecies::RemoveThreshold(cGenotype & in_genotype)
+{
+  total_genotypes++;
+  total_organisms += in_genotype.GetTotalOrganisms();
+  num_threshold--;
+}
+
+void cSpecies::AddGenotype()
+{
+  num_genotypes++;
+}
+
+void cSpecies::RemoveGenotype() {
+  num_genotypes--;
+}
Index: avida/current/source/main/species.hh
diff -u /dev/null avida/current/source/main/species.hh:1.10
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/species.hh	Tue Nov 25 09:37:58 2003
@@ -0,0 +1,87 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef SPECIES_HH
+#define SPECIES_HH
+
+#include <fstream>
+
+#ifndef GENOME_HH
+#include "genome.hh"
+#endif
+
+#define SPECIES_QUEUE_NONE     0
+#define SPECIES_QUEUE_ACTIVE   1
+#define SPECIES_QUEUE_INACTIVE 2
+#define SPECIES_QUEUE_GARBAGE  3
+
+#define SPECIES_MAX_DISTANCE 20
+
+class cGenotype;
+
+class cSpecies {
+private:
+  int id_num;
+  int parent_id;
+  cGenome genome;
+  int update_born;
+
+  int total_organisms;
+  int total_genotypes;
+  int num_threshold;
+  int num_genotypes;
+  int num_organisms;
+  int queue_type;
+  char symbol;
+  int genotype_distance[SPECIES_MAX_DISTANCE];
+
+  cSpecies * next;
+  cSpecies * prev;
+public:
+  cSpecies(const cGenome & in_genome, int update);
+  ~cSpecies();
+
+  int Compare(const cGenome & test_genome, int max_fail_count=-1);
+  bool OK();
+
+  void AddThreshold(cGenotype & in_genotype);
+  void RemoveThreshold(cGenotype & in_genotype);
+  void AddGenotype();
+  void RemoveGenotype();
+
+  void AddOrganisms(int in_num) { num_organisms += in_num; }
+  void ResetStats() { num_organisms = 0; }
+
+  cSpecies * GetNext() { return next; }
+  cSpecies * GetPrev() { return prev; }
+
+  int GetID() { return id_num; }
+  int GetParentID() { return parent_id; }
+  const cGenome & GetGenome() { return genome; }
+  int GetUpdateBorn() { return update_born; }
+  int GetNumGenotypes() { return num_genotypes; }
+  int GetNumThreshold() { return num_threshold; }
+  int GetNumOrganisms() { return num_organisms; }
+  int GetTotalOrganisms() { return total_organisms; }
+  int GetTotalGenotypes() { return total_genotypes; }
+  int GetQueueType() { return queue_type; }
+  char GetSymbol() { return symbol; }
+
+  void SetQueueType(int in_qt) { queue_type = in_qt; }
+  void SetNext(cSpecies * in_next) { next = in_next; }
+  void SetPrev(cSpecies * in_prev) { prev = in_prev; }
+  void SetSymbol(char in_symbol) { symbol = in_symbol; }
+  void SetParentID(int in_id) { parent_id = in_id; }
+
+#ifdef DEBUG
+  // These are used in cGenebank::OK()
+  int debug_num_genotypes;
+  int debug_num_threshold;
+#endif
+};
+
+#endif
Index: avida/current/source/main/stats.cc
diff -u /dev/null avida/current/source/main/stats.cc:1.57
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/stats.cc	Tue Nov 25 09:37:58 2003
@@ -0,0 +1,892 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef STATS_HH
+#include "stats.hh"
+#endif
+
+#ifndef CONFIG_HH
+#include "config.hh"
+#endif
+#ifndef DATA_FILE_HH
+#include "data_file.hh"
+#endif
+#ifndef FUNCTIONS_HH
+#include "functions.hh"
+#endif
+#ifndef STRING_UTIL_HH
+#include "string_util.hh"
+#endif
+#ifndef TDATAENTRY_HH
+#include "tDataEntry.hh"
+#endif
+
+using namespace std;
+
+////////////
+//  cStats
+////////////
+
+cStats::cStats()
+  : current_update(-1)
+  , sub_update(0)
+  , avida_time(0)
+  , data_manager(this, "population_data")
+  , rave_true_replication_rate( 500 )
+  , entropy(0)
+  , species_entropy(0)
+  , energy(0)
+  , dom_fidelity(0)
+  , ave_fidelity(0)
+  , max_viable_fitness(0)
+  , dom_genotype(NULL)
+  , dom_merit(0)
+  , dom_gestation(0)
+  , dom_repro_rate(0)
+  , dom_fitness(0)
+  , dom_size(0)
+  , dom_copied_size(0)
+  , dom_exe_size(0)
+  , max_fitness(0)
+  , max_merit(0)
+  , dom_genotype_id(-1)
+  , dom_name("(none)")
+  , dom_births(0)
+  , dom_breed_true(0)
+  , dom_breed_in(0)
+  , dom_breed_out(0)
+  , dom_abundance(0)
+  , dom_gene_depth(-1)
+  , dom_sequence("")
+  , coal_depth(0)
+  , num_births(0)
+  , num_deaths(0)
+  , num_breed_in(0)
+  , num_breed_true(0)
+  , num_breed_true_creatures(0)
+  , num_creatures(0)
+  , num_genotypes(0)
+  , num_threshold(0)
+  , num_species(0)
+  , num_thresh_species(0)
+  , num_lineages(0)
+  , num_executed(0)
+  , num_parasites(0)
+  , num_no_birth_creatures(0)
+  , num_genotypes_last(1)
+  , tot_organisms(0)
+  , tot_genotypes(0)
+  , tot_threshold(0)
+  , tot_species(0)
+  , tot_thresh_species(0)
+  , tot_lineages(0)
+  , tot_executed(0)
+{
+  // Open log files.
+
+  if (cConfig::GetLogCreatures()) fp_creature_log.open("creature.log");
+  else fp_creature_log.close();
+
+  if (cConfig::GetLogGenotypes()) fp_genotype_log.open("genotype.log");
+  else fp_genotype_log.close();
+
+  if (cConfig::GetLogThreshold()) fp_threshold_log.open("threshold.log");
+  else fp_threshold_log.close();
+
+  if (cConfig::GetLogSpecies())   fp_species_log.open("species.log");
+  else fp_species_log.close();
+
+  if (cConfig::GetLogLineages())  fp_lineage_log.open("lineage.log");
+  else fp_lineage_log.close();
+
+  task_cur_count.Resize( cConfig::GetNumTasks() );
+  task_last_count.Resize( cConfig::GetNumTasks() );
+  task_exe_count.Resize( cConfig::GetNumTasks() );
+  task_cur_count.SetAll(0);
+  task_last_count.SetAll(0);
+  task_exe_count.SetAll(0);
+
+#ifdef INSTRUCTION_COUNT
+  sum_exe_inst_array.Resize( cConfig::GetNumInstructions() );
+  ZeroInst();
+#endif
+  inst_names.Resize( cConfig::GetNumInstructions() );
+
+
+
+  reaction_count.Resize( cConfig::GetNumReactions() );
+  reaction_count.SetAll(0);
+
+  resource_count.Resize( cConfig::GetNumResources() );
+  resource_count.SetAll(0);
+
+  task_names.Resize( cConfig::GetNumTasks() );
+  reaction_names.Resize( cConfig::GetNumReactions() );
+  resource_names.Resize( cConfig::GetNumResources() );
+
+  genotype_map.Resize( cConfig::GetWorldX() * cConfig::GetWorldY() );
+  SetupPrintDatabase();
+}
+
+void cStats::SetupPrintDatabase()
+{
+  // Load in all the keywords, descriptions, and associated functions for
+  // data management.
+
+  // Time Stats
+  data_manager.Add("update",      "Update",      &cStats::GetUpdate);
+  data_manager.Add("sub_update",  "Sub-Update",  &cStats::GetSubUpdate);
+  data_manager.Add("generation",  "Generation",  &cStats::GetGeneration);
+
+  // Population Level Stats
+  data_manager.Add("entropy",         "Genotype Entropy (Diversity)", &cStats::GetEntropy);
+  data_manager.Add("species_entropy", "Species Entropy (Diversity)",  &cStats::GetEntropy);
+  data_manager.Add("energy",          "Average Inferiority (Energy)", &cStats::GetEnergy);
+  data_manager.Add("richness",        "Number of Different Genotypes (Richness)", &cStats::GetNumGenotypes);
+  data_manager.Add("eveness",         "Equitability of Genotype Distribution (Evenness)", &cStats::GetEvenness);
+  data_manager.Add("coal_depth",      "Depth of Coalescent Genotype", &cStats::GetCoalescentDepth);
+
+  // Dominant Genotype Stats
+  data_manager.Add("dom_merit",      "Ave Merit of Dominant Genotype",          &cStats::GetDomMerit);
+  data_manager.Add("dom_gest",       "Ave Gestation Time of Dominant Genotype", &cStats::GetDomGestation);
+  data_manager.Add("dom_fitness",    "Ave Fitness of Dominant Genotype",        &cStats::GetDomFitness);
+  data_manager.Add("dom_repro",      "Ave Repro-Rate of Dominant Genotype",     &cStats::GetDomReproRate);
+  data_manager.Add("dom_length",     "Genome Length of Dominant Genotype",      &cStats::GetDomSize);
+  data_manager.Add("dom_copy_length","Copied Length of Dominant Genotype",      &cStats::GetDomCopySize);
+  data_manager.Add("dom_exe_length", "Executed Length of Dominant Genotype",    &cStats::GetDomExeSize);
+  data_manager.Add("dom_id",         "ID of Dominant Genotype",                 &cStats::GetDomID);
+  data_manager.Add("dom_name",       "Name of Dominant Genotype",               &cStats::GetDomName);
+  data_manager.Add("dom_births",     "Birth Count of Dominant Genotype",        &cStats::GetDomBirths);
+  data_manager.Add("dom_breed_true", "Breed-True Count  of Dominant Genotype",  &cStats::GetDomBreedTrue);
+  data_manager.Add("dom_breed_in",   "Breed-In Count of Dominant Genotype",     &cStats::GetDomBreedIn);
+  data_manager.Add("dom_breed_out",  "Breed-Out Count of Dominant Genotype",    &cStats::GetDomBreedOut);
+  data_manager.Add("dom_num_cpus",   "Abundance of Dominant Genotype",          &cStats::GetDomAbundance);
+  data_manager.Add("dom_depth",      "Tree Depth of Dominant Genotype",         &cStats::GetDomGeneDepth);
+  data_manager.Add("dom_sequence",   "Sequence of Dominant Genotype",           &cStats::GetDomSequence);
+
+  // Dominant Inject Genotype Stats
+  data_manager.Add("dom_inj_size",      "Genome Length of Dominant Parasite",   &cStats::GetDomInjSize);
+  data_manager.Add("dom_inj_ID",        "ID of Dominant Parasite",              &cStats::GetDomInjID);
+  data_manager.Add("dom_inj_name",      "Nameof Dominant Parasite",             &cStats::GetDomInjName);
+  data_manager.Add("dom_inj_births",    "Birth Count of Dominant Parasite",     &cStats::GetDomInjBirths);
+  data_manager.Add("dom_inj_abundance", "Abundance of Dominant Parasite",       &cStats::GetDomInjAbundance);
+  data_manager.Add("dom_inj_sequence",  "Sequence of Dominant Parasite",        &cStats::GetDomInjSequence);
+  
+  // Current Counts...
+  data_manager.Add("num_births",     "Count of Births in Population",          &cStats::GetNumBirths);
+  data_manager.Add("num_deaths",     "Count of Deaths in Population",          &cStats::GetNumDeaths);
+  data_manager.Add("breed_in",       "Count of Non-Breed-True Births",         &cStats::GetBreedIn);
+  data_manager.Add("breed_true",     "Count of Breed-True Births",             &cStats::GetBreedTrue);
+  data_manager.Add("bred_true",      "Count of Organisms that have Bred True", &cStats::GetBreedTrueCreatures);
+  data_manager.Add("num_cpus",       "Count of Organisms in Population",       &cStats::GetNumCreatures);
+  data_manager.Add("num_genotypes",  "Count of Genotypes in Population",       &cStats::GetNumGenotypes);
+  data_manager.Add("num_threshold",  "Count of Threshold Genotypes",           &cStats::GetNumThreshold);
+  data_manager.Add("num_species",    "Count of Species in Population",         &cStats::GetNumSpecies);
+  data_manager.Add("thresh_species", "Count of Threshold Species",             &cStats::GetNumThreshSpecies);
+  data_manager.Add("num_lineages",   "Count of Lineages in Population",        &cStats::GetNumLineages);
+  data_manager.Add("num_parasites",  "Count of Parasites in Population",       &cStats::GetNumParasites);
+  data_manager.Add("num_no_birth",   "Count of Childless Organisms",           &cStats::GetNumNoBirthCreatures);
+
+  // Total Counts...
+  data_manager.Add("tot_cpus",      "Total Organisms ever in Population", &cStats::GetTotCreatures);
+  data_manager.Add("tot_genotypes", "Total Genotypes ever in Population", &cStats::GetTotGenotypes);
+  data_manager.Add("tot_threshold", "Total Threshold Genotypes Ever",     &cStats::GetTotThreshold);
+  data_manager.Add("tot_species",   "Total Species ever in Population",   &cStats::GetTotSpecies);
+  data_manager.Add("tot_lineages",  "Total Lineages ever in Population",  &cStats::GetTotLineages);
+
+  // Some Average Data...
+  data_manager.Add("ave_repro_rate", "Average Repro-Rate (1/Gestation)", &cStats::GetAveReproRate);
+  data_manager.Add("ave_merit",      "Average Merit",                    &cStats::GetAveMerit);
+  data_manager.Add("ave_age",        "Average Age",                      &cStats::GetAveCreatureAge);
+  data_manager.Add("ave_memory",     "Average Memory Used",              &cStats::GetAveMemSize);
+  data_manager.Add("ave_neutral",    "Average Neutral Metric",           &cStats::GetAveNeutralMetric);
+  data_manager.Add("ave_lineage",    "Average Lineage Label",            &cStats::GetAveLineageLabel);
+  data_manager.Add("ave_gest",       "Average Gestation Time",           &cStats::GetAveGestation);
+  data_manager.Add("ave_fitness",    "Average Fitness",                  &cStats::GetAveFitness);
+  data_manager.Add("ave_gen_age",    "Average Genotype Age",             &cStats::GetAveGenotypeAge);
+  data_manager.Add("ave_length",     "Average Genome Length",            &cStats::GetAveSize);
+  data_manager.Add("ave_copy_length","Average Copied Length",            &cStats::GetAveCopySize);
+  data_manager.Add("ave_exe_length", "Average Executed Length",          &cStats::GetAveExeSize);
+  data_manager.Add("ave_thresh_age", "Average Threshold Genotype Age",   &cStats::GetAveThresholdAge);
+  data_manager.Add("ave_species_age","Average Species Age",              &cStats::GetAveSpeciesAge);
+
+  // And a couple of Maximums
+  data_manager.Add("max_fitness", "Maximum Fitness in Population", &cStats::GetMaxFitness);
+  data_manager.Add("max_merit",   "Maximum Merit in Population",   &cStats::GetMaxMerit);
+}
+
+cStats::~cStats()
+{
+  cout << "Closing stats object..."<<endl;
+
+  // Close all the statistics files.
+
+  data_file_manager.FlushAll();
+
+  fp_creature_log.close();
+  fp_genotype_log.close();
+  fp_threshold_log.close();
+  fp_species_log.close();
+  fp_lineage_log.close();
+}
+
+void cStats::ZeroTasks()
+{
+  for( int i=0; i < task_cur_count.GetSize(); i++ ){
+    task_cur_count[i] = 0;
+    task_last_count[i] = 0;
+  }
+}
+
+
+#ifdef INSTRUCTION_COUNT
+void cStats::ZeroInst()
+{
+  for( int i=0; i < sum_exe_inst_array.GetSize(); i++ ){
+    sum_exe_inst_array[i].Clear();
+  }
+}
+#endif
+
+void cStats::CalcEnergy()
+{
+  assert(sum_fitness.Average() >= 0.0);
+  assert(dom_fitness >= 0);
+
+  if (sum_fitness.Average() == 0.0 || dom_fitness == 0.0) {
+    energy = 0.0;
+  } else  {
+    energy = Log(dom_fitness / sum_fitness.Average());
+  }
+}
+
+void cStats::CalcFidelity()
+{
+  // There is a (small) probability that when a random instruction is picked
+  // after a mutation occurs, that it will be the original instruction again;
+  // This needs to be adjusted for!
+
+  double adj = ((double) (cConfig::GetNumInstructions() - 1)) /
+    (double) cConfig::GetNumInstructions();
+
+  double base_fidelity = (1.0 - adj * cConfig::GetDivideMutProb()) *
+    (1.0 - cConfig::GetDivideInsProb()) * (1.0 - cConfig::GetDivideDelProb());
+
+  double true_cm_rate = adj * cConfig::GetCopyMutProb();
+  ave_fidelity = base_fidelity * pow(1.0 - true_cm_rate, sum_size.Average());
+  dom_fidelity = base_fidelity * pow(1.0 - true_cm_rate, dom_size);
+}
+
+void cStats::RecordBirth(int cell_id, int genotype_id, bool breed_true)
+{
+  tot_organisms++;
+  num_births++;
+  if (fp_creature_log.good() == true) {
+    fp_creature_log << GetUpdate()   << " "
+		    << cell_id       << " "
+		    << genotype_id   << endl;
+  }
+
+  if (breed_true == true) num_breed_true++;
+  else num_breed_in++;
+}
+
+
+void cStats::RecordDeath(int cell_id, int genotype_id, int age)
+{
+  num_deaths++;
+}
+
+void cStats::AddGenotype(int id_num)
+{
+  id_num = -1;  // @CAO do we still need id_num here?
+  tot_genotypes++;
+}
+
+void cStats::RemoveGenotype(int id_num, int parent_id,
+   int parent_dist, int depth, int max_abundance, int parasite_abundance,
+   int age, int length)
+{
+  if (fp_genotype_log.good() &&
+      (!cConfig::GetLogThresholdOnly() || max_abundance > 2)) {
+    const int update_born = cStats::GetUpdate() - age + 1;
+    fp_genotype_log << id_num             << " "    //  1
+		    << update_born        << " "    //  2
+		    << parent_id          << " "    //  3
+		    << parent_dist        << " "    //  4
+		    << depth              << " "    //  5
+		    << max_abundance      << " "    //  6
+		    << age                << " "    //  7
+		    << length             << endl;  //  8
+  }
+
+  (void) parasite_abundance; // Not used now, but maybe in future.
+}
+
+void cStats::AddThreshold(int id_num, const char * name, int species_num)
+{
+  num_threshold++;
+  tot_threshold++;
+  if( fp_threshold_log.good() )
+    fp_threshold_log << cStats::GetUpdate() << " "   // 1
+		     << id_num              << " "   // 2
+		     << species_num         << " "   // 3
+		     << name                << endl; // 4
+}
+
+void cStats::RemoveThreshold(int id_num)
+{
+  id_num = -1;  // @CAO do we still need id_num here?
+  num_threshold--;
+}
+
+void cStats::AddSpecies(int id_num)
+{
+  id_num = -1; // @CAO do we still need id_num here?
+  tot_species++;
+  num_species++;
+}
+
+void cStats::RemoveSpecies(int id_num, int parent_id,
+			   int max_gen_abundance, int max_abundance, int age)
+{
+  num_species--;
+  if( fp_species_log.good() )
+    fp_species_log << cStats::GetUpdate() << " "   // 1
+		   << id_num              << " "   // 2
+		   << parent_id           << " "   // 3
+		   << max_gen_abundance   << " "   // 4
+		   << max_abundance       << " "   // 5
+		   << age                 << endl; // 6
+}
+
+void cStats::AddLineage()
+{
+  tot_lineages++;
+  num_lineages++;
+}
+
+void cStats::ProcessUpdate()
+{
+  static int last_update = 0;
+
+  // Increment the "avida_time"
+  if (sum_merit.Count() > 0 && sum_merit.Average() > 0) {
+    double delta = ((double)(current_update-last_update))/sum_merit.Average();
+    avida_time += delta;
+
+    // calculate the true replication rate in this update
+    rave_true_replication_rate.Add( num_births/
+	  (delta * cConfig::GetAveTimeslice() * num_creatures) );
+  }
+  last_update = current_update;
+
+  // Zero-out any variables which need to be cleared at end of update.
+
+  num_births = 0;
+  num_deaths = 0;
+  num_breed_true = 0;
+
+  tot_executed += num_executed;
+  num_executed = 0;
+
+  task_cur_count.SetAll(0);
+  task_last_count.SetAll(0);
+  task_exe_count.SetAll(0);
+
+  dom_merit = 0;
+  dom_gestation = 0.0;
+  dom_fitness = 0.0;
+  max_fitness = 0.0;
+}
+
+
+void cStats::FlushFP(){
+  data_file_manager.FlushAll();
+
+  fp_creature_log.flush();
+  fp_genotype_log.flush();
+  fp_threshold_log.flush();
+  fp_species_log.flush();
+  fp_lineage_log.flush();
+}
+
+
+void cStats::RemoveLineage(int id_num, int parent_id, int update_born,
+			   double generation_born,
+			   int total_CPUs, int total_genotypes, double fitness,
+			   double lineage_stat1, double lineage_stat2 )
+{
+  static bool msg_printed = false;
+
+  if ( !msg_printed ){
+    if( fp_lineage_log.good() )
+      fp_lineage_log << "# (1) lineage id "
+		     << "(2) parent lineage id "
+		     << "(3) initial fitness "
+		     << "(4) total number of creatures "
+		     << "(5) total number of genotypes "
+		     << "(6) update born "
+		     << "(7) update extinct "
+		     << "(8) generation born "
+		     << "(9) generation extinct"
+		     << "(10) lineage stat1"
+		     << "(11) lineage stat2 [10, 11 depend on lineage creation method chosen]"
+		     << endl;
+    msg_printed = true;
+  }
+
+  num_lineages--;
+  if( fp_lineage_log.good() ) {
+    fp_lineage_log << id_num              << " "   // 1
+		   << parent_id           << " "   // 2
+		   << fitness             << " "   // 3
+		   << total_CPUs          << " "   // 4
+		   << total_genotypes     << " "   // 5
+		   << update_born         << " "   // 6
+		   << cStats::GetUpdate() << " "   // 7
+		   << generation_born     << " "   // 8
+		   << SumGeneration().Average() << " " // 9
+		   << lineage_stat1 	  << " "   // 10
+		   << lineage_stat2       << " " << endl;
+  }
+}
+
+
+void cStats::PrintDataFile(const cString & filename, const cString & format,
+			   char sep)
+{
+  cDataFile & data_file = GetDataFile(filename);
+  data_manager.PrintRow(data_file, format, sep);
+}
+
+
+void cStats::PrintAverageData(const cString & filename)
+{
+  cDataFile & df = GetDataFile(filename);
+
+  df.WriteComment( "Avida average data" );
+  df.WriteTimeStamp();
+
+  df.Write(GetUpdate(),                    "update" );
+  df.Write(sum_merit.Average(),            "average merit" );
+  df.Write(sum_gestation.Average(),        "average gestation time" );
+  df.Write(sum_fitness.Average(),          "average fitness" );
+  df.Write(sum_repro_rate.Average(),       "repro rate?" );
+  df.Write(sum_size.Average(),             "average size" );
+  df.Write(sum_copy_size.Average(),        "average copied size" );
+  df.Write(sum_exe_size.Average(),         "average executed size"  );
+  df.Write(sum_abundance.Average(),        "average abundance?" );
+  df.Write((double)num_births/num_creatures,
+	   "proportion of organisms that gave birth in this update" );
+  df.Write((double)num_breed_true/num_creatures,
+	   "proportion of breed true organisms" );
+  df.Write(sum_genotype_depth.Average(),   "average genotype depth" );
+  df.Write(sum_generation.Average(),       "average generation" );
+  df.Write(sum_neutral_metric.Average(),   "average neutral metric" );
+  df.Write(sum_lineage_label.Average(),    "average lineage label" );
+  df.Write(rave_true_replication_rate.Average(),
+	   "true replication rate (based on births/update, time-averaged)");
+  df.Endl();
+}
+
+
+void cStats::PrintErrorData(const cString & filename)
+{
+  ofstream & fp = GetDataFileOFStream(filename);
+  assert(fp.good());
+  fp<< GetUpdate()                          << " "  // 1
+    << sum_merit.StdError()                 << " "  // 2
+    << sum_gestation.StdError()             << " "  // 3
+    << sum_fitness.StdError()               << " "  // 4
+    << sum_repro_rate.StdError()            << " "  // 5
+    << sum_size.StdError()                  << " "  // 6
+    << sum_copy_size.StdError()             << " "  // 7
+    << sum_exe_size.StdError()              << " "  // 8
+    << sum_abundance.StdError()             << " "  // 9
+    << -1                                   << " "  // 10
+    << -1                                   << " "  // 11
+    << sum_genotype_depth.StdError()        << " "  // 12
+    << sum_generation.StdError()            << " "  // 15
+    << sum_neutral_metric.StdError()        << " "  // 16
+    << sum_lineage_label.StdError()         << endl;// 17
+}
+
+
+void cStats::PrintVarianceData(const cString & filename)
+{
+  ofstream & fp = GetDataFileOFStream(filename);
+  assert(fp.good());
+  fp<<GetUpdate()                           << " "  // 1
+    << sum_merit.Variance()                 << " "  // 2
+    << sum_gestation.Variance()             << " "  // 3
+    << sum_fitness.Variance()               << " "  // 4
+    << sum_repro_rate.Variance()            << " "  // 5
+    << sum_size.Variance()                  << " "  // 6
+    << sum_copy_size.Variance()             << " "  // 7
+    << sum_exe_size.Variance()              << " "  // 8
+    << sum_abundance.Variance()             << " "  // 9
+    << -1                                   << " "  // 10
+    << -1                                   << " "  // 11
+    << sum_genotype_depth.Variance()        << " "  // 12
+    << sum_generation.Variance()            << " "  // 15
+    << sum_neutral_metric.Variance()        << " "  // 16
+    << sum_lineage_label.Variance()         << " "  // 17
+    << rave_true_replication_rate.Variance()<< endl;// 18
+}
+
+
+void cStats::PrintDominantData(const cString & filename)
+{
+  cDataFile & df = GetDataFile(filename);
+
+  df.WriteComment( "Avida dominant data" );
+  df.WriteTimeStamp();
+
+  df.Write( GetUpdate(),     "update" );
+  df.Write( dom_merit,       "average merit of dominant genotype" );
+  df.Write( dom_gestation,   "average gestation time of dominant" );
+  df.Write( dom_fitness,     "average fitness of dominant genotype" );
+  df.Write( dom_repro_rate,  "repro rate?" );
+  df.Write( dom_size,        "size of dominant genotype" );
+  df.Write( dom_copied_size, "copied size of dominant genotype" );
+  df.Write( dom_exe_size,    "executed size of dominant genotype" );
+  df.Write( dom_abundance,   "abundance of dominant genotype" );
+  df.Write( dom_births,      "number of births" );
+  df.Write( dom_breed_true,  "number of dominant breed true?" );
+  df.Write( dom_gene_depth,  "dominant gene depth" );
+  df.Write( dom_breed_in,    "dominant breed in");
+  df.Write( max_fitness,     "max fitness?" );
+  df.Write( dom_genotype_id, "genotype ID of dominant genotype" );
+  df.Write( dom_name,        "name of dominant genotype" );
+  df.Endl();
+}
+
+void cStats::PrintDominantParaData(const cString & filename)
+{
+  cDataFile & df = GetDataFile(filename);
+
+  df.WriteComment( "Avida dominant parasite data" );
+  df.WriteTimeStamp();
+
+  df.Write( GetUpdate(),     "update" );
+  df.Write( dom_inj_size,        "size of dominant genotype" );
+  df.Write( dom_inj_abundance,   "abundance of dominant genotype" );
+  df.Write( dom_inj_genotype_id, "genotype ID of dominant genotype" );
+  df.Write( dom_inj_name,        "name of dominant genotype" );
+  df.Endl();
+}
+
+void cStats::PrintStatsData(const cString & filename)
+{
+  const int genotype_change = num_genotypes - num_genotypes_last;
+  const double log_ave_fid = (ave_fidelity > 0) ? -Log(ave_fidelity) : 0.0;
+  const double log_dom_fid = (dom_fidelity > 0) ? -Log(dom_fidelity) : 0.0;
+
+  cDataFile & df = GetDataFile(filename);
+
+  df.WriteComment( "Generic Statistics Data" );
+  df.WriteTimeStamp();
+
+  df.Write( GetUpdate(),        "update" );
+  df.Write( energy,             "average inferiority (energy)");
+  df.Write( 1.0 - ave_fidelity, "ave probability of any mutations in genome" );
+  df.Write( 1.0 - dom_fidelity, "probability of any mutations in dom genome" );
+  df.Write( log_ave_fid,        "log(average fidelity)");
+  df.Write( log_dom_fid,        "log(dominant fidelity)");
+  df.Write( genotype_change,    "change in number of genotypes");
+  df.Write( entropy,            "genotypic entropy");
+  df.Write( species_entropy,    "species entropy");
+  df.Write( coal_depth,         "depth of most reacent coalescence");
+  df.Endl();
+}
+
+
+void cStats::PrintCountData(const cString & filename)
+{
+  cDataFile & df = GetDataFile(filename);
+
+  df.WriteComment( "Avida count data" );
+  df.WriteTimeStamp();
+
+  df.Write( GetUpdate(),            "update");
+  df.Write( num_executed,           "number of insts executed this update");
+  df.Write( num_creatures,          "number of organisms");
+  df.Write( num_genotypes,          "number of different genotypes");
+  df.Write( num_threshold,          "number of different threshold genotypes");
+  df.Write( num_species,            "number of different species");
+  df.Write( num_thresh_species,     "number of different threshold species");
+  df.Write( num_lineages,           "number of different lineages");
+  df.Write( num_births,             "number of births in this update");
+  df.Write( num_deaths,             "number of deaths in this update");
+  df.Write( num_breed_true,         "number of breed true");
+  df.Write( num_breed_true_creatures, "number of breed true organisms?");
+  //df.Write( num_parasites,            "number of parasites");
+  df.Write( num_no_birth_creatures,   "number of no-birth organisms");
+  df.Write( num_single_thread_creatures, "number of single-threaded organisms");
+  df.Write( num_multi_thread_creatures, "number of multi-threaded organisms");
+  df.Write( num_modified, "number of modified organisms");
+  df.Endl();
+}
+
+
+void cStats::PrintTotalsData(const cString & filename)
+{
+  ofstream & fp = GetDataFileOFStream(filename);
+  assert(fp.good());
+  fp << GetUpdate()                  << " " // 1
+     << (tot_executed+num_executed)  << " " // 2
+     << num_executed            << " " // 3
+     << tot_organisms                << " " // 4
+     << tot_genotypes                << " " // 5
+     << tot_threshold                << " " // 6
+     << tot_species                  << " " // 7
+     << tot_lineages                 << endl; // 8
+}
+
+
+void cStats::PrintTasksData(const cString & filename)
+{
+  cDataFile & df = GetDataFile(filename);
+
+  df.WriteComment( "Avida tasks data" );
+  df.WriteTimeStamp();
+  df.WriteComment( "First column gives the current update, all further columns give the number" );
+  df.WriteComment( "of organisms that have the particular task as a component of the merit." );
+
+
+  df.Write( GetUpdate(),   "Update");
+  for(int i = 0; i < task_last_count.GetSize(); i++) {
+    df.Write( task_last_count[i], task_names[i] );
+  }
+  df.Endl();
+}
+
+
+void cStats::PrintTasksExeData(const cString & filename)
+{
+  cDataFile & df = GetDataFile(filename);
+
+  df.WriteComment( "Avida tasks data" );
+  df.WriteTimeStamp();
+  df.WriteComment( "First column gives the current update, all further columns give the number" );
+  df.WriteComment( "of times the particular task has been executed this update." );
+
+  df.Write( GetUpdate(),   "Update");
+  for (int i = 0; i < task_exe_count.GetSize(); i++) {
+    df.Write( task_exe_count[i], task_names[i] );
+    task_exe_count[i] = 0;
+  }
+  df.Endl();
+}
+
+
+void cStats::PrintReactionData(const cString & filename)
+{
+  cDataFile & df = GetDataFile(filename);
+
+  df.WriteComment( "Avida tasks data" );
+  df.WriteTimeStamp();
+  df.WriteComment( "First column gives the current update, all further columns give the number" );
+  df.WriteComment( "of currently living organisms each reaction has affected." );
+
+  df.Write( GetUpdate(),   "Update");
+  for (int i = 0; i < reaction_count.GetSize(); i++) {
+    df.Write( reaction_count[i], reaction_names[i] );
+    task_exe_count[i] = 0;
+  }
+  df.Endl();
+}
+
+void cStats::PrintResourceData(const cString & filename)
+{
+  cDataFile & df = GetDataFile(filename);
+
+  df.WriteComment( "Avida resource data" );
+  df.WriteTimeStamp();
+  df.WriteComment( "First column gives the current update, all further columns give the quantity" );
+  df.WriteComment( "of the particular resource at that update." );
+
+  df.Write( GetUpdate(),   "Update");
+  for (int i = 0; i < resource_count.GetSize(); i++) {
+    df.Write( resource_count[i], resource_names[i] );
+    if (resource_geometry[i] != GEOMETRY_GLOBAL) {
+      PrintSpatialResData(filename, i);
+    }
+  }
+  df.Endl();
+}
+
+void cStats::PrintSpatialResData(const cString & filename, int i)
+{
+
+  // Write spatial data to a file that can easily be read into Matlab
+
+  cString tmpfilename = "resource_";
+  tmpfilename +=  resource_names[i] + ".m";
+  cDataFile & df = GetDataFile(tmpfilename);
+  cString UpdateStr = resource_names[i] + 
+                      cStringUtil::Stringf( "%07i", GetUpdate() ) + " = [ ...";
+
+  df.WriteRaw(UpdateStr);
+
+  int gridsize = spatial_res_count[i].GetSize();
+  int xsize = cConfig::GetWorldX();
+
+  // write grid to file
+
+  for (int j = 0; j < gridsize; j++) {
+    df.WriteBlockElement(spatial_res_count[i][j], j, xsize);
+  }
+  df.WriteRaw("];");
+}
+
+
+void cStats::PrintTimeData(const cString & filename)
+{
+  cDataFile & df = GetDataFile(filename);
+
+  df.WriteComment( "Avida time data" );
+  df.WriteTimeStamp();
+
+  df.Write( GetUpdate(),              "update" );
+  df.Write( avida_time,               "avida time" );
+  df.Write( sum_generation.Average(), "average generation" );
+  df.Write( num_executed,             "num_executed?" );
+  df.Endl();
+}
+
+
+void cStats::PrintMutationData(const cString & filename)
+{
+  ofstream & fp = GetDataFileOFStream(filename);
+  assert(fp.good());
+  fp << GetUpdate()                              << " "   //  1
+     << isum_parent_dist.Ave()                   << " "   //  2
+     << isum_parent_size.Ave()                   << " "   //  3
+     << isum_child_size.Ave()                    << " "   //  4
+     << isum_copied_size.Ave()                   << " "   //  5
+     << isum_executed_size.Ave()                 << " "   //  6
+     << isum_copies_exec.Ave()                   << " "   //  7
+     << isum_point_mut.Ave()                     << " "   //  8
+     << isum_copy_mut.Ave()                      << " "   //  9
+     << isum_insert_mut.Ave()                    << " "   // 10
+     << isum_delete_mut.Ave()                    << " "   // 11
+     << isum_point_mut_line.Ave()                << " "   // 12
+     << isum_copy_mut_line.Ave()                 << " "   // 13
+     << isum_divide_mut.Ave()                    << " "   // 14
+     << isum_divide_insert_mut.Ave()             << " "   // 15
+     << isum_divide_delete_mut.Ave()             << " "   // 16
+     << dsum_copy_mut_by_copies_exec.Ave()       << " "   // 17
+     << dsum_copied_size_by_copies_exec.Ave()    << " "   // 18
+     << dsum_copy_mut_lines_by_copied_size.Ave() << " "   // 19
+     << dsum_copy_mut_lines_by_copy_mut.Ave()    << endl; // 20
+
+  isum_parent_dist.Clear();
+  isum_parent_size.Clear();
+  isum_child_size.Clear();
+  isum_point_mut.Clear();
+  isum_copy_mut.Clear();
+  isum_insert_mut.Clear();
+  isum_point_mut_line.Clear();
+  isum_copy_mut_line.Clear();
+  isum_delete_mut.Clear();
+  isum_divide_mut.Clear();
+  isum_divide_insert_mut.Clear();
+  isum_divide_delete_mut.Clear();
+  isum_copied_size.Clear();
+  isum_executed_size.Clear();
+  isum_copies_exec.Clear();
+  dsum_copy_mut_by_copies_exec.Clear();
+  dsum_copied_size_by_copies_exec.Clear();
+  dsum_copy_mut_lines_by_copied_size.Clear();
+  dsum_copy_mut_lines_by_copy_mut.Clear();
+}
+
+void cStats::PrintMutationRateData(const cString & filename)
+{
+  cDataFile & df = GetDataFile(filename);
+
+  df.WriteComment( "Avida copy mutation rate data" );
+  df.WriteTimeStamp();
+
+  df.Write( GetUpdate(),              "Update" );
+  df.Write( sum_copy_mut_rate.Ave(),  "Average copy mutation rate" );
+  df.Write( sum_copy_mut_rate.Var(),  "Variance in copy mutation rate" );
+  df.Write( sum_copy_mut_rate.StdDeviation(),  "Standard Deviation in copy mutation rate" );
+  df.Write( sum_copy_mut_rate.Skw(),  "Skew in copy mutation rate" );
+  df.Write( sum_copy_mut_rate.Kur(),  "Kurtosis in copy mutation rate" );
+
+  df.Write( sum_log_copy_mut_rate.Ave(),  "Average log(copy mutation rate)" );
+  df.Write( sum_log_copy_mut_rate.Var(),  "Variance in log(copy mutation rate)" );
+  df.Write( sum_log_copy_mut_rate.StdDeviation(),  "Standard Deviation in log(copy mutation rate)" );
+  df.Write( sum_log_copy_mut_rate.Skw(),  "Skew in log(copy mutation rate)" );
+  df.Write( sum_log_copy_mut_rate.Kur(),  "Kurtosis in log(copy mutation rate)" );
+  df.Endl();
+
+}
+
+
+void cStats::PrintDivideMutData(const cString & filename)
+{
+  cDataFile & df = GetDataFile(filename);
+
+  df.WriteComment( "Avida divide mutation rate data" );
+  df.WriteTimeStamp();
+
+  df.Write( GetUpdate(),              "Update" );
+  df.Write( sum_div_mut_rate.Ave(),  "Average divide mutation rate" );
+  df.Write( sum_div_mut_rate.Var(),  "Variance in divide mutation rate" );
+  df.Write( sum_div_mut_rate.StdDeviation(),  "Standard Deviation in divide mutation rate" );
+  df.Write( sum_div_mut_rate.Skw(),  "Skew in divide mutation rate" );
+  df.Write( sum_div_mut_rate.Kur(),  "Kurtosis in divide mutation rate" );
+
+  df.Write( sum_log_div_mut_rate.Ave(),  "Average log(divide mutation rate)" );
+  df.Write( sum_log_div_mut_rate.Var(),  "Variance in log(divide mutation rate)" );
+  df.Write( sum_log_div_mut_rate.StdDeviation(),  "Standard Deviation in log(divide mutation rate)" );
+  df.Write( sum_log_div_mut_rate.Skw(),  "Skew in log(divide mutation rate)" );
+  df.Write( sum_log_div_mut_rate.Kur(),  "Kurtosis in log(divide mutation rate)" );
+  df.Endl();
+
+}
+
+void cStats::PrintInstructionData(const cString & filename)
+{
+  cDataFile & df = GetDataFile(filename);
+
+  df.WriteComment( "Avida instruction execution data" );
+  df.WriteTimeStamp();
+
+#ifdef INSTRUCTION_COUNT
+  df.Write( GetUpdate(),              "Update" );
+  for( int i=0; i < sum_exe_inst_array.GetSize(); i++ ){
+    df.Write( (int) sum_exe_inst_array[i].Sum(), inst_names[i] );
+  }
+#else // INSTRUCTION_COUNT undefined
+  cerr<<"Warning: Instruction Counts not compiled in"<<endl;
+#endif // ifdef INSTRUCTION_COUNT
+
+  df.Endl();
+}
+
+void cStats::PrintGenotypeMap(const cString & filename)
+{
+  cDataFile & df = cStats::GetDataFile(filename);
+  cString UpdateStr =
+    cStringUtil::Stringf( "GenoID%07i", GetUpdate() ) + " = [ ...";
+  df.WriteRaw(UpdateStr);
+
+  int gridsize = genotype_map.GetSize();
+  int xsize = cConfig::GetWorldX();
+
+  // write grid to file                                        
+
+  for (int i = 0; i < gridsize; i++) {
+    df.WriteBlockElement(genotype_map[i],i,xsize);
+  }
+  df.WriteRaw("];");
+}
Index: avida/current/source/main/stats.hh
diff -u /dev/null avida/current/source/main/stats.hh:1.51
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/main/stats.hh	Tue Nov 25 09:37:58 2003
@@ -0,0 +1,595 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2002 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef STATS_HH
+#define STATS_HH
+
+#include <assert.h>
+#include <fstream>
+#include <iostream>
+
+#ifndef DATA_FILE_MANAGER_HH
+#include "data_file_manager.hh"
+#endif
+#ifndef DOUBLE_SUM_HH
+#include "double_sum.hh"
+#endif
+#ifndef FUNCTIONS_HH
+#include "functions.hh"
+#endif
+#ifndef INT_SUM_HH
+#include "int_sum.hh"
+#endif
+#ifndef RUNNING_AVERAGE_HH
+#include "running_average.hh"
+#endif
+#ifndef TARRAY_HH
+#include "tArray.hh"
+#endif
+#ifndef TDATAMANAGER_HH
+#include "tDataManager.hh"
+#endif
+
+#define GEOMETRY_GLOBAL 0
+#define GEOMETRY_GRID   1
+#define GEOMETRY_TORUS  2
+
+template <class T> class tDataManager; // aggregate
+class cDataFileManager; // aggregate
+class cDoubleSum; // aggregate
+class cRunningAverage; // aggregate
+class cIntSum; // aggregate
+template <class T> class tArray; // aggregate
+class cGenotype;
+class cString; // aggregate
+class cInjectGenotype;
+class cDataFile;
+
+class cStats {
+private:
+  // Time scales...
+  int current_update;
+  int sub_update;
+  double avida_time;
+
+  // The data manager handles printing user-formated output files.
+  tDataManager<cStats> data_manager;
+
+  // Log files are recorded every time a specified event occurs.
+  cDataFileManager data_file_manager;
+
+  std::ofstream fp_creature_log;
+  std::ofstream fp_genotype_log;
+  std::ofstream fp_threshold_log;
+  std::ofstream fp_species_log;
+  std::ofstream fp_lineage_log;
+
+
+  //// By Creature Sums ////  (Cleared and resummed by population each update)
+  cDoubleSum sum_merit;
+  cDoubleSum sum_mem_size;
+  cDoubleSum sum_creature_age;
+  cDoubleSum sum_generation;
+
+  cDoubleSum sum_neutral_metric;
+  cDoubleSum sum_lineage_label;
+
+  cDoubleSum sum_copy_mut_rate;
+  cDoubleSum sum_log_copy_mut_rate;
+
+  cDoubleSum sum_div_mut_rate;
+  cDoubleSum sum_log_div_mut_rate;
+
+  //// By Genotype Sums ////  (Cleared and resummed by population each update)
+
+  cDoubleSum sum_gestation;
+  cDoubleSum sum_fitness;
+  cDoubleSum sum_repro_rate;
+
+  // calculates a running average over the actual replication rate
+  // given by the number of births per update
+  cRunningAverage rave_true_replication_rate;
+
+  cDoubleSum sum_size;
+  cDoubleSum sum_copy_size;
+  cDoubleSum sum_exe_size;
+
+  cDoubleSum sum_genotype_age;
+
+  // breed/geneological stats
+  cDoubleSum sum_abundance;
+  cDoubleSum sum_genotype_depth;
+
+
+  //// By Threshold Sums ////  (Cleared and resummed by population each update)
+
+  cDoubleSum sum_threshold_age;
+
+
+  //// By Species Sums ////  (Cleared and resummed by population each update)
+
+  cDoubleSum sum_species_age;
+
+
+  //// Sums cleard on output only ////
+  cIntSum isum_parent_dist;
+  cIntSum isum_parent_size;
+  cIntSum isum_child_size;
+  cIntSum isum_point_mut;
+  cIntSum isum_copy_mut;
+  cIntSum isum_insert_mut;
+  cIntSum isum_point_mut_line;
+  cIntSum isum_copy_mut_line;
+  cIntSum isum_delete_mut;
+  cIntSum isum_divide_mut;
+  cIntSum isum_divide_insert_mut;
+  cIntSum isum_divide_delete_mut;
+  cIntSum isum_copied_size;
+  cIntSum isum_executed_size;
+  cIntSum isum_copies_exec;
+  cDoubleSum dsum_copy_mut_by_copies_exec;
+  cDoubleSum dsum_copied_size_by_copies_exec;
+  cDoubleSum dsum_copy_mut_lines_by_copied_size;
+  cDoubleSum dsum_copy_mut_lines_by_copy_mut;
+
+  // Instruction Counts (DM)
+  tArray<cIntSum> sum_exe_inst_array;
+
+
+  // Calculated stats
+  double entropy;
+  double species_entropy;
+  double energy;
+  double dom_fidelity;
+  double ave_fidelity;
+
+  // For tracking of advantageous mutations
+  double max_viable_fitness;
+
+  // Dominant Genotype
+  cGenotype * dom_genotype;
+  double dom_merit;
+  double dom_gestation;
+  double dom_repro_rate;
+  double dom_fitness;
+  int dom_size;
+  double dom_copied_size;
+  double dom_exe_size;
+  double max_fitness;
+  double max_merit;
+  int dom_genotype_id;
+  cString dom_name;
+  int dom_births;
+  int dom_breed_true;
+  int dom_breed_in;
+  int dom_breed_out;
+  int dom_abundance;
+  int dom_gene_depth;
+  cString dom_sequence;
+  int coal_depth;
+
+  // Dominant Parasite
+  cInjectGenotype * dom_inj_genotype;
+  int dom_inj_size;
+  int dom_inj_genotype_id;
+  cString dom_inj_name;
+  int dom_inj_births;
+  int dom_inj_abundance;
+  cString dom_inj_sequence;
+
+  int num_births;
+  int num_deaths;
+  int num_breed_in;
+  int num_breed_true;
+  int num_breed_true_creatures;
+  int num_creatures;
+  int num_genotypes;
+  int num_threshold;
+  int num_species;
+  int num_thresh_species;
+  int num_lineages;
+  int num_executed;
+  int num_parasites;
+  int num_no_birth_creatures;
+  int num_single_thread_creatures;
+  int num_multi_thread_creatures;
+  int num_modified;
+
+  int num_genotypes_last;
+
+  int tot_organisms;
+  int tot_genotypes;
+  int tot_threshold;
+  int tot_species;
+  int tot_thresh_species;
+  int tot_lineages;
+  int tot_executed;
+  
+  tArray<int> genotype_map;
+
+  tArray<int> task_cur_count;
+  tArray<int> task_last_count;
+  tArray<int> task_exe_count;
+
+  tArray<double> reaction_count;
+  tArray<double> resource_count;
+  tArray<int> resource_geometry;
+  tArray< tArray<double> > spatial_res_count;
+
+  tArray<cString> task_names;
+  tArray<cString> inst_names;
+  tArray<cString> reaction_names;
+  tArray<cString> resource_names;
+
+public:
+  cStats();
+  ~cStats();
+
+  void SetupPrintDatabase();
+
+  void ProcessUpdate();
+
+
+  // GLOBAL STATS
+
+  inline void SetCurrentUpdate(int new_update) {
+    current_update = new_update;
+    sub_update = 0;
+  }
+
+  inline void IncCurrentUpdate() {
+    current_update++;
+    sub_update = 0;
+  }
+
+  void IncSubUpdate() { sub_update++; }
+
+  bool OK() { return true; }  // @CAO FIX!!!!
+
+  void FlushFP(); // Flush all the files
+
+  // Accessors...
+  int GetUpdate() const { return current_update; }
+  int GetSubUpdate() const { return sub_update; }
+  double GetGeneration() const { return SumGeneration().Average(); }
+
+  cGenotype * GetDomGenotype() const { return dom_genotype; }
+  double GetDomMerit() const { return dom_merit; }
+  double GetDomGestation() const { return dom_gestation; }
+  double GetDomReproRate() const { return dom_repro_rate; }
+  double GetDomFitness() const { return dom_fitness; }
+  double GetDomCopySize() const { return dom_copied_size; }
+  double GetDomExeSize() const { return dom_exe_size; }
+
+  int GetDomSize() const { return dom_size; }
+  int GetDomID() const { return dom_genotype_id; }
+  const cString & GetDomName() const { return dom_name; }
+  int GetDomBirths() const { return dom_births; }
+  int GetDomBreedTrue() const { return dom_breed_true; }
+  int GetDomBreedIn() const { return dom_breed_in; }
+  int GetDomBreedOut() const { return dom_breed_out; }
+  int GetDomAbundance() const { return dom_abundance; }
+  int GetDomGeneDepth() const { return dom_gene_depth; }
+  const cString & GetDomSequence() const { return dom_sequence; }
+
+  cInjectGenotype * GetDomInjGenotype() const { return dom_inj_genotype; }
+  int GetDomInjSize() const { return dom_inj_size; }
+  int GetDomInjID() const { return dom_inj_genotype_id; }
+  const cString & GetDomInjName() const { return dom_inj_name; }
+  int GetDomInjBirths() const { return dom_inj_births; }
+  int GetDomInjAbundance() const { return dom_inj_abundance; }
+  const cString & GetDomInjSequence() const { return dom_inj_sequence; }
+
+  // Settings...
+  void SetDomGenotype(cGenotype * in_gen) { dom_genotype = in_gen; }
+  void SetDomMerit(double in_merit) { dom_merit = in_merit; }
+  void SetDomGestation(double in_gest) { dom_gestation = in_gest; }
+  void SetDomReproRate(double in_rate) { dom_repro_rate = in_rate; }
+  void SetDomFitness(double in_fit) { dom_fitness = in_fit; }
+  void SetDomCopiedSize(double in_size) { dom_copied_size = in_size; }
+  void SetDomExeSize(double in_size) { dom_exe_size = in_size; }
+
+  void SetDomSize(int in_size) { dom_size = in_size; }
+  void SetDomID(int in_id) { dom_genotype_id = in_id; }
+  void SetDomName(const cString & in_name) { dom_name = in_name; }
+  void SetDomBirths(int in_births) { dom_births = in_births; }
+  void SetDomBreedTrue(int in_bt) { dom_breed_true = in_bt; }
+  void SetDomBreedIn(int in_bi) { dom_breed_in = in_bi; }
+  void SetDomBreedOut(int in_bo) { dom_breed_out = in_bo; }
+  void SetDomAbundance(int in_abund) { dom_abundance = in_abund; }
+  void SetDomGeneDepth(int in_depth) { dom_gene_depth = in_depth; }
+  void SetDomSequence(const cString & in_seq) { dom_sequence = in_seq; }
+
+  void SetDomInjGenotype(cInjectGenotype * in_inj_genotype) 
+  {dom_inj_genotype = in_inj_genotype;}
+  void SetDomInjSize(int in_inj_size)
+  {dom_inj_size = in_inj_size;}
+  void SetDomInjID(int in_inj_ID)
+  {dom_inj_genotype_id = in_inj_ID;}
+  void SetDomInjName(const cString & in_name)
+  {dom_inj_name = in_name;}
+  void SetDomInjBirths(int in_births)
+  {dom_inj_births=in_births;}
+  void SetDomInjAbundance(int in_inj_abundance)
+  {dom_inj_abundance=in_inj_abundance;}
+  void SetDomInjSequence(const cString & in_inj_sequence)
+  {dom_inj_sequence = in_inj_sequence;}
+
+  void SetGenoMapElement(int i, int in_geno) { genotype_map[i] = in_geno; }
+  // Generic data
+  void SetCoalescentGenotypeDepth(int in_depth) {coal_depth = in_depth;}
+
+  inline void SetNumGenotypes(int new_genotypes);
+  inline void SetNumCreatures(int new_creatures);
+  inline void SetNumThreshSpecies(int new_thresh_species);
+  inline void SetBreedTrueCreatures(int in_num_breed_true_creatures);
+  inline void SetNumParasites(int in_num_parasites);
+  inline void SetNumNoBirthCreatures(int in_num_no_birth_creatures);
+  inline void SetNumSingleThreadCreatures(int in_num_single_thread_creatures);
+  inline void SetNumMultiThreadCreatures(int in_num_multi_thread_creatures);
+  inline void SetNumModified(int in_num_modified);
+
+  inline void SetMaxFitness(double in_max_fitness)
+    { max_fitness = in_max_fitness; }
+  inline void SetMaxMerit(double in_max_merit)
+    { max_merit = in_max_merit; }
+  inline void SetEntropy(double in_entropy)
+    { entropy = in_entropy; }
+  inline void SetSpeciesEntropy(double in_ent)
+    { species_entropy = in_ent; }
+
+  cDoubleSum & SumFitness()       { return sum_fitness; }
+  cDoubleSum & SumGestation()     { return sum_gestation; }
+  cDoubleSum & SumMerit()         { return sum_merit; }
+  cDoubleSum & SumReproRate()     { return sum_repro_rate; }
+
+  cDoubleSum & SumCreatureAge()   { return sum_creature_age; }
+  cDoubleSum & SumGenotypeAge()   { return sum_genotype_age; }
+  cDoubleSum & SumGeneration()    { return sum_generation; }
+  cDoubleSum & SumAbundance()     { return sum_abundance; }
+  cDoubleSum & SumGenotypeDepth() { return sum_genotype_depth; }
+  cDoubleSum & SumThresholdAge()  { return sum_threshold_age; }
+  cDoubleSum & SumSpeciesAge()    { return sum_species_age; }
+
+  cDoubleSum & SumNeutralMetric() { return sum_neutral_metric; }
+  cDoubleSum & SumLineageLabel()  { return sum_lineage_label; }
+  cDoubleSum & SumCopyMutRate()   { return sum_copy_mut_rate; }
+  cDoubleSum & SumLogCopyMutRate()   { return sum_log_copy_mut_rate; }
+  cDoubleSum & SumDivMutRate()   { return sum_div_mut_rate; }
+  cDoubleSum & SumLogDivMutRate()   { return sum_log_div_mut_rate; }
+
+  cDoubleSum & SumSize()          { return sum_size; }
+  cDoubleSum & SumCopySize()      { return sum_copy_size; }
+  cDoubleSum & SumExeSize()       { return sum_exe_size; }
+  cDoubleSum & SumMemSize()       { return sum_mem_size; }
+
+  void ZeroInst();
+  tArray<cIntSum> & SumExeInst() { return sum_exe_inst_array; }
+
+  // And constant versions of the above...
+  const cDoubleSum & SumFitness() const       { return sum_fitness; }
+  const cDoubleSum & SumGestation() const     { return sum_gestation; }
+  const cDoubleSum & SumMerit() const         { return sum_merit; }
+  const cDoubleSum & SumReproRate() const     { return sum_repro_rate; }
+
+  const cDoubleSum & SumCreatureAge() const   { return sum_creature_age; }
+  const cDoubleSum & SumGenotypeAge() const   { return sum_genotype_age; }
+  const cDoubleSum & SumGeneration() const    { return sum_generation; }
+  const cDoubleSum & SumAbundance() const     { return sum_abundance; }
+  const cDoubleSum & SumGenotypeDepth() const { return sum_genotype_depth; }
+  const cDoubleSum & SumThresholdAge() const  { return sum_threshold_age; }
+  const cDoubleSum & SumSpeciesAge() const    { return sum_species_age; }
+
+  const cDoubleSum & SumNeutralMetric() const { return sum_neutral_metric; }
+  const cDoubleSum & SumLineageLabel() const  { return sum_lineage_label; }
+  const cDoubleSum & SumCopyMutRate() const   { return sum_copy_mut_rate; }
+  const cDoubleSum & SumLogCopyMutRate() const{ return sum_log_copy_mut_rate; }
+  const cDoubleSum & SumDivMutRate() const   { return sum_div_mut_rate; }
+  const cDoubleSum & SumLogDivMutRate() const{ return sum_log_div_mut_rate; }
+
+  const cDoubleSum & SumSize() const          { return sum_size; }
+  const cDoubleSum & SumCopySize() const      { return sum_copy_size; }
+  const cDoubleSum & SumExeSize() const       { return sum_exe_size; }
+  const cDoubleSum & SumMemSize() const       { return sum_mem_size; }
+
+  void CalcEnergy();
+  void CalcFidelity();
+
+  void RecordBirth(int cell_id, int genotype_id, bool breed_true);
+  void RecordDeath(int genotype_id, int num_divides, int age);
+  void AddGenotype(int id_num);
+  void RemoveGenotype(int id_num, int parent_id,
+			     int parent_distance, int depth, int max_abundance,
+			     int parasite_abundance, int age, int length);
+  void AddThreshold(int id_num, const char * name,
+				  int species_num=-1);
+  void RemoveThreshold(int id_num);
+  void AddSpecies(int id_num);
+  void RemoveSpecies(int id_num, int parent_id,
+			 int max_gen_abundance, int max_abundance, int age);
+  void AddLineage();
+  void RemoveLineage(int id_num, int parent_id, int update_born,
+		     double generation_born, int total_CPUs,
+		     int total_genotypes, double fitness, 
+		     double lineage_stat1, double lineage_stat2 );
+				
+  void IncExecuted() { num_executed++; }
+
+  void AddCurTask(int task_num) { task_cur_count[task_num]++; }
+  void AddLastTask(int task_num) { task_last_count[task_num]++; }
+  void IncTaskExeCount(int task_num) { task_exe_count[task_num]++; }
+  void ZeroTasks();
+
+  void SetReactions(const tArray<double> &_in) { reaction_count = _in; }
+  void SetResources(const tArray<double> &_in) { resource_count = _in; }
+  void SetResourcesGeometry(const tArray<int> &_in) { resource_geometry = _in;}
+  void SetSpatialRes(const tArray< tArray<double> > &_in) { 
+    spatial_res_count = _in;
+  }
+
+  void SetTaskName(int id, const cString & name) { task_names[id] = name; }
+  void SetInstName(int id, const cString & name) {
+    assert(id < inst_names.GetSize());
+    inst_names[id] = name;
+  }
+  void SetReactionName(int id, const cString & name) { reaction_names[id] = name; }
+  void SetResourceName(int id, const cString & name) { resource_names[id] = name; }
+
+  // Information retrieval section...
+
+  int GetNumBirths() const          { return num_births; }
+  int GetNumDeaths() const          { return num_deaths; }
+  int GetBreedIn() const            { return num_breed_in; }
+  int GetBreedTrue() const          { return num_breed_true; }
+  int GetBreedTrueCreatures() const { return num_breed_true_creatures; }
+  int GetNumCreatures() const       { return num_creatures; }
+  int GetNumGenotypes() const       { return num_genotypes; }
+  int GetNumThreshold() const       { return num_threshold; }
+  int GetNumSpecies() const         { return num_species; }
+  int GetNumThreshSpecies() const   { return num_thresh_species; }
+  int GetNumLineages() const        { return num_lineages; }
+  int GetNumParasites() const       { return num_parasites; }
+  int GetNumNoBirthCreatures() const{ return num_no_birth_creatures; }
+  int GetNumSingleThreadCreatures() const { return num_single_thread_creatures; }
+  int GetNumMultiThreadCreatures() const { return num_multi_thread_creatures; }
+  int GetNumModified() const { return num_modified;}
+
+  int GetTotCreatures() const       { return tot_organisms; }
+  int GetTotGenotypes() const       { return tot_genotypes; }
+  int GetTotThreshold() const       { return tot_threshold; }
+  int GetTotSpecies() const         { return tot_species; }
+  int GetTotThreshSpecies() const   { return tot_thresh_species; }
+  int GetTotLineages() const        { return tot_lineages; }
+
+  int GetTaskCurCount(int task_num) const { return task_cur_count[task_num]; }
+  int GetTaskLastCount(int task_num) const {return task_last_count[task_num];}
+  int GetTaskExeCount(int task_num) const { return task_exe_count[task_num]; }
+
+  const tArray<double> & GetReactions() const { return reaction_count; }
+  const tArray<double> & GetResources() const { return resource_count; }
+
+  double GetAveReproRate() const  { return sum_repro_rate.Average(); }
+
+  double GetAveMerit() const      { return sum_merit.Average(); }
+  double GetAveCreatureAge() const{ return sum_creature_age.Average(); }
+  double GetAveMemSize() const    { return sum_mem_size.Average(); }
+
+  double GetAveNeutralMetric() const { return sum_neutral_metric.Average(); }
+  double GetAveLineageLabel() const  { return sum_lineage_label.Average(); }
+  double GetAveCopyMutRate() const   { return sum_copy_mut_rate.Average(); }
+  double GetAveLogCopyMutRate() const{ return sum_log_copy_mut_rate.Average();}
+  double GetAveDivMutRate() const   { return sum_div_mut_rate.Average(); }
+  double GetAveLogDivMutRate() const{ return sum_log_div_mut_rate.Average();}
+
+  double GetAveGestation() const { return sum_gestation.Average(); }
+  double GetAveFitness() const   { return sum_fitness.Average(); }
+
+  double GetAveGenotypeAge() const { return sum_genotype_age.Average();}
+
+  double GetAveSize() const       { return sum_size.Average(); }
+  double GetAveCopySize() const   { return sum_copy_size.Average(); }
+  double GetAveExeSize() const    { return sum_exe_size.Average(); }
+
+  double GetEntropy() const        { return entropy; }
+  double GetSpeciesEntropy() const { return species_entropy; }
+  double GetEnergy() const         { return energy; }
+  double GetEvenness() const       { return entropy / Log(num_genotypes); }
+  int GetCoalescentDepth() const   { return coal_depth; }
+
+  double GetAveThresholdAge() const { return sum_threshold_age.Average(); }
+  double GetAveSpeciesAge() const { return sum_species_age.Average(); }
+
+  double GetMaxFitness() const { return max_fitness; }
+  double GetMaxMerit() const { return max_merit; }
+
+  // this value gets recorded when a creature with the particular
+  // fitness value gets born. It will never change to a smaller value,
+  // i.e., when the maximum fitness in the population drops, this value will
+  // still stay up.
+  double GetMaxViableFitness() const { return max_viable_fitness; }
+
+  // Access to data_file_manager (so cPopulation can output files)
+  std::ofstream & GetDataFileOFStream(const cString & fname){
+    return data_file_manager.GetOFStream(fname); }
+  cDataFile & GetDataFile(const cString & fname){
+    return data_file_manager.Get(fname); }
+
+
+  // User-defined datafile...
+  void PrintDataFile(const cString & filename, const cString & format,
+		     char sep=' ');
+
+  // Public calls to output data files (for events)
+  void PrintAverageData(const cString & filename);
+  void PrintErrorData(const cString & filename);
+  void PrintVarianceData(const cString & filename);
+  void PrintDominantData(const cString & filename);
+  void PrintDominantParaData(const cString & filename);
+  void PrintStatsData(const cString & filename);
+  void PrintCountData(const cString & filename);
+  void PrintTotalsData(const cString & filename);
+  void PrintTasksData(const cString & filename);
+  void PrintTasksExeData(const cString & filename);
+  void PrintReactionData(const cString & filename);
+  void PrintResourceData(const cString & filename);
+  void PrintSpatialResData(const cString & filename, int i);
+  void PrintTimeData(const cString & filename);
+  void PrintMutationData(const cString & filename);
+  void PrintDivideMutData(const cString & filename);
+  void PrintMutationRateData(const cString & filename);
+  void PrintInstructionData(const cString & filename);
+  void PrintGenotypeMap(const cString & filename);
+};
+
+
+inline void cStats::SetNumGenotypes(int new_genotypes)
+{
+  num_genotypes_last = num_genotypes;
+  num_genotypes = new_genotypes;
+}
+
+inline void cStats::SetNumCreatures(int new_creatures)
+{
+  num_creatures = new_creatures;
+}
+
+inline void cStats::SetNumThreshSpecies(int new_thresh_species)
+{
+  num_thresh_species = new_thresh_species;
+}
+
+inline void cStats::SetBreedTrueCreatures(int in_num_breed_true_creatures)
+{
+  num_breed_true_creatures = in_num_breed_true_creatures;
+}
+
+inline void cStats::SetNumParasites(int in_num_parasites)
+{
+  num_parasites = in_num_parasites;
+}
+
+inline void cStats::SetNumNoBirthCreatures(int in_num_no_birth_creatures)
+{
+  num_no_birth_creatures = in_num_no_birth_creatures;
+}
+
+inline void cStats::SetNumSingleThreadCreatures(int in_num_single_thread_creatures)
+{
+  num_single_thread_creatures = in_num_single_thread_creatures;
+}
+
+inline void cStats::SetNumMultiThreadCreatures(int in_num_multi_thread_creatures)
+{
+  num_multi_thread_creatures = in_num_multi_thread_creatures;
+}
+
+inline void cStats::SetNumModified(int in_num_modified)
+{
+  num_modified = in_num_modified;
+}
+
+#endif
Index: avida/current/source/main/Makefile.am
diff -u avida/current/source/main/Makefile.am:1.35 avida/current/source/main/Makefile.am:1.36
--- avida/current/source/main/Makefile.am:1.35	Wed Oct 15 19:59:21 2003
+++ avida/current/source/main/Makefile.am	Tue Nov 25 09:37:56 2003
@@ -16,46 +16,72 @@
 #
 # don't know why it was needed.
 #
-AVIDA_EVENT_DIR = -I$(srcdir)/../event -I../event
-AVIDA_CPU_DIR = -I$(srcdir)/../cpu
-INCLUDES = $(AVIDA_EVENT_DIR) $(AVIDA_CPU_DIR)
+EVENT_DIR = -I$(srcdir)/../event -I../event
+CPU_DIR = -I$(srcdir)/../cpu
+TOOLS_DIR = -I$(srcdir)/../tools
+SOURCE_DIR = -I$(srcdir)/..
+INCLUDES = $(EVENT_DIR) $(CPU_DIR) $(TOOLS_DIR) $(SOURCE_DIR)
 #
 
-libmain_a_SOURCES = analyze.hh		analyze.cc		\
-    analyze_util.hh		analyze_util.cc		\
-    avida.hh		avida.cc		\
-    birth_chamber.hh	birth_chamber.cc	\
-    callback_util.hh	callback_util.cc	\
-    config.hh		config.cc		\
-    environment.hh		environment.cc		\
-    fitness_matrix.hh	fitness_matrix.cc	\
-    genebank.hh		genebank.cc		\
-    genome.hh		genome.cc		\
-    genome_util.hh		genome_util.cc		\
-    genotype.hh		genotype.cc		\
-    inject_genebank.hh	inject_genebank.cc   	\
-    inject_genotype.hh  inject_genotype.cc	\
-    inst.hh			inst.cc			\
-    inst_set.hh		inst_set.cc		\
-    inst_lib.hh \
-    inst_util.hh		inst_util.cc		\
-    landscape.hh		landscape.cc		\
-    lineage.hh		lineage.cc		\
-    lineage_control.hh	lineage_control.cc 	\
-    mutations.hh		mutations.cc		\
-    org_message.hh      org_message.cc          \
-    organism.hh		organism.cc		\
-    phenotype.hh		phenotype.cc		\
-    population.hh		population.cc		\
-    population_cell.hh	population_cell.cc	\
-    pop_interface.hh	pop_interface.cc	\
-    reaction.hh		reaction.cc		\
-    reaction_result.hh	reaction_result.cc	\
-    resource.hh		resource.cc		\
-    resource_count.hh	resource_count.cc	\
-    species.hh		species.cc		\
-    stats.hh		stats.cc		\
-    tasks.hh		tasks.cc		
+libmain_a_SOURCES = \
+  analyze.hh analyze.cc \
+  analyze_genotype.hh analyze_genotype.cc \
+  analyze_util.hh analyze_util.cc \
+  avida.hh avida.cc \
+  avida_driver_analyze.hh avida_driver_analyze.cc \
+  avida_driver_base.hh avida_driver_base.cc \
+  avida_driver_population.hh avida_driver_population.cc \
+  birth_chamber.hh birth_chamber.cc	\
+  callback_util.hh callback_util.cc	\
+  config.hh config.cc \
+  environment.hh environment.cc		\
+  fitness_matrix.hh fitness_matrix.cc \
+  genebank.hh genebank.cc \
+  genome.hh genome.cc		\
+  genome_util.hh genome_util.cc		\
+  genotype.hh genotype.cc \
+  genotype_birth_data.hh genotype_birth_data.cc \
+  genotype_control.hh genotype_control.cc \
+  genotype_test_data.hh genotype_test_data.cc \
+  inject_genebank.hh inject_genebank.cc \
+  inject_genotype.hh inject_genotype.cc \
+  inject_genotype_birth_data.hh inject_genotype_birth_data.cc \
+  inject_genotype_control.hh inject_genotype_control.cc \
+  inject_genotype_queue.hh inject_genotype_queue.cc \
+  instruction.hh instruction.cc \
+  inst_set.hh inst_set.cc \
+  inst_lib_base.hh \
+  inst_util.hh inst_util.cc		\
+  landscape.hh landscape.cc		\
+  lineage.hh lineage.cc \
+  lineage_control.hh lineage_control.cc 	\
+  local_mutations.hh local_mutations.cc		\
+  mutation_lib.hh mutation_lib.cc		\
+  mutation_rates.hh mutation_rates.cc		\
+  mutation.hh mutation.cc		\
+  mx_code_array.hh mx_code_array.cc		\
+  org_message.hh org_message.cc          \
+  organism.hh organism.cc		\
+  phenotype.hh phenotype.cc		\
+  population.hh population.cc		\
+  population_cell.hh population_cell.cc	\
+  population_interface.hh population_interface.cc	\
+  reaction.hh reaction.cc		\
+  reaction_lib.hh reaction_lib.cc		\
+  reaction_process.hh reaction_process.cc		\
+  reaction_requisite.hh reaction_requisite.cc		\
+  reaction_result.hh reaction_result.cc	\
+  resource.hh resource.cc		\
+  resource_count.hh resource_count.cc \
+  resource_lib.hh resource_lib.cc		\
+  spatial_count_elem.hh spatial_count_elem.cc \
+  spatial_res_count.hh spatial_res_count.cc \
+  species.hh species.cc \
+  species_control.hh species_control.cc \
+  species_queue.hh species_queue.cc \
+  stats.hh stats.cc		\
+  task_entry.hh task_entry.cc \
+  task_lib.hh task_lib.cc
 
 noinst_LIBRARIES = libmain.a
 
@@ -68,16 +94,10 @@
     ../event/libevent.a          	\
     ./libmain.a			\
     ../tools/libtools.a \
-    ../third-party/trio-1.9/libtrio.a
+    ../third-party/trio/libtrio.a
 
 if BUILD_PRIMITIVE
 bin_PROGRAMS = primitive
 endif
 
 EXTRA_DIST = main.pro main_sub.pri
-
-if DEJAGNU_REGRESSION_TESTS
-# Disabled unit_testsuite until I can try it out on our beowulf.
-#SUBDIRS = . unit_testsuites functional_testsuites
-SUBDIRS = . functional_testsuites
-endif
Index: avida/current/source/tools/block_struct.cc
diff -u /dev/null avida/current/source/tools/block_struct.cc:1.5
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/block_struct.cc	Tue Nov 25 09:38:00 2003
@@ -0,0 +1,223 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2000 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BLOCK_STRUCT_HH
+#include "block_struct.hh"
+#endif
+
+////////////////////
+//  cBlockStruct
+////////////////////
+
+cBlockStruct::cBlockStruct(int in_num_scaled, int in_num_fixed)
+{
+  num_fixed = in_num_fixed;
+  num_scaled = in_num_scaled;
+
+  fixed_array = new cFixedBlock[num_fixed];
+  scaled_array = new cScaledBlock[num_scaled];
+
+  fixed_used(0, 0);
+  scaled_used = 0;
+
+  fixed_size = 0;
+}
+
+cBlockStruct::~cBlockStruct()
+{
+  delete [] scaled_array;
+  delete [] fixed_array;
+}
+
+int cBlockStruct::AddData(void * in_data, int in_size)
+{
+  if (in_size <= 0) return -1;    // Only allow positive sized data.
+
+  scaled_array[scaled_used].SetData(in_data);
+  scaled_array[scaled_used].SetSize(in_size);
+  
+  return scaled_used++;
+}
+
+int cBlockStruct::AddDataTo(void * in_data, int in_index)
+{
+  scaled_array[in_index].SetData(in_data);
+
+  return scaled_array[in_index].GetSize();
+}
+
+void cBlockStruct::Clear()
+{
+  fixed_used(0, 0);
+  scaled_used = 0;
+}
+
+int cBlockStruct::Process()
+{
+  if (!fixed_size) {
+    printf("Error! No fixed size!\n");
+    return -1;
+  }
+
+  int cur_scaled = 0;
+  int cur_fixed = 0;
+  int size_left = scaled_array[0].GetSize();
+
+  // Set up the internal data for the first scaled block.
+
+  scaled_array[0].SetStart(0, 0);
+
+  // Move through the fixed blocks assigning each to the corresponding scaled
+  // block.  This is done by keeping track of the current scaled block for
+  // a particular location, and keeping track the "size" until the next block.
+  
+  for(cur_fixed = 0; cur_fixed < num_fixed; cur_fixed++) {
+    // Set the current fixed block to point to whatever scaled block we are
+    // currently in.
+
+    fixed_array[cur_fixed].SetStart(cur_scaled);
+
+    // If the current scaled block covers the entire fixed block, then just
+    // adjust the size_left and move on.
+
+    if (size_left > fixed_size) {
+      size_left -= fixed_size;
+      continue;
+    }
+
+    // Otherwise, start moving through the scaled blocks until the size can
+    // be covered.
+
+    while (size_left <= fixed_size) {
+      // move onto the next scaled block...
+      cur_scaled++;
+
+      //  Check to see if we are finished...
+      if (cur_scaled == scaled_used) {
+	fixed_used(cur_fixed, size_left);  // Store max coord
+	return cur_fixed + 1;
+      }
+
+      // Setup the next cScaledBlock...
+
+      scaled_array[cur_scaled].SetStart(cur_fixed, size_left);
+      if (size_left == fixed_size) {
+	scaled_array[cur_scaled].SetStart(cur_fixed + 1, 0);
+      }
+
+      // Add the size of the new cScaledBlock onto the size_left.
+
+      size_left += scaled_array[cur_scaled].GetSize();
+    }
+
+    // Move onto the next fixed block.
+    size_left -= fixed_size;
+  }
+
+  printf("END Process() : Ran out of fixed_blocks...\n");
+  
+  return -1;
+}
+
+int cBlockStruct::Update()
+{
+  // @CAO make sure a process has been done at some point in the past?
+
+  // Start out where the last Process() finished.
+
+  int cur_scaled = fixed_array[fixed_used.GetBlockNum()].GetStart();
+  int cur_fixed = scaled_array[cur_scaled].GetStart().GetBlockNum();
+  int cur_offset = scaled_array[cur_scaled].GetStart().GetOffset();
+  int size_left = scaled_array[cur_scaled].GetSize();
+
+  // Re-adjust to make sure we are starting at the begining of a fixed block.
+
+  if (cur_offset) {
+    size_left += cur_offset - fixed_size;
+    cur_fixed++;
+  }
+
+  // Move through the fixed blocks assigning each to the corresponding scaled
+  // block.  This is done by keeping track of the current scaled block for
+  // a particular location, and keeping track the "size" until the next block.
+  
+  for(; cur_fixed < num_fixed; cur_fixed++) {
+    // Set the current fixed block to point to whatever scaled block we are
+    // currently in.
+
+    fixed_array[cur_fixed].SetStart(cur_scaled);
+
+    // If the current scaled block covers the entire fixed block, then just
+    // adjust the size_left and move on.
+
+    if (size_left > fixed_size) {
+      size_left -= fixed_size;
+      continue;
+    }
+
+    // Otherwise, start moving through the scaled blocks until the size can
+    // be covered.
+
+    while (size_left <= fixed_size) {
+      // move onto the next scaled block...
+      cur_scaled++;
+
+      //  Check to see if we are finished...
+      if (cur_scaled == scaled_used) {
+	fixed_used(cur_fixed, size_left);  // Store max coord
+	return cur_fixed + 1;
+      }
+
+      // Setup the next cScaledBlock...
+
+      scaled_array[cur_scaled].SetStart(cur_fixed, size_left);
+      if (size_left == fixed_size) {
+	scaled_array[cur_scaled].SetStart(cur_fixed + 1, 0);
+      }
+
+      // Add the size of the new cScaledBlock onto the size_left.
+
+      size_left += scaled_array[cur_scaled].GetSize();
+    }
+
+    // Move onto the next fixed block.
+    size_left -= fixed_size;
+  }
+
+  printf("END Update() : Ran out of fixed_blocks...\n");
+  
+  return -1;
+}
+
+
+int cBlockStruct::Compress()
+{
+  int scan_loc;
+  int write_loc = 0;
+
+  for (scan_loc = 0; scan_loc < num_scaled; scan_loc++) {
+    if (scaled_array[scan_loc].GetData()) {
+      if (scan_loc != write_loc) {
+	scaled_array[write_loc] = scaled_array[scan_loc];
+	scaled_array[scan_loc].SetData(NULL);
+	scaled_array[scan_loc].SetSize(0);
+      }
+      write_loc++;
+    }
+  }
+
+  num_scaled = write_loc;
+
+  return num_scaled;
+}
+
+void * cBlockStruct::Remove(int out_block)
+{
+  void * temp = scaled_array[out_block].GetData();
+  scaled_array[out_block].SetData(NULL);
+  return temp;
+}
Index: avida/current/source/tools/block_struct.hh
diff -u /dev/null avida/current/source/tools/block_struct.hh:1.6
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/block_struct.hh	Tue Nov 25 09:38:00 2003
@@ -0,0 +1,271 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BLOCK_STRUCT_HH
+#define BLOCK_STRUCT_HH
+
+#ifndef FIXEDBLOCK_HH
+#include "fixed_block.hh"
+#endif
+#ifndef FIXEDCOORDS_HH
+#include "fixed_coords.hh"
+#endif
+#ifndef SCALED_BLOCK_HH
+#include "scaled_block.hh"
+#endif
+#ifndef UINT_HH
+#include "uint.hh"
+#endif
+
+#define BLOCK_FLAG_FILL_IN       0
+#define BLOCK_FLAG_AUTO_COMPRESS 1
+#define BLOCK_FLAG_FRAGMENT_OK   2
+#define BLOCK_FLAG_AUTOCALC_SIZE 3
+
+/**
+ * A data structure which allows indexing into an array
+ * where each cell of the array is *not* a fixed size. This would be useful
+ * in situations such as when working with probabilities (construct an array
+ * with each piece of data having a size propotional to its probability, and
+ * then index randomly into the array) or mapping the contents of a one-
+ * dimensional space (such as computer memory) allowing random access to what
+ * is at any location with maximal precision, high speed, and reasonably low
+ * memory costs.
+ *
+ * The structure works by first creating an array where each block contains
+ * the data it points to, and a number representing its size. This is then
+ * translated onto a second array where all of the blocks represent a fixed
+ * size, and simply point back to their respective location in the original
+ * array. The structure can therefore find the approximate location in the
+ * original array, and do a serial search from there.
+ *
+ * Example: We have a time line of 100 years which there were 5 distinct
+ *   periods of time (labeled A-E for convienence), A = 15 yrs, B = 20 yrs,
+ *   C = 10 yrs, D = 5 yrs, and E = 50 yrs. We can represent each of these
+ *   as a block with a size equal to its duration. Then, we might translate
+ *   it to 5 fixed blocks, each of size 20 years, where the first points to
+ *   block A, the second to B, the third to C, and the last two to E. Thus,
+ *   if you want to know what period any specific year was in, you only have
+ *   to indexed into the fixed-size array, and you immediately have a much
+ *   more acurate starting point for your search in the scaled array. In
+ *   this case it's not a big deal since there only five blocks to consider,
+ *   but when you start having huge quantities of data to consider, this
+ *   technique is much more useful.
+ *
+ * In avida this is used in two parts. The first is in the probabilistic
+ * time slicing scheme where we want all of the creatures to have a chance
+ * of being executed proportional to their merit. The second is in the
+ * cosmic ray mutations, where each creature's chance of being struck by one
+ * is scaled to their size.
+ *
+ * In creating a cBlockStruct, the variables which need to be set are the
+ * number of blocks in each of the arrays. In the first array, this simply
+ * determines how many of pieces of data can be entered into the structure.
+ * In the second (fixed-size blocked) array, this will determine the
+ * resolution of the initial search. A higher resolution allows for a much
+ * faster search, while a lower resultion means less memory is used. By the
+ * diminishing returns of larger arrays, memory and speed maximize when both
+ * arrays are made of the same size.
+ *
+ * The only other variable which needs to be considered is the actual size
+ * of each block in the fixed-size array. This can either be entered by the
+ * programer, or else optimally determined from the data which has thus far
+ * been entered by running the CalcFixedSize() method. It is only recomened
+ * the you calculate the value outside of the object if you are planing to
+ * still insert more data to be added into the structure after it is initially
+ * constructed.
+ *
+ * To add data to the object, call AddData(void *, int),
+ * where the first input
+ * is a pointer to the data, and the second is its size. Once all the data
+ * has been added, a call to Process() will build up the object so it can
+ * be used (remember, the fixed_size must be set before Process() 
+ * can run).
+ * If more data is added to the structure after Process() is run, a second
+ * function, Update(), will incorporate all of the new information without
+ * having to take the time to rebuild the whole thing.
+ *
+ * When AddData(void *, int) is called, it will return a int value 
+ * which is
+ * the location in the propotional sized array that that piece of data has.
+ * If you every want to remove the data from the structure, you must call
+ * Remove(int) giving it back this int tag. 
+ * Remove will simply change the
+ * pointer to the data at this location to a NULL pointer. If you want to
+ * put new data in this location, call AddDataTo(void *, int) where the
+ * first argument is the data, and the second is the location to place it in.
+ * It will have the same size as the original piece of data in this location.
+ * Finally, if you wish to simply get rid of the NULL data locations, a
+ * call to the method Compress() will do this in O(N) time. 
+ * Note that once
+ * the data is compressed, all of the tags will change, and the ones sent
+ * back by AddData() will no longer be valid.
+ *
+ * Extra options (in the form of flags) are going to be added. These are:
+ *   BLOCK_FLAG_FILL_IN : This causes all new entries added with AddData()
+ *     to be placed in the first cell pointing to NULL data in which it fits,
+ *     rather then at the end of the currently used portion of the array.
+ *     This is useful to conserve space in the array, but insertions take
+ *     slightly longer.
+ *   BLOCK_FLAG_AUTO_COMPRESS : This causes the array to automatically be
+ *     compressed to remove the space left by removed data, and the runs
+ *     process again. This keeps clean arrays with no holes in them, but
+ *     insertions take *very* long.
+ *   BLOCK_FLAG_FRAGMENT_OK : This causes new data to be placed in the blocks
+ *     of old data, even if it means spliting up a single piece of data over
+ *     a number of blocks. This minimizes the amount of wasted space in the
+ *     array without taking the time to compress the entire thing, but can
+ *     lead to a huge number of cells in the array being used due to
+ *     fragmentation.
+ *   BLOCK_FLAG_AUTOCALC_SIZE : This option causes Process() to 
+ *     automatically
+ *     recalculate the fixed_size every time it is run.
+ **/
+
+class cFixedCoords; // aggregate
+class cFixedBlock; // accessed
+class cScaledBlock; // accessed
+class cUInt; // aggregate
+
+class cBlockStruct {
+private:
+  cFixedBlock * fixed_array;
+  cScaledBlock * scaled_array;
+
+  int num_fixed;
+  int num_scaled;
+
+  cFixedCoords fixed_used;
+  int scaled_used;
+
+  int fixed_size;
+public:
+  cBlockStruct(int in_num_scaled = 1, int in_num_fixed = 1);
+  ~cBlockStruct();
+
+/**
+ * This function adds a single piece of data to the scaled array
+ * but does not update the fixed array yet. 
+ * 
+ * @see cBlockStruct::AddDataTo
+ * @return An index into the scaled block array.
+ * @param in_data A pointer to the data.
+ * @param in_size The size of the data.
+ **/
+  int AddData(void * in_data, int in_size);
+  
+    
+/**
+ * This function adds a single piece of data to the scaled array
+ * but does not update the fixed array yet. In comparison to
+ * @ref cBlockStruct::AddData, this function adds the data at the given
+ * index in_index in the scaled block array, and returns the size of the
+ * data at that index position.
+ * 
+ * @see cBlockStruct::AddData
+ * @return The size of the data at position in_index.
+ * @param in_data A pointer to the data.
+ * @param in_index The index position at which the data should be put.
+ **/
+  int AddDataTo(void * in_data, int in_index);
+
+/**
+ * This function removes all of the data from the structure.
+ **/
+  void Clear();
+
+/**
+ * This function takes the scaled array and constructs from it the
+ * proper fixed array.  Any information which previously was in the fixed 
+ * array is  
+ * completely erased and re-constructed.  
+ *
+ * @return The number of @ref cFixedBlock's, or -1 if that number overflows.
+ **/
+  int Process();   
+
+/**
+ * This function looks at data which has been taken in since the last
+ * time the fixed array was built or updated, and the new info at the end.
+ *
+ * @return The number of @ref cFixedBlock's, or -1 if that number overflows.
+ **/
+  int Update();
+
+/**
+ * This function takes the scaled array, and removes any elements from it
+ * which no longer point to data, and compresses everything to the begining.
+ * This should always be followed shortly by adding any new data, and then
+ * a Process(). 
+ *
+ * @return The new number of @ref cScaledBlock's used.
+ **/
+    
+  int Compress();
+
+
+/**
+ * Function to retrieve data from the structure.
+ **/
+  inline void * Find(const cFixedCoords & search_coords) const;
+/**
+ * Function to retrieve data from the structure.
+ **/    
+  inline void * Find(int in_block, int in_offset) const;
+/**
+ * Function to retrieve data from the structure.
+ **/    
+  inline void * Find(cUInt in_position) const;
+
+/**
+ *  Function to remove data from the structure.
+ **/
+  void * Remove(int out_block);
+
+  // Finally, internal variable control...
+  inline int GetFixedSize() const { return fixed_size; }
+  inline int GetBlocksUsed() const { return fixed_used.GetBlockNum() + 1; }
+  inline void SetFixedSize(int in_fs) { fixed_size = in_fs; }
+};
+
+inline void * cBlockStruct::Find(const cFixedCoords & search_coords) const
+{
+  // Make sure the find is within range.
+  if (search_coords >= fixed_used) {
+    return NULL;
+  }
+
+  // Find the starting point in the scaled array for the search.
+  int scaled_loc = fixed_array[search_coords.GetBlockNum()].GetStart();
+  cFixedCoords cur_coords = scaled_array[scaled_loc].GetStart();
+
+  // Starting at the starting point, move through the array until the entry
+  // which covers this area is found.
+  cur_coords.Add(0, scaled_array[scaled_loc].GetSize(), fixed_size);
+  while (cur_coords <= search_coords) {
+    scaled_loc++;
+    cur_coords.Add(0, scaled_array[scaled_loc].GetSize(), fixed_size);
+  }
+
+  // Return the data in the found entry.
+  return scaled_array[scaled_loc].GetData();
+}
+
+inline void * cBlockStruct::Find(int in_block, int in_offset) const
+{
+  cFixedCoords search_coords(in_block, in_offset);
+  return Find(search_coords);
+}
+
+inline void * cBlockStruct::Find(cUInt in_position) const
+{
+  cFixedCoords search_coords((in_position /= fixed_size).AsInt(),
+			     (in_position %= fixed_size).AsInt());
+  return Find(search_coords);
+}
+
+#endif
Index: avida/current/source/tools/data_entry.cc
diff -u /dev/null avida/current/source/tools/data_entry.cc:1.6
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/data_entry.cc	Tue Nov 25 09:38:00 2003
@@ -0,0 +1,17 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef DATA_ENTRY_HH
+#include "data_entry.hh"
+#endif
+
+
+std::ostream & operator << (std::ostream & out, cDataEntry & entry)
+{
+  entry.Print(out);
+  return out;
+}
Index: avida/current/source/tools/data_entry.hh
diff -u /dev/null avida/current/source/tools/data_entry.hh:1.8
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/data_entry.hh	Tue Nov 25 09:38:00 2003
@@ -0,0 +1,43 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef DATA_ENTRY_HH
+#define DATA_ENTRY_HH
+
+#include <iostream>
+
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+
+class cString; // aggregate
+
+class cDataEntry {
+private:
+  cString name;            // Short Name
+  cString desc;            // Descriptive Name
+  cString null_value;      // Value when "off", such as "0", "Inf.", or "N/A"
+  cString html_table_flags; // String to include in <td> entry in html mode.
+public:
+  cDataEntry(const cString & _name, const cString & _desc,
+	     const cString & _null="0",
+	     const cString & _html_cell="align=center")
+    : name(_name), desc(_desc), null_value(_null),
+      html_table_flags(_html_cell) { ; }
+  virtual ~cDataEntry() { ; }
+
+  const cString & GetName() const { return name; }
+  const cString & GetDesc() const { return desc; }
+  const cString & GetNull() const { return null_value; }
+  const cString & GetHtmlCellFlags() const { return html_table_flags; }
+
+  virtual bool Print(std::ostream & fp) const { (void) fp;  return false; }
+};
+
+std::ostream & operator << (std::ostream & out, cDataEntry & entry);
+
+#endif
Index: avida/current/source/tools/file.cc
diff -u /dev/null avida/current/source/tools/file.cc:1.22
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/file.cc	Tue Nov 25 09:38:00 2003
@@ -0,0 +1,114 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef FILE_HH
+#include "file.hh"
+#endif
+
+#ifndef INIT_FILE_HH
+#include "init_file.hh"
+#endif
+#ifndef GENESIS_HH
+#include "genesis.hh"
+#endif
+#ifndef STRING_ITERATOR_HH
+#include "string_iterator.hh"
+#endif
+
+extern "C" {
+#include <stdlib.h>
+#include <errno.h>   // needed for FOPEN error constants (MSVC)
+}
+
+#ifndef TOOLS_HH
+#include "tools.hh"  // for g_debug global
+#endif
+
+
+using namespace std;
+
+
+////////////
+//  cFile
+////////////
+
+
+
+//bool cFile::Open(cString _fname, int flags)
+// porting to gcc 3.1 -- k
+bool cFile::Open(cString _fname, ios::openmode flags)
+{
+  if( IsOpen() ) Close();    // If a file is already open, clost it first.
+  fp.open(_fname(), flags);  // Open the new file.
+
+  // Test if there was an error, and if so, try again!
+  int err_id = fp.fail();
+  if( err_id ){
+    fp.clear();
+    fp.open(_fname(), flags);
+  }
+
+  // If there is still an error, determine its type and report it.
+  err_id = fp.fail();
+  if (err_id){
+    cString error_desc = "?? Unknown Error??";
+
+    // See if we can determine a more exact error type.
+    if (err_id == EACCES) error_desc = "Access denied";
+    else if (err_id == EINVAL) error_desc = "Invalid open flag or access mode";
+    else if (err_id == ENOENT) error_desc = "File or path not found";
+
+    // Print the error.
+    cerr << "Unable to open file '" << _fname
+	 << "' : " << error_desc << endl;
+    return false;
+  }
+
+  filename = _fname;
+  is_open = true;
+
+  // Return true only if there were no problems...
+  return( fp.good() && !fp.fail() );
+}
+
+bool cFile::Close()
+{
+  if (is_open == true) {
+    fp.close();
+    return true;
+  }
+  return false;
+}
+
+bool cFile::ReadLine(cString & in_string)
+{
+  char cur_line[MAX_STRING_LENGTH];
+  cur_line[0]='\0';
+  fp.getline(cur_line, MAX_STRING_LENGTH);
+  if( fp.bad() ){
+    return false;
+  }
+  in_string = cur_line;
+  return true;
+}
+
+/*
+int cFile::CountLines()
+{
+  char cur_line[MAX_STRING_LENGTH];
+
+  Rewind();
+  int n_lines = -1;
+
+  do{
+    fp.getline(cur_line, MAX_STRING_LENGTH);
+    n_lines++;
+  } while( cur_line[0]!='\0' && !fp.eof() );
+
+  return n_lines;
+}
+*/
Index: avida/current/source/tools/file.hh
diff -u /dev/null avida/current/source/tools/file.hh:1.20
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/file.hh	Tue Nov 25 09:38:00 2003
@@ -0,0 +1,88 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef FILE_HH
+#define FILE_HH
+
+#include <fstream>
+
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+
+/**
+ * This class encapsulates file handling. In comparison to @ref cDataFile
+ * it has somewhat different features. It is more intended for reading files.
+ * In particular, by default it does not create a file that doesn't exist. 
+ * Its main usage is for the class @ref cInitFile.
+ **/
+
+class cString; // aggregate
+
+class cFile {
+protected:
+  std::fstream fp;
+  cString filename;
+  bool is_open; // Have we successfully opened this file?
+  bool verbose; // Should file be verbose about warnings to users?
+public:
+  /**
+   * The empty constructor does nothing.
+   **/ 
+  cFile() : filename(""), is_open(false), verbose(false) { ; }
+  
+  /**
+   * This constructor opens a file of the given name.
+   *
+   * @param _filename The name of the file to open.
+   **/
+  cFile(cString _filename) : filename(""), is_open(false) { Open(_filename); }
+  
+  /**
+   * The desctructor automatically closes the file.
+   **/
+  ~cFile() { if (is_open == true) fp.close(); filename = ""; }
+  
+  /**
+   * @return The name of the file currently open.
+   **/
+  const cString & GetFilename() const { return filename; }
+  
+  /**
+   * Open a file of the given name. If another file was open previously,
+   * close that one first.
+   *
+   * @return 0 if something went wrong, and 1 otherwise.
+   * @param _filename The name of the file to open.
+   * @param mode The opening mode.
+   **/
+  //bool Open(cString _filename, int mode=(ios::in|ios::nocreate));
+  // nocreate is no longer in the class ios -- k
+  bool Open(cString _filename, std::ios::openmode mode=(std::ios::in));
+  
+  /**
+   * Close the currently open file.
+   **/
+  bool Close();
+  
+  /**
+   * Reads the next line in the file.
+   **/
+  bool ReadLine(cString & in_string);
+  
+  // Tests
+  bool IsOpen() const { return is_open; }
+  bool Fail() const { return (fp.fail()); }
+  bool Good() const { return (fp.good()); }
+  bool Eof() const { return (fp.eof()); }
+  // int AtStart();
+  // int AtEnd();
+
+  void SetVerbose(bool _v=true) { verbose = _v; }
+};
+
+#endif
Index: avida/current/source/tools/functions.hh
diff -u /dev/null avida/current/source/tools/functions.hh:1.14
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/functions.hh	Tue Nov 25 09:38:00 2003
@@ -0,0 +1,153 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef FUNCTIONS_HH
+#define FUNCTIONS_HH
+
+#include <iostream>
+#include <math.h>
+#include <stdio.h>
+#include <assert.h>
+
+#ifndef TARRAY_HH
+#include "tArray.hh"
+#endif
+
+template <class T> class tArray; // accessed
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+inline int Min(int in1, int in2);
+inline int Max(int in1, int in2);
+inline int Range(int value, int min, int max);
+inline int Mod(int value, int base);
+inline int Pow(int bas, int expon);
+inline double Log(double value);
+
+//////////////////////
+// Generic (inline) functions...
+//////////////////////
+
+inline void Swap(int & in1, int & in2)
+{
+  const int tmp = in1;
+  in1 = in2;
+  in2 = tmp;
+}
+
+inline void Swap(double & in1, double & in2)
+{
+  const double tmp = in1;
+  in1 = in2;
+  in2 = tmp;
+}
+
+inline bool ToggleBool(bool & in_bool)
+{
+  if (in_bool == true) in_bool = false;
+  else in_bool = true;
+  return in_bool;
+}
+
+inline int Min(int in1, int in2)
+{
+  return (in1 > in2) ? in2 : in1;
+}
+
+inline int Max(int in1, int in2)
+{
+  return (in1 < in2) ? in2 : in1;
+}
+
+inline double Max(double in1, double in2)
+{
+  return (in1 < in2) ? in2 : in1;
+}
+
+inline int Range(int value, int min, int max)
+{
+  value = (value < min) ? min : value;
+  return (value > max) ? max : value;
+}
+
+inline int Mod(int value, int base)
+{
+  value %= base;
+  if (value < 0) value += base;
+  return value;
+}
+
+inline int Pow(int base, int expon)
+{
+  int value = 1;
+  for (int i = 0; i < expon; i++) value *= base;
+  return value;
+}
+
+inline double Log(double value)
+{
+  assert(value > 0);
+  return log(value);
+}
+
+/*
+ *   Special array functions...
+ */
+
+inline int Min(const tArray<int> & test_array)
+{
+  assert(test_array.GetSize() > 0);
+
+  int min_val = test_array[0];
+  for (int i = 1; i < test_array.GetSize(); i++) {
+    if (test_array[i] < min_val) min_val = test_array[i];
+  }
+  return min_val;
+}
+
+inline int Max(const tArray<int> & test_array)
+{
+  assert(test_array.GetSize() > 0);
+
+  int max_val = test_array[0];
+  for (int i = 1; i < test_array.GetSize(); i++) {
+    if (test_array[i] > max_val) max_val = test_array[i];
+  }
+  return max_val;
+}
+
+inline int Sum(const tArray<int> & test_array)
+{
+  int sum = 0;
+  for (int i = 0; i < test_array.GetSize(); i++) {
+    sum += test_array[i];
+  }
+  return sum;
+}
+
+inline int Neighbor(int cell_id, int size_x, int size_y, int diff_x, 
+                    int diff_y)
+{
+  // Routine to find a neighboring cell in an array that is
+  // pretending to be a matrix
+
+  int new_x = Mod(((cell_id % size_x) + diff_x), size_x);
+  int new_y = Mod(((cell_id / size_x) + diff_y), size_y);
+  return (new_y * size_x) + new_x;
+}
+
+// For QSORT in Divide_DoMutations ... MOVE THIS -- at TCC
+inline int IntCompareFunction(const void * a, const void * b)
+{
+  if( *((int*)a) > *((int*)b) ) return 1;
+  if( *((int*)a) < *((int*)b) ) return -1;
+  return 0;
+}
+
+#endif
Index: avida/current/source/tools/merit.cc
diff -u /dev/null avida/current/source/tools/merit.cc:1.6
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/merit.cc	Tue Nov 25 09:38:00 2003
@@ -0,0 +1,96 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#include "merit.hh"
+
+
+using namespace std;
+
+
+void cMerit::UpdateValue(double in_value){
+  const int max_bits = sizeof(unsigned int)*8;
+  static double mult[max_bits];
+  static bool mult_initilalized = false;
+
+  /*
+  XXX:
+  For some reason, if debugging with gdb, this assert fails when
+  in_value == 0.
+
+  temporarily disabled.  -- Kaben.
+  */
+  //assert( in_value >= 0 );
+
+  // Initilize multipliers only once
+  if( mult_initilalized == false ){
+    //cout<<"initializing multipliers"<<endl;
+    mult_initilalized = true;
+    for( int i=0; i<max_bits; ++i ){
+      mult[i] = pow((double)2,i);
+      //cout<<"  mult["<<i<<"] = "<<mult[i]<<endl;
+    }
+  }
+
+
+  value = in_value;
+
+  double mant = frexp (value , &bits);
+
+  //cout<<value<<" = "<<mant<<" * 2 ^ "<<bits<<endl;
+
+  if( bits > max_bits ){
+    offset = bits - max_bits;
+  }else{
+    offset = 0;
+  }
+
+  base = (unsigned int) (mant * mult[bits-offset-1] * 2 );
+
+  //cout<<value<<" = "<<base<<" ["<<bits<<" bits] "<<" * 2 ^ "<<offset;
+  //cout<<" = "<<(base * pow((double)2,offset))<<endl;
+}
+
+
+ostream & cMerit::BinaryPrint(ostream & os) const {
+  for( int i=GetNumBits()-1; i>=0; --i ){
+    os<<GetBit(i);
+  }
+  return os;
+}
+
+
+bool cMerit::OK() const {
+  double test_value = (double)base * pow((double)2,(int)offset);
+  int test_bits = (int)(log(value)/log((double)2)) + 1;
+  if( base == 0 ) test_bits = 0;
+
+  // Uncomment block for debugging output and assertion of OK
+  /*
+  cout<<"cMerit Ok? ";
+  cout<<base<<" * 2^"<<offset<<" = "<<test_value<<" ~= "<<value<<endl;
+  cout<<"\tnum_bits="<<GetNumBits()<<" ?= "<<test_bits<<endl;
+  BinaryPrint(cout)<<endl;
+
+  */
+  assert ( test_bits == bits &&
+	   ( test_value <= value * (1 + 1/UINT_MAX) ||
+	     test_value >= value / (1 + 1/UINT_MAX) ) );
+
+  return ( test_bits == bits &&
+	   ( test_value <= value * (1 + 1/UINT_MAX) ||
+	     test_value >= value / (1 + 1/UINT_MAX) ) );
+}
+
+
+
+
+ostream & operator<<(ostream & os, const cMerit & merit){
+  os<<merit.GetDouble();
+  return os;
+}
+
+
Index: avida/current/source/tools/merit.hh
diff -u /dev/null avida/current/source/tools/merit.hh:1.7
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/merit.hh	Tue Nov 25 09:38:00 2003
@@ -0,0 +1,83 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef MERIT_HH
+#define MERIT_HH
+
+#include <iostream>
+#include <math.h>
+#include <limits.h>
+#include <assert.h>
+
+#ifndef UINT
+#define UINT unsigned int
+#endif
+
+class cMerit {
+protected:
+  int bits;
+  UINT base;
+  UINT offset;
+  double value;
+
+  void UpdateValue(double in_value);
+
+public:
+  cMerit() : bits(0), base(0), offset(0), value(0) {;}
+
+  explicit cMerit(const int    in_value){ UpdateValue(in_value); }
+  explicit cMerit(const UINT   in_value){ UpdateValue(in_value); }
+  explicit cMerit(const double in_value){ UpdateValue(in_value); }
+
+  bool OK() const ;
+
+  void operator=(const cMerit & _merit){
+    bits   = _merit.bits;
+    base   = _merit.base;
+    offset = _merit.offset;
+    value  = _merit.value; }
+
+  void operator=(double _merit){ UpdateValue(_merit); }
+  void operator+=(const cMerit & _m){ UpdateValue(value + _m.GetDouble()); }
+
+  int  operator>(const cMerit & _m)  const { return value >  _m.GetDouble(); }
+  int  operator<(const cMerit & _m)  const { return value <  _m.GetDouble(); }
+  int  operator>=(const cMerit & _m) const { return value >= _m.GetDouble(); }
+  int  operator<=(const cMerit & _m) const { return value <= _m.GetDouble(); }
+
+  int  operator==(const cMerit & _m) const { return value == _m.GetDouble(); }
+  int  operator==(const double _m) const { return value == _m; }
+  int  operator==(const UINT _m)   const { return (offset==0 && base==_m); }
+
+  int  operator!=(const cMerit & _m) const { return value != _m.GetDouble(); }
+  int  operator!=(const double _m) const { return value != _m; }
+  int  operator!=(const UINT _m)   const { return (offset!=0 || base!=_m); }
+
+  void Clear() { value = 0; base = 0; offset = 0; bits = 0; }
+
+  // @TCC - This function fails for values > UINT_MAX...
+  UINT GetUInt()   const {
+    assert(value < UINT_MAX);  // Fails for merit values > UINT_MAX.
+    return (UINT) value; }
+
+  double GetDouble()      const { return value; }
+
+  int GetBit(UINT bit_num)  const {
+    return ( bit_num >= offset && bit_num < (UINT)bits ) ?
+			( base >> (bit_num-offset) ) & 1 : 0; }
+
+  int GetNumBits() const { return bits; }
+
+  double CalcFitness(int gestation_time) const {
+    return ( gestation_time != 0 ) ? value / ((double) gestation_time) : 0; }
+
+  std::ostream & BinaryPrint(std::ostream & os = std::cout) const ;
+};
+
+std::ostream & operator<<(std::ostream & os, const cMerit & merit);
+
+#endif
Index: avida/current/source/tools/message_display.cc
diff -u /dev/null avida/current/source/tools/message_display.cc:1.14
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/message_display.cc	Tue Nov 25 09:38:00 2003
@@ -0,0 +1,352 @@
+
+#ifndef _LIMITS_H___
+#include <limits.h>
+#endif
+#ifndef _STDIO_H_
+#include <stdio.h>
+#endif
+#ifndef _STDARG_H
+#include <stdarg.h>
+#endif
+
+#ifndef TRIO_TRIO_H
+#include "../third-party/trio/trio.h"
+#endif
+
+#ifndef _CPP_IOSTREAM
+#include <iostream>
+#endif
+
+#ifndef MESSAGE_DISPLAY_HDRS_HH
+#include "message_display_hdrs.hh"
+#endif
+
+
+using namespace std;
+
+
+/*
+pointers to the cMessageDisplay instantiations actually in use.
+each of the message classes gets a handle to one of the cMessageDisplay
+instantiations, so that by using the manipulator functions
+  void setStandardOutDisplay(cMessageDisplay &out)
+and
+  void setStandardErrDisplay(cMessageDisplay &err),
+the output and error messages can be redirected from, say, the console
+to a graphical window and back again (if you want).
+*/
+static cMessageDisplay *s_info_display;
+static cMessageDisplay *s_debug_display;
+static cMessageDisplay *s_error_display;
+static cMessageDisplay *s_fatal_display;
+static cMessageDisplay *s_noprefix_display;
+
+
+
+void setInfoDisplay(cMessageDisplay &info){
+  cout << "<setInfoDisplay>" << endl;
+  s_info_display = &info;
+  cout << "<setInfoDisplay> done." << endl;
+}
+void setDebugDisplay(cMessageDisplay &debug){
+  cout << "<setDebugDisplay>" << endl;
+  s_debug_display = &debug;
+  cout << "<setDebugDisplay> done." << endl;
+}
+void setErrorDisplay(cMessageDisplay &error){
+  cout << "<setErrorDisplay>" << endl;
+  s_error_display = &error;
+  cout << "<setErrorDisplay> done." << endl;
+}
+void setFatalDisplay(cMessageDisplay &fatal){
+  cout << "<setFatalDisplay>" << endl;
+  s_fatal_display = &fatal;
+  cout << "<setFatalDisplay> done." << endl;
+}
+void setNoPrefixDisplay(cMessageDisplay &noprefix){
+  cout << "<setNoPrefixDisplay>" << endl;
+  s_noprefix_display = &noprefix;
+  cout << "<setNoPrefixDisplay> done." << endl;
+}
+
+
+/*
+These booleans determine whether to print the function, file, and line
+number containing the message call.  The booleans are reset according to
+the contents of the environment variable "DEBUG_MESSAGING", which should
+be a comma-delimited list containing any of the three words
+  "chatter,where,function".
+
+Message types in the classes MCFatal and MCNoPrefix are always
+displayed; the remaining messages will only be displayed if
+DEBUG_MESSAGING contains "chatter".
+
+The line number and file containing the message call are printed if
+DEBUG_MESSAGING contains "where".
+
+The function containing the message call is printed only if
+DEBUG_MESSAGING contains "function".
+
+Note that message types of class "MCNoPrefix" will not print the
+function, file, or line number.
+*/
+static bool show_function = false;
+static bool show_where = false;
+static bool be_quiet = true;
+
+
+/*
+Definition of the five message classes.
+*/
+cMessageClass MCInfo("Info:", &s_info_display, false, false, false);
+cMessageClass MCDebug("Debug:", &s_debug_display, false, false, false);
+cMessageClass MCError("Error:", &s_error_display, false, true, false);
+cMessageClass MCFatal("Fatal:", &s_fatal_display, true, true, false);
+cMessageClass MCNoPrefix("NoPrefix:", &s_noprefix_display, false, true, true);
+
+/*
+cMessageClass constructor.
+*/
+cMessageClass::cMessageClass(
+  const char *class_name,
+  cMessageDisplay **msg_display,
+  bool is_fatal,
+  bool is_prefix,
+  bool no_prefix
+):m_class_name(class_name),
+  m_msg_display(msg_display),
+  m_is_fatal(is_fatal),
+  m_is_prefix(is_prefix),
+  m_no_prefix(no_prefix),
+  _configured(false)
+{
+  *msg_display = 0;
+}
+
+
+/*
+This configures the behavior of each cMessageClass and cMessageType
+according the contents of the environment variable DEBUG_MESSAGING.
+this is affected by setting the static booleans "show_function,
+show_where, be_quiet".
+
+These booleans determine whether to print the function, file, and line
+number containing the message call.  the booleans are reset according to
+the contents of the environment variable "DEBUG_MESSAGING", which should
+be a comma-delimited list containing any of the three words
+  "chatter,where,function".
+
+Message types in the classes MCFatal and MCNoPrefix are always
+displayed; the remaining messages will only be displayed if
+DEBUG_MESSAGING contains "chatter".
+
+The line number and file containing the message call are printed if
+DEBUG_MESSAGING contains "where".
+
+The function containing the message call is printed only if
+DEBUG_MESSAGING contains "function".
+
+Message types of class "MCNoPrefix" will not print the function, file,
+or line number.
+*/
+void
+cMessageClass::configure(cMessageType *message_type){
+  if(!_configured){
+    _configured = true;
+    char *denv = getenv("DEBUG_MESSAGING");
+    if(denv){
+      denv = strdup(denv);
+      char *tok = strtok(denv, ",");
+      while(tok){
+        if(strcmp(tok,"where") == 0){
+          show_where = true;
+        } else if (strcmp(tok,"function") == 0){
+          show_function = true;
+        } else if (strcmp(tok,"chatter") == 0){
+          be_quiet = false;
+        }
+        tok = strtok(NULL,",");
+      }
+      free(denv);
+    }
+  }
+  if( (this == &MCInfo)
+    ||(this == &MCDebug)
+    ||(this == &MCError)
+  ) message_type->m_is_active = !be_quiet;
+}
+
+
+/*
+cMessageType constructor.
+*/
+cMessageType::cMessageType(
+  const char *type_name,
+  cMessageClass &message_class
+):m_type_name(type_name),
+  m_message_class(message_class),
+  m_is_active(true)
+{ message_class.configure(this); }
+
+
+/*
+cMessageClosure constructor and destructor.
+*/
+cMessageClosure::cMessageClosure(
+  cMessageType &type,
+  const char *function_name,
+  const char *file_name,
+  int line_number
+):_type(type),
+  _function(function_name),
+  _file(file_name),
+  _line(line_number),
+  _error(INT_MAX),
+  _op_count(0)
+{}
+
+cMessageClosure::~cMessageClosure(void){
+  if(!(*_type.m_message_class.m_msg_display)){
+    cerr << "<~cMessageClosure> WARNING:" << endl;
+    cerr << "<~cMessageClosure> message display classes not fully initialized;" << endl;
+    cerr << "<~cMessageClosure> directing messages of class \""
+      << cString(_type.m_type_name)
+      << "\" to its default output device..." << endl;
+    if(&_type.m_message_class == &MCInfo) {
+      (*_type.m_message_class.m_msg_display) = &s_info_msg_cout;
+    } else if(&_type.m_message_class == &MCDebug) {
+      (*_type.m_message_class.m_msg_display) = &s_debug_msg_cerr;
+    } else if(&_type.m_message_class == &MCError) {
+      (*_type.m_message_class.m_msg_display) = &s_error_msg_cerr;
+    } else if(&_type.m_message_class == &MCFatal) {
+      (*_type.m_message_class.m_msg_display) = &s_fatal_msg_cerr;
+    } else if(&_type.m_message_class == &MCNoPrefix) {
+      (*_type.m_message_class.m_msg_display) = &s_noprefix_msg_cout;
+    } else {
+      (*_type.m_message_class.m_msg_display) = &s_noprefix_msg_cout;
+    }
+  }
+  (*_type.m_message_class.m_msg_display)->out(_msg);
+  if(_type.m_message_class.m_is_fatal) (*_type.m_message_class.m_msg_display)->abort();
+}
+
+
+/*
+Pretty-printing for cMessageClosure.
+*/
+void
+cMessageClosure::prefix(void){
+  if(_op_count++ == 0 && !_type.m_message_class.m_no_prefix){
+    if(_type.m_message_class.m_is_prefix){
+      _msg += _type.m_type_name;
+      _msg += '-';
+    }
+    _msg += _type.m_message_class.m_class_name;
+    if(!_type.m_message_class.m_is_prefix || show_function || show_where){
+      bool colon = false;
+      if(!_type.m_message_class.m_is_prefix){
+        _msg += _type.m_type_name;
+        _msg += ": ";
+      }
+      if(show_function || show_where){
+        _msg += "<";
+      }
+      if(show_function){
+        _msg += _function;
+        colon = true;
+      }
+      if(show_where){
+        if(colon){_msg += ':';}
+        _msg += _file;
+        _msg += ':';
+        // FIXME:  consider move this varargs gunk to cString.  -- kgn.
+        {
+          int size = trio_snprintf((char *) 0, 0, "%i", _line);
+          char *buf = new char[size + 1];
+          assert(buf != 0);
+          trio_snprintf(buf, size+1, "%i", _line);
+          _msg += buf;
+          delete[] buf;
+        }
+      }
+      if(show_function || show_where){
+        _msg += ">";
+      }
+      _msg += ' ';
+    } else {
+      _msg += ':';
+    }
+  }
+}
+
+
+/*
+cMessageClosure::va():
+
+Support for cString-based operator<< and operator() definitions in
+cMessageClosure.  Variable argument lists are formatted and then printed
+into a temporary buffer; the contents of this buffer are then appended
+to the cString _msg.
+*/
+
+// FIXME:  consider move this varargs gunk to cString.  -- kgn.
+cMessageClosure &
+cMessageClosure::va(const char *fmt, ...)
+{
+  va_list ap;
+
+  va_start(ap, fmt);
+  int size = trio_vsnprintf((char *) 0, 0, fmt, ap);
+  va_end(ap);
+
+  char *buf = new char[size + 1];
+  assert(buf != 0);
+
+  va_start(ap, fmt);
+  trio_vsnprintf(buf, size+1, fmt, ap);
+  va_end(ap);
+
+  prefix();
+  _msg += buf;
+  delete[] buf;
+
+  return *this;
+}
+
+/*
+operator<< and operator() definitions for cMessageClosure.
+
+Any kind of input can be placed behind the operator<<, really, but try
+to not (further) overcrowd the class...
+
+The operator is meant to convert its input into a string for display.
+If for example you implement
+  cMessageClosure &operator<<(const myClass &instance);
+then you can write a message thus:
+  DemoDebug << "this is a myClass instance: " << my_instance;
+with the result:
+  "Debug [Demo] this is a myClass instance: stuff in my_instance."
+*/
+cMessageClosure &cMessageClosure::operator<<(char c){ prefix(); _msg += c; return *this; }
+cMessageClosure &cMessageClosure::operator<<(unsigned char c){ prefix(); _msg += c; return *this; }
+cMessageClosure &cMessageClosure::operator<<(int i){ return va("%d", i); }
+cMessageClosure &cMessageClosure::operator<<(unsigned int i){ return va("%u", i); }
+cMessageClosure &cMessageClosure::operator<<(long i){ return va("%ld", i); }
+cMessageClosure &cMessageClosure::operator<<(unsigned long i){ return va("%lu", i); }
+cMessageClosure &cMessageClosure::operator<<(float f){ return va("%g", f); }
+cMessageClosure &cMessageClosure::operator<<(double f){ return va("%g", f); }
+cMessageClosure &cMessageClosure::operator<<(const void *p){ return va("%p", p); }
+cMessageClosure &cMessageClosure::operator<<(const char *s){ prefix(); _msg += s; return *this; }
+
+/*
+Definition of the message type "NoPrefix_Msg".
+*/
+cMessageType NoPrefix_Msg("NoPrefix", MCNoPrefix);
+cMessageType Info_GEN_Msg("General", MCInfo);
+cMessageType Debug_GEN_Msg("General", MCDebug);
+cMessageType Error_GEN_Msg("General", MCError);
+cMessageType Fatal_GEN_Msg("General", MCFatal);
+
+
+
+
Index: avida/current/source/tools/message_display.hh
diff -u /dev/null avida/current/source/tools/message_display.hh:1.12
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/message_display.hh	Tue Nov 25 09:38:00 2003
@@ -0,0 +1,38 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef MESSAGE_DISPLAY_HH
+#define MESSAGE_DISPLAY_HH
+
+/*
+cMessageDisplay displays the message "final_msg" to the user/programmer.
+cMessageDisplay is meant to be subclassed, where
+  out(string final_msg)
+is reimplemented to display "final_msg" in the desired manner. 
+
+Instances of the subclass may then be passed to
+  setStandardOutDisplay(cMessageDisplay &)
+and
+  setStandardErrDisplay(cMessageDisplay &)
+with expected results.
+*/
+
+class cString;
+
+class cMessageDisplay{
+public:
+  virtual void out(cString &final_msg){}
+  virtual void abort(){ abort(); }
+};
+
+void setInfoDisplay(cMessageDisplay &info);
+void setDebugDisplay(cMessageDisplay &debug);
+void setErrorDisplay(cMessageDisplay &error);
+void setFatalDisplay(cMessageDisplay &fatal);
+void setNoPrefixDisplay(cMessageDisplay &noprefix);
+
+#endif
Index: avida/current/source/tools/message_display_hdrs.hh
diff -u /dev/null avida/current/source/tools/message_display_hdrs.hh:1.4
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/message_display_hdrs.hh	Tue Nov 25 09:38:00 2003
@@ -0,0 +1,41 @@
+#ifndef MESSAGE_DISPLAY_HDRS_HH
+#define MESSAGE_DISPLAY_HDRS_HH
+
+#ifndef _CPP_IOSTREAM
+#include <iostream>
+#endif
+#ifndef DEFAULT_MESSAGE_DISPLAY_HH
+#include "default_message_display.hh"
+#endif
+#ifndef MESSAGE_CLASS_HH
+#include "message_class.hh"
+#endif
+#ifndef MESSAGE_CLOSURE_HH
+#include "message_closure.hh"
+#endif
+#ifndef MESSAGE_DISPLAY_HH
+#include "message_display.hh"
+#endif
+#ifndef MESSAGE_TYPE_HH
+#include "message_type.hh"
+#endif
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+
+#ifndef MESSAGE_DISPLAY_HH
+#include "message_display.hh"
+#endif
+
+extern cMessageType NoPrefix_Msg;
+extern cMessageType Info_GEN_Msg;
+extern cMessageType Debug_GEN_Msg;
+extern cMessageType Error_GEN_Msg;
+extern cMessageType Fatal_GEN_Msg;
+#define Message _PLAIN_MSG(NoPrefix)
+#define GenInfo _INFO_MSG(GEN)
+#define GenDebug _DEBUG_MSG(GEN)
+#define GenError _ERROR_MSG(GEN)
+#define GenFatal _FATAL_MSG(GEN)
+
+#endif
Index: avida/current/source/tools/random.cc
diff -u /dev/null avida/current/source/tools/random.cc:1.10
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/random.cc	Tue Nov 25 09:38:00 2003
@@ -0,0 +1,216 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2000 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef RANDOM_HH
+#include "random.hh"
+#endif
+
+#ifndef TARRAY_HH
+#include "tArray.hh"
+#endif
+
+/* FIXME this is not defined in Visual Studio.net. -- kgn */
+//#ifdef MSVC_COMPILER
+/* FIXME find out what the VS.n macro might be. for now use WIN32 -- kgn */
+#ifdef WIN32
+#include <process.h>
+#else
+#include <unistd.h>
+#endif
+
+
+// Constants //////////////////////////////////////////////////////////////////
+
+// Statistical Approximation
+const unsigned int cRandom::_BINOMIAL_TO_NORMAL=50;    //if < n*p*(1-p)
+const unsigned int cRandom::_BINOMIAL_TO_POISSON=1000; //if < n
+
+// Engine
+const unsigned int cRandom::_RAND_MBIG=1000000000;
+const unsigned int cRandom::_RAND_MSEED=161803398;
+
+// Number Generation
+const double cRandom::_RAND_FAC=(1.0/_RAND_MBIG);
+const double cRandom::_RAND_mP_FAC=(_RAND_MBIG/1000);
+const double cRandom::_RAND_uP_FAC=(_RAND_MBIG/1000000);
+
+
+// Constructor and setup //////////////////////////////////////////////////////
+
+cRandom::cRandom(const int in_seed) :
+ seed(0),
+ original_seed(0),
+ inext(0),
+ inextp(0),
+ use_count(0),
+ expRV(0)
+  {
+    for( int i=0; i<56; ++i ){
+      ma[i] = 0;
+    }
+    ResetSeed(in_seed);  // Calls init()
+  }
+
+
+void cRandom::ResetSeed(const int in_seed){
+  //if( in_seed<0 ){  // @TCC - make 0 also be seeded with time * pid
+  original_seed = in_seed;
+  
+  if( in_seed<=0 ){
+    int seed_time = (int) time(NULL);
+#ifdef MSVC_COMPILER
+    int seed_pid = (int) _getpid(); 
+#else
+    int seed_pid = (int) getpid(); 
+#endif
+    seed = seed_time ^ (seed_pid << 8);
+  }
+  else {
+    seed = in_seed;
+  }
+  
+  if( seed < 0 ) seed*=-1;
+  seed%=_RAND_MSEED;
+
+  init();
+  initStatFunctions();
+}
+
+
+void cRandom::init(){
+  int mj, mk, ii, i;
+
+  // Clear variables
+  inext = 0;
+  inextp = 0;
+  expRV = 0;
+  for( i=0; i<56; ++i ){
+    ma[i] = 0;
+  }
+
+  mj = _RAND_MSEED - seed;
+  mj %= _RAND_MBIG;
+  ma[55] = mj;
+  mk = 1;
+
+  for (i = 1; i < 55; ++i) {
+    ii = (21 * i) % 55;
+    ma[ii] = mk;
+    mk = mj - mk;
+    if (mk < 0) mk += _RAND_MBIG;
+    mj = ma[ii];
+  }
+
+  for (int k = 0; k < 4; ++k) {
+    for (int j = 1; j < 55; ++j) {
+      ma[j] -= ma[1 + (j + 30) % 55];
+      if (ma[j] < 0) ma[j] += _RAND_MBIG;
+    }
+  }
+
+  inext = 0;
+  inextp = 31;
+}
+
+void cRandom::initStatFunctions(){
+  // Setup variables used by Statistical Distribution functions
+  expRV=-log(GetDouble());
+}
+  
+
+// Statistical functions //////////////////////////////////////////////////////
+
+double cRandom::GetRandNormal(){
+  // Draw from a Unit Normal Dist
+  // Using Rejection Method and saving of initial exponential random variable
+  double expRV2;
+  while( 1 ){
+    expRV2=-log(GetDouble());
+    expRV-=(expRV2-1)*(expRV2-1)/2;
+    if( expRV>0 ) break;  
+    expRV=-log(GetDouble());
+  }
+  if( P(.5) ) 
+    return expRV2;
+  else
+    return -expRV2;
+}
+
+unsigned int cRandom::GetRandPoisson(const double mean){
+  // Draw from a Poisson Dist with mean
+  // if cannot calculate, returns UINT_MAX
+  // Uses Rejection Method
+  unsigned int k=0;
+  double a=exp(-mean);
+  double u=GetDouble();
+  if( a <=0 ) return UINT_MAX; // cannot calculate, so return UINT_MAX
+  while( u>=a ){
+    u*=GetDouble();
+    ++k;
+  }
+  return k;
+}
+
+unsigned int cRandom::GetFullRandBinomial(const double n, const double p){
+  // Actually try n Bernoulli events with probability p
+  unsigned int k=0;
+  for( unsigned int i=0; i<n; ++i )
+    if( P(p) ) k++;
+  return k;
+}
+
+unsigned int cRandom::GetRandBinomial(const double n, const double p){
+  // Approximate Binomial if appropriate
+  // if np(1-p) is large, use a Normal approx
+  if( n*p*(1-p) >= _BINOMIAL_TO_NORMAL ){
+    return (unsigned int)(GetRandNormal(n*p,n*p*(1-p))+.5);
+  }
+  // elseif n is large, use a Poisson approx
+  if( n >= _BINOMIAL_TO_POISSON ){
+    unsigned int k=GetRandPoisson(n,p);
+    if( k < UINT_MAX ) // if approx worked
+      return k;
+  }
+  // otherwise, actually generate the randBinomial
+  return GetFullRandBinomial(n,p);
+}
+
+
+bool cRandom::Choose(int num_in, tArray<int> & out_array){
+  // If you ask for more than you pass in...
+  assert ( num_in >= out_array.GetSize() );
+
+  if (num_in == out_array.GetSize()) {
+    // init array to 0's
+    for(int i = 0; i < out_array.GetSize(); i++)  out_array[i] = i;
+    return true;
+  }
+
+  int choice_num = 0;
+  // @CAO this could be done a lot faster when choose size is close to
+  // full size.  However we need to rememebr to watch out for larger num_in
+  while (choice_num < out_array.GetSize()) {
+    int next = (int) GetUInt(num_in);
+
+    // See if this choice is ok to use...
+    bool ok = true;
+    for (int i = 0; i < choice_num; i++) {
+      if (out_array[i] == next) {
+	ok = false;
+	break;
+      }
+    }
+
+    // And if its good, record it.
+    if (ok == true) {
+      out_array[choice_num] = next;
+      choice_num++;
+    }
+  }
+
+  return true;
+}
Index: avida/current/source/tools/random.hh
diff -u /dev/null avida/current/source/tools/random.hh:1.11
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/random.hh	Tue Nov 25 09:38:00 2003
@@ -0,0 +1,270 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+/******************************************************************************
+
+cRandom
+
+Random number generator
+Random variables from various statistical distributions
+
+******************************************************************************/
+
+#ifndef RANDOM_HH
+#define RANDOM_HH
+
+#include <time.h>
+#include <limits.h>
+#include <math.h>
+
+#ifndef UINT
+#define UINT unsigned int
+#endif
+
+/**
+ * A versatile and fast pseudo random number generator.
+ **/
+
+template <class T> class tArray;
+
+class cRandom{
+public:
+  /**
+   * Set up the random generator object.
+   * @param in_seed The seed of the random number generator. 
+   * A negative seed means that the random number generator gets its
+   * seed from the actual system time.
+   **/
+  cRandom(const int in_seed=-1);
+  
+  inline int GetUseCount() { return use_count; }
+  
+  
+  /**
+   * @return The seed that was actually used to start the random sequence.
+   **/
+  inline int GetSeed(){ return seed; }
+  
+  /**
+   * @return The seed that was originally provided by the user.
+   **/
+  inline int GetOriginalSeed(){ return original_seed; }
+  
+  /**
+   * Starts a new sequence of pseudo random numbers.
+   *
+   * @param new_seed The seed for the new sequence.
+   * A negative seed means that the random number generator gets its
+   * seed from the actual system time.
+   **/
+  void ResetSeed(const int new_seed);
+  
+  
+  // Random Number Generation /////////////////////////////////////////////////
+  
+  /**
+   * Generate a double between 0 and 1.
+   *
+   * @return The pseudo random number.
+   **/
+  inline double GetDouble(){ return Get()*_RAND_FAC; }
+  
+  /**
+   * Generate a double between 0 and a given number.
+   *
+   * @return The pseudo random number.
+   * @param max The upper bound for the random numbers (will never be returned).
+   **/
+  inline double GetDouble(const double max){ return GetDouble() * max;}
+  
+  /**
+   * Generate a double out of a given interval.
+   *
+   * @return The pseudo random number.
+   * @param min The lower bound for the random numbers.
+   * @param max The upper bound for the random numbers (will never be returned).
+   **/
+  inline double GetDouble(const double min, const double max){
+    return GetDouble()*(max-min)+min;}
+  
+  /**
+   * Generate an unsigned int.
+   *
+   * @return The pseudo random number.
+   * @param max The upper bound for the random numbers (will never be returned).
+   **/
+  inline unsigned int GetUInt(const unsigned int max){
+    return (int) (GetDouble()*max);}
+  
+  /**
+   * Generate an unsigned int out of an interval.
+   *
+   * @return The pseudo random number.
+   * @param min The lower bound for the random numbers.
+   * @param max The upper bound for the random numbers (will never be returned).
+     **/
+  inline unsigned int GetUInt(const unsigned int min, const unsigned int max){
+    return GetUInt(max-min+1)+min; }
+  
+  /**
+   * Generate an int out of an interval.
+   *
+   * @return The pseudo random number.
+   * @param min The lower bound for the random numbers.
+   * @param max The upper bound for the random numbers (will never be returned).
+   **/
+  inline int GetInt(const int max){
+    return (int)GetUInt(max); }
+  inline int GetInt(const int min, const int max){
+    return ((int)GetUInt(max-min+1))+min; }
+  
+  
+  // Random Event Generation //////////////////////////////////////////////////
+  
+  // P(p) => if p < [0,1) random variable
+  inline bool P(const double _p){
+    return (Get()<(_p*_RAND_MBIG));}
+  inline bool mP(const double _p){	// p = _p*10^-3
+    return (Get()<_RAND_mP_FAC && Get()<(_p*_RAND_MBIG));}
+  inline bool uP(const double _p){	// p = _p*10^-6
+    return (Get()<_RAND_uP_FAC && Get()<(_p*_RAND_MBIG));}
+  inline bool pP(const double _p){	// p = _p*10^-6
+    return (Get()<_RAND_uP_FAC && Get()<_RAND_uP_FAC &&
+	    Get()<(_p*_RAND_MBIG));}
+
+
+  // Other neat stuff /////////////////////////////////////////////////////////
+  inline UINT MutateByte(UINT value);
+  inline UINT ClearByte(UINT value);
+  inline UINT MutateBit(UINT value);
+  inline UINT MutateBit(UINT value, int in_byte);
+
+  bool Choose(int num_in, tArray<int> & out_array);
+
+
+  // Statistical functions ////////////////////////////////////////////////////
+
+  // Distributions //
+
+  /**
+   * Generate a random variable drawn from a unit normal distribution.
+   **/
+  double GetRandNormal();
+  /**
+   * Generate a random variable drawn from a distribution with given
+   * mean and variance.
+   **/
+  inline double GetRandNormal(const double mean, const double variance){
+    return mean+GetRandNormal()*sqrt(variance);
+  }
+  
+  /**
+   * Generate a random variable drawn from a Poisson distribution.
+   **/
+  inline unsigned int GetRandPoisson(const double n, double p) {
+    // Optimizes for speed and calculability using symetry of the distribution
+    if( p>.5 ) return (unsigned int)n-GetRandPoisson(n*(1-p));
+    else return GetRandPoisson(n*p);
+  }
+  
+  /**
+   * Generate a random variable drawn from a Poisson distribution.
+   *
+   * @param mean The mean of the distribution.
+   **/
+  unsigned int GetRandPoisson(const double mean);
+  
+  /**
+   * Generate a random variable drawn from a Binomial distribution.
+   * 
+   * This function is exact, but slow. 
+   * @see cRandom::GetRandBinomial
+   **/
+  unsigned int GetFullRandBinomial(const double n, const double p); // Exact
+  
+  /**
+   * Generate a random variable drawn from a Binomial distribution.
+   * 
+   * This function is faster than @ref cRandom::GetFullRandBinomial(), but 
+   * uses some approximations.
+   *
+   * @see cRandom::GetFullRandBinomial
+   **/  
+  unsigned int GetRandBinomial(const double n, const double p); // Approx
+  
+  
+  // Internals ////////////////////////////////////////////////////////////////
+private:
+  // Internal memebers
+  int seed;
+  int original_seed;
+  int inext;
+  int inextp;
+  int ma[56];
+  int use_count;
+
+  // Constants ////////////////////////////////////////////////////////////////
+  // Statistical Approximation
+  static const unsigned int _BINOMIAL_TO_NORMAL;  //if < n*p*(1-p)
+  static const unsigned int _BINOMIAL_TO_POISSON; //if < n && !Normal approx
+  // Engine
+  static const unsigned int _RAND_MBIG;
+  static const unsigned int _RAND_MSEED;
+  // Number Generation
+  static const double _RAND_FAC;
+  static const double _RAND_mP_FAC;
+  static const double _RAND_uP_FAC;
+
+  // Members & functions for stat functions
+  double expRV; // Exponential Random Variable for the randNormal function
+
+  // Internal functions
+  void init();	// Setup  (called by ResetSeed(in_seed);
+  void initStatFunctions();
+
+  // Basic Random number
+  // Returns a random number [0,_RAND_MBIG)
+  inline unsigned int Get(){
+    // use_count++;  // Turn this on if random uses need to be tracked.
+
+    if (++inext == 56) inext = 0;
+    if (++inextp == 56) inextp = 0;
+    int mj = ma[inext] - ma[inextp];
+    if (mj < 0) mj += _RAND_MBIG;
+    ma[inext] = mj;
+    return mj;
+  }
+
+};
+
+inline UINT cRandom::MutateByte(UINT value) {
+  int byte_pos = 8 * GetUInt(4);
+  int new_byte = GetUInt(256);
+  value &= ~(255 << byte_pos);
+  value |= new_byte << byte_pos;
+  return value;
+}
+
+inline UINT cRandom::ClearByte(UINT value) {
+  int byte_pos = 8 * GetUInt(4);
+  value &= ~(255 << byte_pos);
+  return value;
+}
+
+inline UINT cRandom::MutateBit(UINT value) {
+  int bit_pos = GetUInt(32);
+  value ^= (1 << bit_pos);
+  return value;
+}
+
+inline UINT cRandom::MutateBit(UINT value, int in_byte) {
+  int bit_pos = (in_byte) * 8 + GetUInt(8);
+  value ^= (1 << bit_pos);
+  return value;
+}
+
+#endif
Index: avida/current/source/tools/string.cc
diff -u /dev/null avida/current/source/tools/string.cc:1.15
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/string.cc	Tue Nov 25 09:38:00 2003
@@ -0,0 +1,641 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#include "string.hh"
+
+extern "C"{
+#include <stdio.h>
+#include <stdarg.h>
+}
+
+
+using namespace std;
+
+
+// ** class cStringData **
+// -- Constructors --
+cString::cStringData::cStringData(unsigned short in_size)
+  : refs(1)
+  , size(in_size)
+  , data(new char[size+1])
+{
+  assert(data!=NULL); // Memory Allocation Error: Out of Memory
+  data[0] = '\0';
+  data[size] = '\0';
+}
+
+cString::cStringData::cStringData(unsigned short in_size, const char * in)
+  : refs(1)
+  , size(in_size)
+  , data(new char[size+1])
+{
+  assert(data!=NULL); // Memory Allocation Error: Out of Memory
+  for( unsigned short i=0; i<size; ++i )  data[i]=in[i];
+  data[size] = '\0';
+}
+
+cString::cStringData::cStringData(const cStringData & in)
+  : refs(1)
+  , size(in.GetSize())
+  , data(new char[size+1])
+{
+  assert(data!=NULL); // Memory Allocation Error: Out of Memory
+  for( unsigned short i=0; i<size; ++i )  data[i]=in[i];
+  data[size] = '\0';
+}
+
+
+
+// ** class cString **
+
+// -- Constants --
+const int cString::MAX_LENGTH = MAX_STRING_LENGTH;
+
+
+// -- Comparisons --
+
+bool cString::operator== (const cString & in) const {
+  // Compares sizes first since we have that info anyway
+  int i=-1;
+  if( GetSize() == in.GetSize() ){
+    for( i=0; i<GetSize() && (*this)[i]==in[i]; ++i );
+  }
+  return ( i == GetSize() );  // i == GetSize if all chars matched
+}
+
+
+int cString::Compare(const char * in) const
+{
+  // -1 (*this<in), 0 (*this==in), 1 (*this>in) ... just like strcmp()
+  assert(in!=NULL);  // NULL input string
+  int i;
+  for( i = 0;
+       i < GetSize() && in[i]!='\0' && (*this)[i] == in[i];
+       i++ );
+
+  if( i == GetSize()  &&  in[i] == '\0' ) {
+    return 0;                // *this == in
+  }
+
+  // They're not equal!
+  if ( i < GetSize() && (*this)[i] > in[i] )  return 1;  // *this > in
+  return -1;                                             // *this < in
+}
+
+bool cString::IsContinueLine()
+{
+  bool found = false;
+  bool goodstufffound = false;
+  int j = GetSize() - 1;
+
+  // Scan the line from the end.  If the last non-whitespace line is
+  // continueation character the line expects a line to be concatenated on
+  // to it
+
+  while ((j >= 0) && !found && !goodstufffound) {
+    if (!IsWhitespace(j)) {
+      if ((*this)[j] == CONTINUE_LINE_CHAR) {
+        found = true;
+        RemovePos(j);
+      } else {
+        goodstufffound = true;
+      }
+    }
+    j--;
+  }
+  return (found);
+}
+
+// -- Information --
+
+int cString::CountWhitespace(int start) const
+{
+  assert(start >= 0); // Negative Index into String
+  if (start >= GetSize()) return 0;
+  int count = 0;
+  while (start+count<GetSize() && IsWhitespace(start+count)) count++;
+  return count;
+}
+
+
+int cString::CountWordsize(int start) const {
+  assert(start >= 0); // Negative Index into String
+  if( start>=GetSize() )  return 0;
+  int count = 0;
+  while( start+count<GetSize() && !IsWhitespace(start+count) )
+    ++count;
+  return count;
+}
+
+
+int cString::CountLinesize(int start) const
+{
+  assert(start >= 0); // Negative Index into String
+  if( start>=GetSize() )  return 0;
+  int count = 0;
+  while( start+count<GetSize() && (*this)[start+count]!='\n' )
+    count++;
+  return count;
+}
+
+
+int cString::CountNumLines() const
+{
+  int num_lines = 1;
+  for( int i=0; i<GetSize(); ++i ){
+    if( (*this)[i] == '\n' )  num_lines++;
+  }
+  return num_lines;
+}
+
+
+int cString::CountNumWords() const
+{
+  int num_words = 0;
+  int pos = CountWhitespace();     // Skip initial whitespace.
+  while( pos<GetSize() ) {
+    pos += CountWordsize(pos);
+    pos += CountWhitespace(pos);
+    num_words++;
+  }
+  return num_words;
+}
+
+
+// -- Search --
+int cString::Find(char in_char, int start) const
+{
+  int pos = start;
+  assert (pos >= 0);         // Negative Position: setting to 0
+  assert (pos <= GetSize()); // Position Past End of String: setting to end.
+  if (pos <= 0) pos = 0;
+  else if (pos > GetSize()) pos = GetSize();
+
+  while( pos < GetSize() ) {
+    if( (*this)[pos] == in_char) return pos; // Found!
+    pos++;
+  }
+  return -1; // Not Found
+}
+
+
+int cString::FindWord(const cString & in, int pos) const
+{
+  assert (pos >= 0);         // Negative Position: setting to 0
+  assert (pos <= GetSize()); // Position Past End of String: setting to end.
+  if (pos <= 0) pos = 0;
+  else if (pos > GetSize()) pos = GetSize();
+
+  // While there is enough space to find
+  while (pos != -1 && pos + in.GetSize() < GetSize()) {
+    cerr << in << " " << pos << endl;
+    if( (pos=Find(in, pos)) >= 0 ){      // try to find it
+      // if it's got whitespace on both sides, it's a word
+      if( ( pos==0 || IsWhitespace(pos-1) )
+	  && ( pos==GetSize()-1 || IsWhitespace(pos+in.GetSize()) ) ){
+	return pos;
+      } else {
+	pos++; // go on and look further down
+      }
+    }
+  }
+  return -1;
+}
+	
+
+cString cString::GetWord(int word_id) const
+{
+  // Find positon of word
+  int pos = 0;
+  int cur_word = 0;
+  while( pos<GetSize() && cur_word<word_id ) {  // If this isn't the word
+    pos += CountWhitespace(pos);                 // Skip leading whitespace
+    pos += CountWordsize(pos);                   // Skip this word
+    cur_word++;
+  }
+  // Return GetWordAt position... (it will skip any leading whitespace)
+  return GetWordAt(pos);
+}
+
+
+cString cString::GetWordAt(int start) const
+{
+  int pos = start + CountWhitespace(start);  // Skip past initial whitespace.
+  int word_size = CountWordsize(pos);        // Get size of word
+  cString new_string(word_size);             // Allocate new_string that size
+  for (int i = 0; i < word_size; i++) {      // Copy the chars to new_string
+    new_string[i] = (*this)[pos + i];
+  }
+  return new_string;
+}
+
+bool cString::IsWhitespace() const
+{
+  for( int i=0; i < GetSize(); ++i){
+    if ( IsWhitespace(i) == false ) return false;
+  }
+  return true;
+}
+
+bool cString::IsUpperLetter() const
+{
+  for (int i = 0; i < GetSize(); ++i) {
+    if ( IsUpperLetter(i) == false ) return false;
+  }
+  return true;
+}
+
+bool cString::IsLowerLetter() const
+{
+  for (int i = 0; i < GetSize(); ++i) {
+    if ( IsLowerLetter(i) == false ) return false;
+  }
+  return true;
+}
+
+bool cString::IsLetter() const
+{
+  for (int i = 0; i < GetSize(); ++i) {
+    if ( IsLetter(i) == false ) return false;
+  }
+  return true;
+}
+
+bool cString::IsNumber() const
+{
+  for (int i = 0; i < GetSize(); ++i) {
+    if ( IsNumber(i) == false ) return false;
+  }
+  return true;
+}
+
+bool cString::IsNumeric() const
+{
+  for (int i = 0; i < GetSize(); ++i) {
+    if ( IsNumber(i) == false ) return false;
+  }
+  return true;
+}
+
+bool cString::IsAlphaNumeric() const
+{
+  for (int i = 0; i < GetSize(); ++i) {
+    if ( IsAlphaNumeric(i) == false ) return false;
+  }
+  return true;
+}
+
+
+
+cString cString::Substring(int start, int size) const
+{
+  assert(size > 0); // Non-Positive Size
+  assert(start >= 0); // Negative Position
+  assert(start + size <= GetSize()); // Position+Size Past End of String
+
+  cString new_string(size);
+  for (int i=0; i<size; i++) {
+    new_string[i] = (*this)[i+start];
+  }
+  return new_string;
+}
+
+bool cString::IsSubstring(const cString & in_string, int start) const
+{
+  assert (start >= 0); // Negative start position
+
+  // If the potential sub-string won't fit, return false;
+  if ( start + in_string.GetSize() > GetSize() ) return false;
+
+  // Otherwise, check character by character.
+  for (int i = 0; i < in_string.GetSize(); i++) {
+    if ( (*this)[i+start] != in_string[i] ) return false;
+  }
+
+  return true;
+}
+
+
+// -- Modifiers --
+
+cString & cString::Set(const char * fmt, ...)
+{
+  va_list argp;
+  char buf[MAX_LENGTH];
+  va_start(argp, fmt);
+  vsprintf(buf, fmt, argp);
+  va_end(argp);
+  (*this) = buf;
+  return *this;
+}
+
+
+int cString::Replace(const cString & old_st, const cString & new_st, int pos)
+{
+  int location;
+  if( (location=Find(old_st, pos)) >= 0 ){ // If we find the old_st
+    Insert(new_st, location, old_st.GetSize());
+  }
+  return location;
+}
+
+
+int cString::LeftJustify()
+{
+  int ws_count = CountWhitespace();
+  if( ws_count>0 )
+    InsertStr(0, NULL, 0, ws_count);
+  return ws_count;
+}
+
+
+int cString::RightJustify()
+{
+  int ws_count = 0;
+  while( GetSize()-ws_count-1>0 && IsWhitespace(GetSize()-ws_count-1) )
+    ws_count++;
+  if( ws_count>0 )
+    InsertStr(0, NULL, GetSize()-ws_count, ws_count);
+  return ws_count;
+}
+
+
+cString cString::Pop(const char delim)
+{
+  int pos;
+  cString rv("");
+  if( (pos=Find(delim)) >= 0 ){ // if it is found at all
+    if( pos > 0 ){  // if the first char is not delim, return substring
+      rv = Substring(0,pos);
+    }
+    // Trim off the front
+    InsertStr(0, NULL, 0, pos+1);
+  }
+
+  // If the deliminator is *not* found, return the whole string.
+  else {
+    rv = *this;
+    *this = "";
+  }
+  return rv;
+}
+
+
+cString cString::PopWord()
+{
+  // If there is nothing here, there is nothing to be popped.
+  if (GetSize() == 0) return "";
+
+  const int start_pos = CountWhitespace();
+  const int word_size = CountWordsize(start_pos);
+
+  // If the string is not all whitespace, save the word we cut off...
+  cString rv("");
+  if (word_size > 0) rv = Substring(start_pos, word_size);
+
+  // Trim off the front
+  const int word_end = start_pos + word_size;
+  const int new_start = word_end + CountWhitespace(word_end);
+  InsertStr(0, NULL, 0, new_start);  // Insert null in place of old word.
+
+  return rv;
+}
+
+
+cString & cString::ToLower()
+{
+  for (int pos = 0; pos < GetSize(); pos++) {
+    if( (*this)[pos] >= 'A' && (*this)[pos] <= 'Z' )
+      (*this)[pos] += 'a' - 'A';
+  }
+
+  return *this;
+}
+
+
+cString & cString::ToUpper()
+{
+  for (int pos = 0; pos < GetSize(); pos++) {
+    if( (*this)[pos] >= 'a' && (*this)[pos] <= 'z' )
+      (*this)[pos] += 'A' - 'a';
+  }
+
+  return *this;
+}
+
+
+void cString::Reverse()
+{
+  cString new_st(GetSize());
+  for( int i=0; i<GetSize(); ++i ){
+    // new_st[i] = (*this)[GetSize()-i-1];       // @CAO Problem in new gcc
+    new_st[i] = GetData()[GetSize()-i-1];
+  }
+  (*this) = new_st;
+}
+
+
+void cString::CompressWhitespace()
+{
+  // Eats initial whitespace
+  // 2 pass method...
+  int i;
+  int pos = 0;
+  int start_pos = CountWhitespace();
+  int new_size = 0;
+  bool ws = false;
+
+  // count the number of characters that we will need in the new string
+  for( i=start_pos; i<GetSize(); ++i ){
+    if( IsWhitespace(i) ){ // if it whitespace...
+      if( ws == false ){     // if we arn't already in a whitespace block
+	ws = true;             // we are now in a whitespace block
+      }
+    }else{                 // it isn't whitespace, so count
+      if( ws==true ){        // if there was a whitespace block
+	++new_size;            // inc once for the block
+	ws = false;
+      }
+      ++new_size;
+    }
+  }
+
+  cString new_st(new_size);  // Allocate new string
+
+  // Copy over the characters
+  // pos will be the location in new_st, while i is the index into this
+  ws = false;
+  for( i=start_pos; i<GetSize(); ++i ){
+    if( IsWhitespace(i) ){ // if it whitespace...
+      if( ws == false ){     // if we arn't already in a whitespace block
+	ws = true;             // we are now in a whitespace block
+      }
+    }else{                 // it isn't whitespace, so count
+      if( ws==true ){        // if there was a whitespace block
+	new_st[pos] = ' ';     // put a space in for the whitespace block
+	++pos;                 // inc once for the block
+	ws = false;
+      }
+      // new_st[pos] = (*this)[i]; // copy it & increment pos  @CAO prob in gcc
+      new_st[pos] = GetData()[i]; // copy it & increment pos
+      ++pos;
+    }
+  }
+
+  (*this) = new_st;  // assign the new_st to this
+}
+
+
+void cString::RemoveWhitespace(){
+  int i;
+  int new_size = 0;
+  for( i=0; i<GetSize(); ++i ){  // count new size
+    if( !IsWhitespace(i) )  ++new_size;
+  }
+  cString new_st(new_size);      // allocate new string
+  int pos = 0;
+  for( i=0; i<GetSize(); ++i ){  // count new size
+    if( !IsWhitespace(i) ){
+      new_st[pos] = GetData()[i]; // copy it & increment pos   @CAO prob in GCC
+      ++pos;
+    }
+  }
+  (*this) = new_st;  // assign the new_st to this
+}
+
+
+void cString::RemoveChar(char out_char){
+  int i;
+  int new_size = 0;
+  for( i=0; i<GetSize(); ++i ){  // count new size
+    if( GetData()[i] != out_char )  ++new_size;
+  }
+  cString new_st(new_size);      // allocate new string
+  int pos = 0;
+  for( i=0; i<GetSize(); ++i ){  // count new size
+    if( GetData()[i] != out_char ){
+      new_st[pos] = GetData()[i]; // copy it & increment pos   @CAO prob in GCC
+      ++pos;
+    }
+  }
+  (*this) = new_st;  // assign the new_st to this
+}
+
+void cString::RemovePos(int pos){
+  int i;
+  int new_size = GetSize() - 1;
+  cString new_st(new_size);      // allocate new string
+  int newpos = 0;
+  for( i=0; i<GetSize(); ++i ){  // count new size
+    if( i != pos ){
+      new_st[newpos++] = GetData()[i]; // copy it & increment pos
+    }
+  }
+  (*this) = new_st;  // assign the new_st to this
+}
+
+
+
+// -- Internal Methods --
+
+cString & cString::AppendStr(const int in_size, const char * in)
+{
+  assert (in_size == 0 || in != NULL); // NULL input string
+
+  // Allocate a new string
+  cStringData * new_value = new cStringData(GetSize()+in_size);
+  assert (new_value != NULL);       // Memory Allocation Error: Out of Memory
+  for(int i=0; i<GetSize(); ++i ) { // Copy self up to pos
+    (*new_value)[i] = this->operator[](i);
+  }
+  for(int i=0; i<in_size; ++i ) {   // Copy in
+    assert(in[i] != '\0');          // Input String Contains '\\0' or too Short
+    (*new_value)[i+GetSize()] = in[i];
+  }
+  TakeValue(new_value);             // Reassing data to new data
+  return(*this);
+}
+
+
+cString & cString::InsertStr(const int in_size, const char * in,
+			     int pos, int excise )
+{
+  // Inserts 'in' (of length 'in_size') at postition 'pos'
+  // Also excises 'excise' characters from 'pos'
+  // If 'in_size'==0 then 'in' can == NULL and only excise happens
+
+  // Validate inputs:
+  assert (in_size >= 0);               // Negative input size
+  assert (pos >= 0);                   // Negative position
+  assert (pos <= GetSize());           // Position past end of string
+  assert (excise >= 0);                // Negative excise
+  assert (excise <= GetSize()-pos);    // Excise number too large
+  assert (excise > 0 || in_size > 0);  // Make sure a change is made!
+  assert (in_size == 0 || in != NULL); // NULL input string
+
+  // Allocate a new string
+  const int new_size = GetSize() + in_size - excise;
+  cStringData * new_value = new cStringData(new_size);
+  assert (new_value != NULL);  // Memory Allocation Error: Out of Memory
+
+  for(int i = 0; i < pos; ++i ){             // Copy self up to pos
+    (*new_value)[i] = this->operator[](i);
+  }
+  for(int i = 0; i < in_size; ++i ){         // Copy in
+    assert( in[i] != '\0');  // Input String Contains '\\0' or too Short
+    (*new_value)[i+pos] = in[i];
+  }
+  for(int i=pos+excise; i<GetSize(); ++i ){  // Copy rest of self
+    (*new_value)[i+in_size-excise] = this->operator[](i);
+  }
+
+  TakeValue(new_value);                      // Reassing data to new data
+  return(*this);
+}
+
+
+int cString::FindStr(const char * in, const int in_size, int pos) const
+{
+  assert (pos>=0);         // Negative position
+  assert (pos<=GetSize()); // Position past end of string
+
+  while (pos < GetSize()) {
+    if( GetSize()-pos < in_size ) return -1; // Too near this string's end.
+    if( (*this)[pos] == in[0] ){
+      // see if we have found the string...
+      int i;
+      for( i = 1; i < in_size; i++ ){
+	assert (pos+i < GetSize()); // Reached end of (*this) in Find
+	assert (in[i] != '\0');     // Reached end of 'in' in Find
+	if( (*this)[pos + i] != in[i] ) break; // Match failure!
+      }
+      // If we have made it fully through the loop, we have found a match!
+      if( i == in_size ) return pos;
+    }
+    pos++;
+  }
+  return -1;
+}
+
+
+
+// {{{ ** External cString Functions **
+
+istream & operator >> (istream & in, cString & string)
+{
+  char buf[cString::MAX_LENGTH];
+  in>>buf;
+  string=buf;
+  return in;
+}
+
+ostream & operator << (ostream & out, const cString & string)
+{
+  out << string.GetData();
+  return out;
+}
+
Index: avida/current/source/tools/string.hh
diff -u /dev/null avida/current/source/tools/string.hh:1.18
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/string.hh	Tue Nov 25 09:38:00 2003
@@ -0,0 +1,616 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef STRING_HH
+#define STRING_HH
+
+#include <stdlib.h>
+#include <iostream>
+#include <string.h>
+#include <assert.h>
+
+#define MAX_STRING_LENGTH 4096
+#define CONTINUE_LINE_CHAR '\\'
+
+/**
+ * A multipurpose string class with many convenient methods of
+ * manipulating and comparing strings.
+ **/
+
+class cString {
+protected:
+  void CopyOnWrite(){
+    if( value->IsShared() ){  // if it is shared
+      value->RemoveRef();     // remove our reference count
+      value = new cStringData(*value);  // make own copy of value
+    }
+  }
+
+  // -- Contained Classes --
+private:
+  // Declarations (only needed)
+  class cStringData;
+
+  // {{{ -- cCharProxy -- To detect rvalue vs lvalue ---------------------
+
+  class cCharProxy{
+  private:
+    cString & string;
+    unsigned short index;
+
+  public:
+    cCharProxy( cString & _string, unsigned short _index) :
+     string(_string), index(_index) {;}
+
+    inline cCharProxy & operator= (char c);     // lvalue
+    inline cCharProxy & operator+= (char c);    // lvalue
+    inline cCharProxy & operator-= (char c);    // lvalue
+    inline cCharProxy & operator++ ();          // lvalue (prefix)
+    inline char         operator++ (int dummy); // lvalue (postfix)
+    inline cCharProxy & operator-- ();          // lvalue (prefix)
+    inline char         operator-- (int dummy); // lvalue (postfix)
+    inline operator char () const ;             // rvalue
+  };
+
+  //friend cCharProxy;  // Telling rvalue vs lvalue ....
+  // porting to gcc 3.1 -- k
+  friend class cCharProxy;  // Telling rvalue vs lvalue ....
+
+  // }}}  End cCharProxy
+  // {{{ -- cStringData -- Holds the actual data and is reference count --
+  class cStringData{
+    // NOTE: Terminating NULL is always there (you can't assign!!)
+
+  private:
+    unsigned short refs;   // Number of references
+    unsigned short size;   // size of data (NOT INCLUDING TRAILING NULL)
+    char * data;
+
+  public:
+    explicit cStringData(unsigned short in_size);
+    cStringData(unsigned short in_size, const char * in);
+    cStringData(const cStringData & in);
+
+    ~cStringData(){
+      assert(refs == 0);  // Deleting cStringData with References!!
+      delete [] data; }
+
+
+    cStringData & operator= (const cStringData & in) {
+      delete [] data;
+      size = in.GetSize();
+      data = new char [size+1];
+      assert(data != NULL);   // Memory Allocation Error: Out of Memory
+      for( unsigned short i=0; i<size; ++i )  data[i]=in[i];
+      data[size] = '\0';
+      return (*this);
+    }
+
+
+    unsigned short GetSize() const { return size; }
+
+    const char * GetData() const { return data; }
+
+    char operator[] (int index) const {
+      assert(index >= 0);    // Lower Bounds Error
+      assert(index <= size); // Upper Bounds Error
+      return data[index];
+    }
+
+    char & operator[](int index) {
+      assert(index >= 0);     // Lower Bounds Error
+      assert(index <= size);  // Upper Bounds Error
+      assert(index != size);  // Cannot Change Terminating NULL
+      return data[index];
+    }
+
+
+    bool IsShared() { return( refs > 1 ); }
+
+    unsigned short RemoveRef() {
+      assert( refs > 0 );  // Reference count corrupted
+      return(--refs);
+    }
+
+    cStringData * NewRef() { ++refs; return this; }
+
+  };
+  // }}} End cStringData
+
+  // -- Constants --
+public:
+  static const int MAX_LENGTH;
+
+
+
+  //  -- INTERFACE -----------------------------------------------------------
+public:
+
+  // -- Constructors --
+  cString(const char * in = "") : value(new cStringData(strlen(in), in)) {
+    assert( in != NULL );     // NULL input string
+    assert( value != NULL );  // Memory Allocation Error: Out of Memory
+  }
+  explicit cString(const int size) : value(new cStringData(size)) {
+    assert( value!=NULL );    // Memory Allocation Error: Out of Memory
+  }
+  cString(const cString & in) : value(in.value->NewRef()) {;}
+
+
+  // -- Destructor --
+  virtual ~cString() { if( value->RemoveRef() == 0 )  delete value; }
+
+
+  // Cast to const char *
+  operator const char * () const { return value->GetData(); }
+  const char * operator() () const { return value->GetData(); } // Depricated
+  const char * GetData() const { return value->GetData(); } // Depricated
+
+
+  // Assignment Operators
+  cString & operator= (const cString & in){
+    ChangeValue(in.value);
+    return *this; }
+  cString & operator= (const char * in){
+    assert( in != NULL ); // NULL input string
+    if( value->RemoveRef() == 0 ) delete value;
+    value = new cStringData(strlen(in),in);
+    assert(value != NULL);  // Memory Allocation Error: Out of Memory
+    return *this;
+  }
+  
+  
+  /**
+   * Get the size of the string (not including the terminating '\0').
+   **/
+  int GetSize() const { return value->GetSize(); }
+
+
+  // Comparisons
+  int Compare(const char * in) const;  // strcmp like function
+  bool operator== (const char * in)    const { return (Compare(in)==0); }
+  bool operator== (const cString & in) const;  // A bit optimized
+  bool operator!= (const char * in)    const { return !(*this==in); }
+  bool operator<  (const char * in)    const { return (Compare(in)<0); }
+  bool operator>  (const char * in)    const { return (Compare(in)>0); }
+  bool operator<= (const char * in)    const { return (Compare(in)<=0); }
+  bool operator>= (const char * in)    const { return (Compare(in)>=0); }
+
+  // Concatenation
+  cString & operator+= (const char in)  { return AppendStr(1,&in); }
+  cString & operator+= (const char * in){ return AppendStr(strlen(in),in); }
+  cString & operator+= (const cString & in){return AppendStr(in.GetSize(),in);}
+  cString operator+ (const char in_char){ return (cString(*this) += in_char); }
+  cString operator+ (const char * in)   { return (cString(*this) += in); }
+  cString operator+ (const cString & in){ return (cString(*this) += in); }
+
+
+  // Additional modifiers
+  cString & Set(const char * fmt, ...);
+
+  cString & Insert(const char in, int pos=0, int excise=0){
+    return InsertStr(1, &in, pos, excise); }
+  cString & Insert(const char * in, int pos=0, int excise=0){
+    return InsertStr(strlen(in), in, pos, excise); }
+  cString & Insert(const cString & in, int pos=0, int excise=0){
+    return InsertStr(in.GetSize(), in, pos, excise); }
+
+
+  // Removes 'size' characters from 'pos' (default size = to end of string)
+  cString & Clip(int pos, int size = -1 /*end of string*/ ){
+    if( size < 0 ) size = GetSize()-pos;
+    return InsertStr(0, NULL, pos, size); }
+  cString & ClipFront(int size){  // Clip off first 'clip_size' chars
+    return InsertStr(0, NULL, 0, size); }
+  cString & ClipEnd(int size){    // Clip off last 'clip_size' chars
+    return InsertStr(0, NULL, GetSize()-size, size); }
+  
+  /**
+   * Find and replace a substring in the string with a different substring.
+   * If the substring is not found, the string object is not changed.
+   *
+   * @return The position at which the substring was found, or -1 if it wasn't found.
+   * @param old_string The substring that is going to be replaced.
+   * @param new_string The replacement.
+   * @param pos The position at which the search should start.
+   **/
+  int Replace(const cString & old_st, const cString & new_st, int pos=0);
+
+  cString Pop(const char delim);  // Remove and return up to delim char
+  
+  /**
+   * Remove the first word.
+   *
+   * @return The removed word.
+   **/
+  cString PopWord();
+  
+  /**
+   * Remove the first line.
+   *
+   * @return The removed line.
+   **/
+  cString PopLine(){ return Pop('\n'); } 
+  
+  /**
+   * Remove begining whitespace.
+   *
+   * @return The number of characters removed.
+   **/
+  int LeftJustify(); 
+  
+  /**
+   * Remove ending whitespace.
+   *
+   * @return The number of characters removed.
+   **/
+  int RightJustify(); 
+  
+  /**
+   * Reverse the order of the characters in the string.
+   **/
+  void Reverse(); 
+  
+  /**
+   * Convert the string to lowercase.
+   **/
+  cString & ToLower(); 
+  
+  /** 
+   * Convert the string to uppercase.
+   **/
+  cString & ToUpper();
+  
+  /**
+   * Replace all blocks of whitespace with a single space (' ').
+   *
+   * @see cString::IsWhitespace()
+   **/
+  void CompressWhitespace();  
+  
+  /**
+   * Get rid of all(!) whitespace. 
+   *
+   * @see cString::IsWhitespace()
+   **/
+  void RemoveWhitespace(); 
+
+  /**
+   * Get rid of all occurances of a specific character.
+   *
+   * @see cString::RemoveWhitespace()
+   **/
+  void RemoveChar(char out_char); 
+  
+  /**
+   * Get rid of one character at a specific location
+   **/
+  void RemovePos(int pos);
+
+  // Individal Char Access
+  inline char operator[] (int index) const {
+    return (char)((*value)[index]);
+    // Below should work, but fails in HP CC -- TCC
+    //    return const_cast(const cStringData&, *value)[index];
+  }
+  cCharProxy operator[] (int index) { return cCharProxy(*this,index); }
+
+
+  /**
+   * Convert string to int.
+   *
+   * @return The integer value corresponding to the string.
+   **/
+  int AsInt() const { return atoi(*this); }
+  
+  /**
+   * Convert string to double.
+   *
+   * @return The double value corresponding to the string.
+   **/
+  double AsDouble() const { return atof(*this); }
+
+  // Accessors & Information
+  /**
+   * Tests whether the string is empty.
+   **/
+  bool IsEmpty() const { return GetSize()==0; } // Can just call GetSize
+    
+  /**
+   * Test if the continuation character is at the end of the line
+   * if it is strip off the charecter and return true else return 
+   * false
+   **/
+  bool IsContinueLine();
+
+  /**
+   * Counts whitespace, beginning at the given position.
+   *
+   * @param start The index at which counting should begin.
+   **/
+  int CountWhitespace(int start=0) const; 
+  
+  /**
+   * Counts non-whitespace, beginning at the given position.
+   *
+   * @param start The index at which counting should begin.
+   **/
+  int CountWordsize(int start=0) const;
+    
+  /**
+   * Counts until the first occurrence of '\n', beginning at the 
+   * given position.
+   *
+   * @param start The index at which counting should begin.
+   **/
+  int CountLinesize(int start=0) const; 
+  
+  /**
+   * Counts the number of lines in a string.
+   **/
+  int CountNumLines() const;           
+  
+  /**
+   * Counts the number of separate words in a string.
+   **/
+  int CountNumWords() const;         
+    
+  /**
+   * Get a specific word from a string.
+   *
+   * @param word_id The number of the word, counted from the beginning of 
+   * the string, starting with 0.
+   **/
+  cString GetWord(int word_id=0) const;
+    
+  /**
+   * Get the next word after the specified position. Any leading whitespace 
+   * is removed.
+   *
+   * @param start The position at which the function should start 
+   * searching for a word.
+   **/
+  cString GetWordAt(int start=0) const; 
+
+  /**
+   * Test if a character is whitespace. Currently, as whitespace count
+   * ' ', '\r', '\t', '\n'.
+   *
+   * @param pos The position of the character to test.
+   **/
+  bool IsWhitespace(int pos) const {
+    return ( (*this)[pos] == ' '  || (*this)[pos] == '\t' ||
+	     (*this)[pos] == '\r' || (*this)[pos] == '\n' );
+  }
+  
+  /**
+   * Test if a character is a capital letter.
+   *
+   * @param pos The position of the character to test.
+   **/
+  bool IsUpperLetter(int pos) const {
+    return ((*this)[pos] >= 'A' && (*this)[pos] <= 'Z');
+  }
+  
+  /**
+   * Test if a character is not a capital letter.
+   *
+   * @param pos The position of the character to test.
+   **/
+  bool IsLowerLetter(int pos) const {
+    return ((*this)[pos] >= 'a' && (*this)[pos] <= 'z');
+  }
+  
+  /**
+   * Test if a character is a letter.
+   *
+   * @param pos The position of the character to test.
+   **/
+  bool IsLetter(int pos) const {
+    return IsUpperLetter(pos) || IsLowerLetter(pos);
+  }
+  
+  /**
+   * Test if a character is a number (this includes expressions
+   * such as -3.4e5).
+   *
+   * @param pos The position of the character to test.
+   **/
+  bool IsNumber(int pos) const {
+    return ( ( (*this)[pos] >= '0' && (*this)[pos] <= '9' ) ||
+	     (*this)[pos] == '-' || (*this)[pos] == '+' ||
+	     (*this)[pos] == '.' || (*this)[pos] == 'e' ||
+	     (*this)[pos] == 'E' );
+  }
+  
+  /**
+   * Test if a character is a numeral (0, 1, ..., 9).
+   *
+   * @param pos The position of the character to test.
+   **/
+  bool IsNumeric(int pos) const {
+    return ((*this)[pos] >= '0' && (*this)[pos] <= '9');
+  }
+  
+  /**
+   * Test if a character is either a numeral or a letter.
+   *
+   * @param pos The position of the character to test.
+   **/
+  bool IsAlphaNumeric(int pos) const {
+    return IsLetter(pos) || IsNumber(pos);
+  }
+  
+  /**
+   * Test whether the complete string consits only of whitespace.
+   **/
+  bool IsWhitespace() const;
+  
+  /**
+   * Test whether the complete string consits only of uppercase letters.
+   **/
+  bool IsUpperLetter() const;
+  
+  /**
+   * Test whether the complete string consits only of lowercase letters.
+   **/
+  bool IsLowerLetter() const;
+  
+  /**
+   * Test whether the complete string consits only of letters.
+   **/
+  bool IsLetter() const;
+  
+  /**
+   * Test whether the complete string can be seen as a number.
+   **/
+  bool IsNumber() const;
+  
+  /**
+   * Test whether the complete string consits only of numerals.
+   **/
+  bool IsNumeric() const;
+  
+  /**
+   * Test whether the complete string consits only of letters or numerals.
+   **/
+  bool IsAlphaNumeric() const;
+  
+  /**
+   * Search for a single character.
+   *
+   * @return The first occurence after pos, or -1 if not found
+   **/
+  int Find(char in_char, int pos=0) const;
+  
+  /**
+   * Search for a substring.
+   *
+   * @return The first occurence after pos, or -1 if not found
+   **/
+  int Find(const char * in, int pos=0) const{
+    return FindStr(in, strlen(in), pos); }
+  
+  /**
+   * Search for a substring.
+   *
+   * @return The first occurence after pos, or -1 if not found
+   **/
+  int Find(const cString & in, int pos=0) const{
+    return FindStr(in, in.GetSize(), pos); }
+  
+  /**
+   * Search for a word.
+   *
+   * @return The first occurence after pos, or -1 if not found
+   **/
+  int FindWord(const cString & in, int pos=0) const;
+  
+  
+  /**
+   * Cut out a substring.
+   *
+   * @return The substring.
+   * @param start The beginning of the substring in the string.
+   * @param size The number of characters in the substring.
+   **/
+  cString Substring(int start, int size) const ;
+  
+  bool IsSubstring(const cString & in_string, int start) const;
+  
+  
+  // {{{ -- INTERNALS -------------------------------------------------------
+protected:
+  // -- Internal Functions --
+  void ChangeValue(cStringData * new_ref){   // If you didn't make new_value
+    if( value->RemoveRef() == 0 ) delete value;
+    value = new_ref->NewRef();
+  }
+
+  void TakeValue(cStringData * new_ref){     // If you made new_value!
+    if( value->RemoveRef() == 0 ) delete value;
+    value = new_ref;
+  }
+
+  // Methods that take input string size (unsafe to call from outside)
+  cString & AppendStr(const int in_size, const char * in);  // Optimized
+  cString & InsertStr(const int in_size, const char * in,
+		      int pos, int excise=0);
+  int FindStr(const char * in_string, const int in_size, int pos) const;
+
+  // -- Internal Data --
+protected:
+  cStringData * value;
+
+// }}} End Internals
+
+};
+
+
+// {{{ ** External cString Functions **
+
+// iostream input
+std::istream & operator >> (std::istream & in, cString & string);
+std::ostream & operator << (std::ostream & out, const cString & string);
+
+// }}}
+
+// -- INLINE INCLUDES --
+
+cString::cCharProxy & cString::cCharProxy::operator= (char c){  // lvalue
+  string.CopyOnWrite();
+  (*(string.value))[index] = c;
+  return *this;
+}
+
+cString::cCharProxy & cString::cCharProxy::operator+= (char c){  // lvalue
+  string.CopyOnWrite();
+  (*(string.value))[index] += c;
+  return *this;
+}
+
+cString::cCharProxy & cString::cCharProxy::operator-= (char c){  // lvalue
+  string.CopyOnWrite();
+  (*(string.value))[index] -= c;
+  return *this;
+}
+
+cString::cCharProxy & cString::cCharProxy::operator++ (){  // lvalue (prefix)
+  string.CopyOnWrite();
+  ++(*(string.value))[index];
+  return *this;
+}
+
+char cString::cCharProxy::operator++ (int dummy){  // lvalue (postfix)
+  (void)dummy;
+  char rv = (*(string.value))[index];
+  string.CopyOnWrite();
+  ++(*(string.value))[index];
+  return rv;
+}
+
+cString::cCharProxy & cString::cCharProxy::operator-- (){  // lvalue (prefix)
+  string.CopyOnWrite();
+  --(*(string.value))[index];
+  return *this;
+}
+
+char cString::cCharProxy::operator-- (int dummy){  // lvalue (postfix)
+  (void)dummy;
+  char rv = (*(string.value))[index];
+  string.CopyOnWrite();
+  --(*(string.value))[index];
+  return rv;
+}
+
+cString::cCharProxy::operator char () const {  // rvalue
+  return (char)((*(string.value))[index]);
+  // Below should work, but fails in HP CC -- TCC
+  //   return const_cast(const cStringData&, *(string.value))[index];
+}
+
+#endif
Index: avida/current/source/tools/string_list.cc
diff -u /dev/null avida/current/source/tools/string_list.cc:1.8
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/string_list.cc	Tue Nov 25 09:38:00 2003
@@ -0,0 +1,71 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#include "functions.hh"
+#ifndef STRING_ITERATOR_HH
+#include "string_iterator.hh"
+#endif
+#ifndef STRING_LIST_HH
+#include "string_list.hh"
+#endif
+
+
+using namespace std;
+
+
+
+cStringList::cStringList(const cString & _list, char seperator)
+{
+  Load(_list, seperator);
+}
+
+cStringList::cStringList(const cStringList & _list)
+{
+  tConstListIterator<cString> list_it(_list.string_list);
+  while (list_it.Next() != NULL) {
+    string_list.PushRear(new cString( *(list_it.Get()) ));
+  }
+}
+
+cStringList::~cStringList()
+{
+  while (string_list.GetSize() > 0) delete string_list.Pop();
+}
+
+
+cStringList & cStringList::operator=(const cStringList & _list)
+{
+  tConstListIterator<cString> list_it(_list.string_list);
+  while (list_it.Next() != NULL) {
+    string_list.PushRear(new cString( *(list_it.Get()) ));
+  }
+  return *this;
+}
+
+bool cStringList::HasString(const cString & test_string) const
+{
+  tConstListIterator<cString> string_it(string_list);
+  const cString * cur_string = NULL;
+  while ((cur_string = string_it.Next()) != NULL) {
+    if (test_string == *cur_string) {
+      return true;
+    }
+  }
+  return false;
+}
+
+cString cStringList::PopString(const cString & test_string)
+{
+  tListIterator<cString> string_it(string_list);
+  const cString * cur_string = NULL;
+  while ((cur_string = string_it.Next()) != NULL) {
+    if (test_string == *cur_string) {
+      return ReturnString(string_list.Remove(string_it));
+    }
+  }
+  return "";
+}
Index: avida/current/source/tools/string_list.hh
diff -u /dev/null avida/current/source/tools/string_list.hh:1.6
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/string_list.hh	Tue Nov 25 09:38:00 2003
@@ -0,0 +1,58 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef STRING_LIST_HH
+#define STRING_LIST_HH
+
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+#ifndef TLIST_HH
+#include "tList.hh"
+#endif
+
+class cString; // aggregate
+template <class T> class tList; // aggregate
+
+class cStringList {
+private:
+  tList<cString> string_list;
+
+  inline cString ReturnString(cString * out_string) {
+    cString tmp_string(*out_string);
+    delete out_string;
+    return tmp_string;
+  }
+public:
+  cStringList() { ; }
+  cStringList(const cString & _list, char seperator=' ');
+  cStringList(const cStringList & _list);
+  ~cStringList();
+
+  cStringList & operator=(const cStringList & _list);
+
+  int GetSize() const { return string_list.GetSize(); }
+  cString GetLine(int line_num) const { return *(string_list.GetPos(line_num)); }
+  const tList<cString> & GetList() const { return string_list; }
+
+  bool HasString(const cString & test_string) const;
+  cString PopString(const cString & test_string);
+
+  void Push(const cString & _in) { string_list.Push(new cString(_in));}
+  void PushRear(const cString & _in) { string_list.PushRear(new cString(_in));}
+  cString Pop() { return ReturnString(string_list.Pop()); }
+  cString PopRear() { return ReturnString(string_list.PopRear()); }
+
+  void Load(cString _list, char seperator=' ') {
+    while (_list.GetSize() > 0) PushRear(_list.Pop(seperator));
+  }
+  void Clear() {
+    while (string_list.GetSize() > 0) delete string_list.Pop(); 
+  }
+};
+
+#endif
Index: avida/current/source/tools/string_util.cc
diff -u /dev/null avida/current/source/tools/string_util.cc:1.7
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/string_util.cc	Tue Nov 25 09:38:00 2003
@@ -0,0 +1,290 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef STRING_UTIL_HH
+#include "string_util.hh"
+#endif
+
+
+#include "functions.hh"
+#include "tMatrix.hh"
+
+extern "C"{
+#include <stdio.h>
+#include <stdarg.h>
+}
+
+
+using namespace std;
+
+
+cString cStringUtil::Stringf(const char * fmt, ...) {
+  va_list argp;
+  char buf[MAX_STRING_LENGTH];
+
+  va_start(argp, fmt);
+  vsprintf(buf, fmt, argp);
+  va_end(argp);
+
+  return cString(buf);
+}
+
+
+cString cStringUtil::ToRomanNumeral(const int in_value) {
+  cString ret_string;
+  if (in_value < 0) {
+    ret_string = "-";
+    ret_string += ToRomanNumeral(-in_value);
+  } else if (in_value > 3999) {
+    // Out of bounds; return a blank;
+  } else if (in_value >= 1000) {
+    ret_string = "M";
+    ret_string += ToRomanNumeral(in_value - 1000);
+  } else if (in_value >= 900) {
+    ret_string = "CM";
+    ret_string += ToRomanNumeral(in_value - 900);
+  } else if (in_value >= 500) {
+    ret_string = "D";
+    ret_string += ToRomanNumeral(in_value - 500);
+  } else if (in_value >= 400) {
+    ret_string = "CD";
+    ret_string += ToRomanNumeral(in_value - 400);
+  } else if (in_value >= 100) {
+    ret_string = "C";
+    ret_string += ToRomanNumeral(in_value - 100);
+  } else if (in_value >= 90) {
+    ret_string = "XC";
+    ret_string += ToRomanNumeral(in_value - 90);
+  } else if (in_value >= 50) {
+    ret_string = "L";
+    ret_string += ToRomanNumeral(in_value - 50);
+  } else if (in_value >= 40) {
+    ret_string = "XL";
+    ret_string += ToRomanNumeral(in_value - 40);
+  } else if (in_value >= 10) {
+    ret_string = "X";
+    ret_string += ToRomanNumeral(in_value - 10);
+  } else if (in_value == 9) {
+    ret_string = "IX";
+  } else if (in_value >= 5) {
+    ret_string = "V";
+    ret_string += ToRomanNumeral(in_value - 5);
+  } else if (in_value == 4) {
+    ret_string = "IV";
+  } else if (in_value > 0) {
+    ret_string = "I";
+    ret_string += ToRomanNumeral(in_value - 1);
+  }
+  // else we already have it exactly and don't need to return anything.
+  return ret_string;
+}
+
+
+int cStringUtil::StrLength(const char * in){
+  // if 'in'==NULL return 0;
+  int size = 0;
+  if( in != NULL ){
+    while( in[size]!='\0' )  ++size; // Count chars in _in
+  }
+  return size;
+}
+
+
+int cStringUtil::Distance(const cString & string1, const cString & string2,
+			  int offset) 
+{
+  if (offset < 0) return cStringUtil::Distance(string2, string1, -offset);
+
+  const int size1 = string1.GetSize();
+  const int size2 = string2.GetSize();
+
+  // Calculate by how much the strings overlap.
+  int overlap = Min( size1 - offset,  size2 );
+
+  // Initialize the distance to that part of the strings which do not
+  // overlap.
+  int num_diffs = size1 + size2 - 2 * overlap;
+
+  // Step through the overlapped section and add on any additional differences.
+  for (int i = 0; i < overlap; i++) {
+    if (string1[i + offset] != string2[i]) num_diffs++;
+  }
+
+  return num_diffs;
+}
+
+
+int cStringUtil::EditDistance(const cString & string1, const cString & string2)
+{
+  const int size1 = string1.GetSize();
+  const int size2 = string2.GetSize();
+
+  if (size1 == 0) return size2;
+  if (size2 == 0) return size1;
+
+  int * cur_row  = new int[size1];  // The row we are calculating
+  int * prev_row = new int[size1];  // The last row we calculated
+
+  // Initialize the previous row to record the differece from nothing.
+  for (int i = 0; i < size1; i++) prev_row[i] = i + 1;
+
+  // Loop through all of the other rows
+  for (int i = 0; i < size2; i++) {
+    // Initialize the first entry in the current row.
+    if (string1[0] == string2[i]) cur_row[0] = i;
+    else cur_row[0] = (i < prev_row[0]) ? (i+1) : (prev_row[0] + 1);
+
+    // Move down the cur_row and fill it in.
+    for (int j = 1; j < size1; j++) {
+      // If the values are equal, keep the value in the upper left.
+      if (string1[j] == string2[i]) {
+	cur_row[j] = prev_row[j-1];
+      }
+
+      // Otherwise, set the current position the the minimal of the three
+      // numbers to the upper right in the chart plus one.
+      else {
+	cur_row[j] =
+	  (prev_row[j] < prev_row[j-1]) ? prev_row[j] : prev_row[j-1];
+	if (cur_row[j-1] < cur_row[j]) cur_row[j] = cur_row[j-1];
+	cur_row[j]++;
+      }
+    }
+
+    // Swap cur_row and prev_row. (we only really need to move the cur row
+    // over to prev, but this saves us from having to keep re-allocating
+    // new rows.  We recycle!
+    int * temp_row = cur_row;
+    cur_row = prev_row;
+    prev_row = temp_row;
+  }
+
+  // Now that we are done, return the bottom-right corner of the chart.
+
+  const int value = prev_row[size1 - 1];
+
+  delete [] cur_row;
+  delete [] prev_row;
+
+  return value;
+}
+
+
+int cStringUtil::EditDistance(const cString & string1, const cString & string2,
+			      cString & info, const char gap)
+{
+  const int size1 = string1.GetSize();
+  const int size2 = string2.GetSize();
+ 
+  if (!size1) return size2;
+  if (!size2) return size1;
+
+  tMatrix<double> dist_matrix(size2+1, size1+1);
+
+  // Keep track of changes in a mut_matrix.
+  //  N=None, M=Mutations, I=Insertion, D=Deletion
+  tMatrix<char> mut_matrix(size2+1, size1+1);
+
+  // Initialize the first row and col to record the differece from nothing.
+  for (int i = 0; i < size1+1; i++) {
+    dist_matrix(0,i) = (double) i;
+    mut_matrix(0,i) = 'I';
+  }
+  for (int i = 0; i < size2+1; i++) {
+    dist_matrix(i,0) = (double) i;
+    mut_matrix(i,0) = 'D';
+  }
+  mut_matrix(0,0) = 'N';
+
+  for (int i = 0; i < size2; i++) {
+    // Move down the cur_row and fill it out.
+    for (int j = 0; j < size1; j++) {
+      // If the values are equal, keep the value in the upper left.
+      if (string1[j] == string2[i]) {
+	dist_matrix(i+1,j+1) = dist_matrix(i,j);
+	mut_matrix(i+1,j+1) = 'N';
+	continue; // Move on to next entry...
+      }
+
+      // Otherwise, set the current position the the minimal of the three
+      // numbers above (insertion), to the left (deletion), or upper left
+      // (mutation) in the chart, plus one.
+      double mut_dist = dist_matrix(i,j) + 1;
+      if ((string1[j] == gap) || (string2[i] == gap)) mut_dist -= 0.0001;
+      const double ins_dist = dist_matrix(i+1,j) + (string1[j] != gap);
+      const double del_dist = dist_matrix(i,j+1) + (string2[i] != gap);
+
+      if (mut_dist < ins_dist && mut_dist < del_dist) {  // Mutation!
+	dist_matrix(i+1,j+1) = mut_dist;
+	mut_matrix(i+1,j+1) = 'M';
+      } else if (ins_dist < del_dist) {                  // Insertion!
+	dist_matrix(i+1,j+1) = ins_dist;
+	mut_matrix(i+1,j+1) = 'I';
+      } else {                                           // Deletion!
+	dist_matrix(i+1,j+1) = del_dist;
+	mut_matrix(i+1,j+1) = 'D';
+      }
+    }
+  }
+
+  // Construct the list of changes
+  int pos1 = size1;
+  int pos2 = size2;
+  info = "";
+
+  cString mut_string;
+  while (pos1 > 0 || pos2 > 0) {
+    if (mut_matrix(pos2, pos1) == 'N') {     
+      pos1--; pos2--;
+      continue;
+    }
+
+    // There is a mutation here; determine the type...
+    const char old_char = (pos2 > 0) ? string2[pos2-1] : '\0';
+    const char new_char = (pos1 > 0) ? string1[pos1-1] : '\0';
+
+    if (mut_matrix(pos2, pos1) == 'M') {
+      mut_string.Set("M%d%c%c", pos2-1, old_char, new_char);
+      pos1--; pos2--;
+    }
+    else if (mut_matrix(pos2, pos1) == 'D') {
+      mut_string.Set("D%d%c", pos2-1, old_char);
+      pos2--;
+    }
+    else { // if (mut_matrix(pos2, pos1) == 'I') {
+      mut_string.Set("I%d%c", pos1-1, new_char);
+      pos1--;
+    }
+
+    if (info.GetSize() > 0) mut_string += ",";
+    info.Insert(mut_string);
+  } 
+
+  // Now that we are done, return the bottom-right corner of the chart.
+  return (int) dist_matrix(size2, size1);
+}
+
+const cString & cStringUtil::Convert(const cString & in_string,
+				     const cString & out_string)
+{
+  return in_string;
+}
+
+bool cStringUtil::Convert(const cString & in_string, bool type_bool)
+{
+  return (in_string.AsInt() != 0);
+}
+
+int cStringUtil::Convert(const cString & in_string, int type_int)
+{
+  return in_string.AsInt();
+}
+
+double cStringUtil::Convert(const cString & in_string, double type_double)
+{
+  return in_string.AsDouble();
+}
Index: avida/current/source/tools/string_util.hh
diff -u /dev/null avida/current/source/tools/string_util.hh:1.4
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/string_util.hh	Tue Nov 25 09:38:00 2003
@@ -0,0 +1,57 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef STRING_UTIL_HH
+#define STRING_UTIL_HH
+
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+
+class cString; // aggregate
+
+struct cStringUtil {
+  static cString Stringf(const char * fmt, ...);
+  static cString ToRomanNumeral(const int in_value);
+  static int StrLength(const char * _in);
+
+  /**
+   * Calculate the Hamming distance between two strings.
+   *
+   * @return The Hamming distance.
+   * @param string1 the first string to compare.
+   * @param string2 the second string to compare.
+   * @param offset This parameter determines how many characters the second
+   * string should be shifted wrt. the first before the comparison.
+   **/
+  static int Distance(const cString & string1, const cString & string2,
+	       int offset=0);
+  
+  /**
+   * Calculate the edit distance between two strings.
+   *
+   * @return The Edit (Levenstein) distance.
+   * @param string1 the first string to compare.
+   * @param string2 the second string to compare.
+   * @param description The string to write out the differences
+   **/
+  static int EditDistance(const cString & string1, const cString & string2);
+  static int EditDistance(const cString & string1, const cString & string2,
+			  cString & info, const char gap=' '); 
+
+  /**
+   * Various, overloaded conversion functions for use in templates.  Note
+   * that in all cases, the second argument is simply to set the return type.
+   **/
+  static const cString & Convert(const cString & in_string,
+				 const cString & out_string);
+  static bool   Convert(const cString & in_string, bool   type_bool);
+  static int    Convert(const cString & in_string, int    type_int);
+  static double Convert(const cString & in_string, double type_double);
+};
+
+#endif
Index: avida/current/source/tools/tArray.hh
diff -u /dev/null avida/current/source/tools/tArray.hh:1.15
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/tArray.hh	Tue Nov 25 09:38:00 2003
@@ -0,0 +1,162 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+/*
+   tArray.hh
+   Array Templates
+
+   Constructor:
+     tArray( int size )
+     tArray( const tArray & rhs )
+
+   Interface:
+     tArray & operator= ( const tArray & rhs )
+
+     bool Good () const
+       array is defined and ready to take data
+
+     unsigned int GetSize () const
+       returns the size of the array
+
+     const T& ElementAt ( const int index ) const
+           T& ElementAt ( const int index )
+     const T& operator[] ( const int index ) const
+           T& operator[] ( const int index )
+       return the element at index in the array
+*/
+
+#ifndef TARRAY_HH
+#define TARRAY_HH
+
+#include <assert.h>
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/**
+ * This class provides an array template.
+ **/ 
+
+template <class T> class tArray {
+
+protected:
+  // Internal Variables
+  T * data;  // Data Elements
+  int size;  // Number of Elements
+
+public:
+  void ResizeClear(const int in_size){
+    size = in_size;
+    assert(size >= 0);  // Invalid size specified for array intialization
+    if (data != NULL) delete [] data;  // remove old data if exists
+    if (size > 0) {
+      data = new T[size];   // Allocate block for data
+      assert(data != NULL); // Memory allocation error: Out of Memory?
+    }
+    else data = NULL;
+  }
+
+public:
+  // Constructor
+  explicit tArray(const int _size=0) : data(NULL) {
+    ResizeClear(_size);
+  }
+
+  // Assingment Operator
+  tArray & operator= (const tArray & rhs) {
+    if (size != rhs.GetSize())  ResizeClear(rhs.GetSize());
+    for(int i = 0; i < size; i++) data[i] = rhs[i];
+    return *this;
+  }
+
+  // Copy constructor
+  explicit tArray(const tArray & rhs) : data(NULL), size(0) {
+    this->operator=(rhs);
+  }
+
+  // Destructor
+  virtual ~tArray() {
+    if (data != NULL) delete [] data;
+  }
+
+  // Interface Methods ///////////////////////////////////////////////////////
+
+  bool Good() const { return (data != NULL); }
+
+//    bool OK() const {
+//      assert(size >= 0);
+//      return true;
+//    }
+
+  int GetSize() const { return size; }
+
+  void Resize(int new_size) {
+    // If we're already at the size we want, don't bother doing anything.
+    if (size == new_size) return;
+
+    // If new size is 0, clean up and go!
+    if (new_size == 0) {
+      delete [] data;
+      data = NULL;
+      size = 0;
+      return;
+    }
+
+    // If new size > 0
+    T * new_data = new T[new_size];
+    assert(new_data != NULL); // Memory Allocation Error: Out of Memory?
+
+    // Copy over old data...
+    for (int i = 0; i < size && i < new_size; i++) {
+      new_data[i] = data[i];
+    }
+    if (data != NULL) delete [] data;  // remove old data if exists
+    data = new_data;
+
+    size = new_size;
+  }
+
+
+  void Resize(int new_size, const T & empty_value) {
+    int old_size = size;
+    Resize(new_size);
+    if( new_size > old_size ){
+      for (int i = old_size; i < new_size; i++) {
+	data[i] = empty_value;
+      }
+    }
+  }
+
+
+  T & ElementAt(const int index){
+    // check range
+    assert(index >= 0);    // Lower Bounds Error
+    assert(index < size);  // Upper Bounds Error
+    return data[index];    // in range, so return element
+  }
+
+  const T & ElementAt(const int index) const {
+    // check range
+    assert(index >= 0);    // Lower Bounds Error
+    assert(index < size);  // Upper Bounds Error
+    return data[index];    // in range, so return element
+  }
+
+        T & operator[](const int index)       { return ElementAt(index); }
+  const T & operator[](const int index) const { return ElementAt(index); }
+
+
+  void SetAll(const T & value){
+    for( int i=0; i < size; ++i ){
+      data[i] = value;
+    }
+  }
+
+};
+
+#endif // TARRAY_HH
Index: avida/current/source/tools/tBuffer.hh
diff -u /dev/null avida/current/source/tools/tBuffer.hh:1.7
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/tBuffer.hh	Tue Nov 25 09:38:00 2003
@@ -0,0 +1,89 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef TBUFFER_HH
+#define TBUFFER_HH
+
+#include <assert.h>
+#include <iostream>
+
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+#ifndef TARRAY_HH
+#include "tArray.hh"
+#endif
+
+template <class T> class tArray; // aggregate
+class cString; // aggregate
+
+template <class T> class tBuffer {
+private:
+  tArray<T> data;      // Contents of buffer...
+  int offset;          // Position in buffer to next write.
+  int total;           // Total inputs ever...
+  int last_total;      // Total inputs at time of last ZeroNumAdds.
+public:
+  tBuffer(const int size) : data(size), offset(0), total(0),
+			    last_total(0) { ; }
+  tBuffer(const tBuffer<T> & in) : data(in.data), offset(in.offset),
+			   total(in.total), last_total(in.last_total) { ; }
+
+  tBuffer & operator= (const tBuffer<T> & in) {
+    data = in.data;
+    offset = in.offset;
+    total = in.total;
+    last_total = in.last_total;
+    return *this;
+  }
+
+  ~tBuffer() { ; }
+
+  void Clear() { offset = 0; total = 0; last_total = 0; }
+
+  void Add(T in){
+    data[offset] = in;
+    total++;
+    offset++;
+    while (offset >= data.GetSize()) offset -= data.GetSize();
+  }
+
+  void ZeroNumAdds() { total = 0; }
+
+  T operator[] (int i) const {
+    int index = offset - i - 1;
+    while (index < 0)  index += data.GetSize();
+    return data[index];
+  }
+
+  int GetCapacity() const { return data.GetSize(); }
+  int GetTotal() const { return total; }
+  int GetNumStored() const
+    { return (total <= data.GetSize()) ? total : data.GetSize(); }
+  int GetNum() const { return total - last_total; }
+
+  void SaveState(std::ostream & fp) {
+    assert(fp.good());
+    fp << "tBuffer" << " ";
+    fp << data.GetSize() << " ";
+    for (int i = 0; i < data.GetSize(); i++)  fp << data[i] << " ";
+    fp << offset << " "  << total << " "  << last_total << " "  << std::endl;
+  }
+  
+  void LoadState(std::istream & fp) {
+    assert(fp.good());
+    cString foo;  fp >> foo;  assert(foo == "tBuffer");
+    int capacity;  fp >> capacity;
+    data.Resize(capacity);
+    for (int i = 0; i < capacity; i++) {
+      fp >> data[i];
+    }
+    fp  >>  offset  >>  total  >>  last_total;
+  }
+};
+
+#endif
Index: avida/current/source/tools/tDictionary.hh
diff -u /dev/null avida/current/source/tools/tDictionary.hh:1.6
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/tDictionary.hh	Tue Nov 25 09:38:01 2003
@@ -0,0 +1,144 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef TDICTIONARY_HH
+#define TDICTIONARY_HH
+
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+#ifndef STRING_UTIL_HH
+#include "string_util.hh"
+#endif
+#ifndef TLIST_HH
+#include "tList.hh"
+#endif
+
+#define DICTIONARY_HASH_DEFAULT 23
+#define DICTIONARY_HASH_MEDIUM  331
+#define DICTIONARY_HASH_LARGE   2311
+
+class cString; // aggregate
+class cStringUtil; // access
+template <class T> class tList; // access
+template <class T> class tListIterator; // aggregate
+
+template <class T> class tDictionary {
+
+  template <class U> struct tDictEntry {
+    cString name;
+    U data;
+  };
+
+private:
+  int size;
+  int hash_size;
+  tList< tDictEntry<T> > * hash_table;
+  
+  int HashString(const cString & key) const {
+    unsigned int out_hash = 0;
+    for (int i = 0; i < key.GetSize(); i++)
+      out_hash += (unsigned int) key[i];
+    return out_hash % hash_size;
+  }
+  tDictEntry<T> * FindEntry(const cString & name) {
+    const int bin = HashString(name);
+    tListIterator< tDictEntry<T> > list_it(hash_table[bin]);
+    while (list_it.Next() != NULL) {
+      if (list_it.Get()->name == name) return list_it.Get();
+    }
+    return NULL;
+  }
+public:
+  tDictionary() : size(0), hash_size(DICTIONARY_HASH_DEFAULT) {
+    hash_table = new tList< tDictEntry<T> >[hash_size];
+  }
+  ~tDictionary() {
+    for (int i = 0; i < hash_size; i++)
+      while (hash_table[i].GetSize()) delete hash_table[i].Pop();
+    delete [] hash_table;
+  }
+
+  int GetSize() { return size; }
+  
+  void Add(const cString & name, T data) {
+    tDictEntry<T> * new_entry = new tDictEntry<T>;
+    new_entry->name = name;
+    new_entry->data = data;
+    const int bin = HashString(name);
+    hash_table[bin].Push(new_entry);
+    size++;
+  }
+  
+  bool HasEntry(const cString & name) {
+    return FindEntry(name) != NULL;
+  }
+
+  bool Find(const cString & name, T & out_data) {
+    tDictEntry<T> * found_entry = FindEntry(name);
+    if (found_entry != NULL) {
+      out_data = found_entry->data;
+      return true;
+    }
+    return false;
+  }
+
+  T Remove(const cString & name) {
+    const int bin = HashString(name);
+    T out_data = NULL;
+    tListIterator< tDictEntry<T> > list_it(hash_table[bin]);
+    while (list_it.Next() != NULL) {
+      if (list_it.Get()->name == name) {
+	out_data = list_it.Get()->data;
+	list_it.Remove();
+	size--;
+	break;
+      }
+    }
+    return out_data;
+  }
+
+  cString NearMatch(const cString name) {
+    cString best_match("");
+    int best_dist = name.GetSize();
+    for (int i = 0; i < hash_size; i++) {
+      tListIterator< tDictEntry<T> > list_it(hash_table[i]);
+      while (list_it.Next() != NULL) {
+	int dist = cStringUtil::EditDistance(name, list_it.Get()->name);
+	if (dist < best_dist) {
+	  best_dist = dist;
+	  best_match = list_it.Get()->name;
+	}
+      }
+    }
+    return best_match;
+  }
+
+  void SetHash(int _hash) {
+    const int old_hash_size = hash_size;
+
+    // Create the new table...
+    hash_size = _hash;
+    tList< tDictEntry<T> > * new_hash_table =
+      new tList< tDictEntry<T> >[hash_size];
+
+    // Move everything over...
+    for (int i = 0; i < old_hash_size; i++) {
+      while (hash_table[i].GetSize() > 0) {
+	tDictEntry<T> * cur_entry = hash_table[i].Pop();
+	const int bin = HashString(cur_entry->name);
+	new_hash_table[bin].Push(cur_entry);
+      }
+    }
+
+    // Cleanup...
+    delete [] hash_table;
+    hash_table = new_hash_table;
+  }
+};
+
+#endif
Index: avida/current/source/tools/tList.hh
diff -u /dev/null avida/current/source/tools/tList.hh:1.11
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/tList.hh	Tue Nov 25 09:38:01 2003
@@ -0,0 +1,414 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef TLIST_HH
+#define TLIST_HH
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+template <class T> class tListNode {
+public:
+  T * data;
+  tListNode<T> * next;
+  tListNode<T> * prev;
+
+  tListNode() : data(NULL), next(this), prev(this) { ; }
+};
+
+template <class T> class tList;
+
+template <class T> class tBaseIterator {
+  friend class tList<T>;
+protected:
+  virtual const tList<T> & GetConstList() = 0;
+  virtual const tListNode<T> * GetConstNode() = 0;
+public:
+  tBaseIterator() { ; }
+  virtual ~tBaseIterator() { ; }
+
+  virtual const T * GetConst() = 0;
+  virtual const T * NextConst() = 0;
+  virtual const T * PrevConst() = 0;
+
+  virtual bool AtRoot() const = 0;
+  virtual bool AtEnd() const = 0;
+};
+
+template <class T> class tListIterator : public tBaseIterator<T> {
+  friend class tList<T>;
+private:
+  tList<T> & list;
+  tListNode<T> * node;
+
+  const tList<T> & GetConstList() { return list; }
+  const tListNode<T> * GetConstNode() { return node; }
+public:
+  explicit tListIterator(tList<T> & _list);
+  ~tListIterator();
+
+  void Reset();
+
+  T * Get();
+  T * Next();
+  T * Prev();
+  const T * GetConst() { return Get(); }
+  const T * NextConst() { return Next(); }
+  const T * PrevConst() { return Prev(); }
+
+  bool Find(T * test_data);
+
+  bool AtRoot() const;
+  bool AtEnd() const;
+
+  // Unique methods...
+  T * Remove();
+};
+
+template <class T> class tConstListIterator : public tBaseIterator<T> {
+  friend class tList<T>;
+private:
+  const tList<T> & list;
+  const tListNode<T> * node;
+
+  const tList<T> & GetConstList() { return list; }
+  const tListNode<T> * GetConstNode() { return node; }
+public:
+  explicit tConstListIterator(const tList<T> & _list);
+  ~tConstListIterator();
+
+  void Reset();
+
+  const T * Get();
+  const T * Next();
+  const T * Prev();
+  const T * GetConst() { return Get(); }
+  const T * NextConst() { return Next(); }
+  const T * PrevConst() { return Prev(); }
+  bool Find(const T * test_data);
+
+  bool AtRoot() const;
+  bool AtEnd() const;
+};
+
+template <class T> class tList {
+  friend class tBaseIterator<T>;
+  friend class tListIterator<T>;
+  friend class tConstListIterator<T>;
+protected:
+  tListNode<T> root;                     // Data root
+  int size;
+  mutable tListNode< tBaseIterator<T> > it_root; // Iterator root
+  mutable int it_count;
+
+  T * RemoveNode(tListNode<T> * out_node) {
+    // Make sure we're not trying to delete the root node!
+    if (out_node == &root) return NULL;
+
+    // Adjust any iterators on the deleted node.
+    tListNode< tBaseIterator<T> > * test_it = it_root.next;
+    while (test_it != &it_root) {
+      // If this iterator is on this node, move it back one.
+      if (test_it->data->GetConstNode() == out_node) {
+	test_it->data->PrevConst();
+      }
+      test_it = test_it->next;
+    }
+
+    // Save the data and patch up the linked list.
+    T * out_data = out_node->data;
+    out_node->prev->next = out_node->next;
+    out_node->next->prev = out_node->prev;
+
+    // Cleanup and return
+    size--;
+    delete out_node;
+    return out_data;
+  }
+
+  // To be called from iterator constructor only!
+  void AddIterator(tBaseIterator<T> * new_it) const {
+    tListNode< tBaseIterator<T> > * new_node =
+      new tListNode< tBaseIterator<T> >;
+    new_node->data = new_it;
+    new_node->next = it_root.next;
+    new_node->prev = &it_root;
+    it_root.next->prev = new_node;
+    it_root.next = new_node;
+    it_count++;
+  }
+
+  // To be called from iterator destructor only!
+  void RemoveIterator(tBaseIterator<T> * old_it) const {
+    tListNode< tBaseIterator<T> > * test_it = it_root.next;
+    while (test_it->data != old_it) test_it = test_it->next;
+    test_it->prev->next = test_it->next;
+    test_it->next->prev = test_it->prev;
+    delete test_it;
+    it_count--;
+  }
+
+public:
+  T * Pop() { return RemoveNode(root.next); }
+  T * PopRear() { return RemoveNode(root.prev); }
+
+  void Push(T * _in) {
+    tListNode<T> * new_node = new tListNode<T>;
+    new_node->data = _in;
+    new_node->next = root.next;
+    new_node->prev = &root;
+    root.next->prev = new_node;
+    root.next = new_node;
+    size++;
+  }
+
+  void PushRear(T * _in) {
+    tListNode<T> * new_node = new tListNode<T>;
+    new_node->data = _in;
+    new_node->next = &root;
+    new_node->prev = root.prev;
+    root.prev->next = new_node;
+    root.prev = new_node;
+    size++;
+  }
+
+  void Clear() { while (size > 0) Pop(); }
+
+  const T * GetFirst() const { return root.next->data; }
+  const T * GetLast()  const { return root.prev->data; }
+  T * GetFirst()             { return root.next->data; }
+  T * GetLast()              { return root.prev->data; }
+
+  T * GetPos(int pos) {
+    if (pos >= GetSize()) return NULL;
+    tListNode<T> * test_node = root.next;
+    for (int i = 0; i < pos; i++) test_node = test_node->next;
+    return test_node->data;
+  }
+
+  const T * GetPos(int pos) const {
+    if (pos >= GetSize()) return NULL;
+    tListNode<T> * test_node = root.next;
+    for (int i = 0; i < pos; i++) test_node = test_node->next;
+    return test_node->data;
+  }
+
+  void CircNext() { if (size > 0) PushRear(Pop()); }
+  void CircPrev() { if (size > 0) Push(PopRear()); }
+
+  T * Remove(tListIterator<T> & other) {
+    if (&(other.list) != this) return NULL;
+    return RemoveNode(other.node);
+  }
+
+  T * Insert(tBaseIterator<T> & list_it, T * in_data) {
+    tListNode<T> * new_node = new tListNode<T>;
+    new_node->data = in_data;
+    new_node->next = list_it.node->next;
+    new_node->prev = list_it.node;
+
+    list_it.node->next->prev = new_node;
+    list_it.node->next = new_node;
+    size++;
+    return in_data;
+  }
+
+
+  bool Remove(T * other) {
+    tListNode<T> * test = root.next;
+    while (test != &root) {
+      if (test->data == other) {
+	RemoveNode(test);
+	return true;
+      }
+      test = test->next;
+    }
+    return false;
+  }
+
+  int GetSize() const { return size; }
+
+  void Append(tList<T> & other_list) {
+    tListIterator<T> other_it(other_list);
+    while (other_it.Next() != NULL) PushRear(other_it.Get());
+  }
+
+  T * Find(T * _in) const {
+    tListNode<T> * test = root.next;
+    while (test != &root) {
+      if ( *(test->data) == *(_in) ) return test->data;
+      test = test->next;
+    }
+    return NULL;
+  }
+
+  T * PopIntValue(int (T::*fun)() const, int value) {
+    tListNode<T> * test = root.next;
+    while (test != &root) {
+      if ( (test->data->*fun)() == value) return RemoveNode(test);
+      test = test->next;
+    }
+    return NULL;
+  }
+
+  T * PopIntMax(int (T::*fun)() const) { 
+    if (size == 0) return NULL;
+    tListNode<T> * test = root.next;
+    tListNode<T> * best = test;
+    int max_val = (test->data->*fun)();
+    while (test != &root) {
+      const int cur_val = (test->data->*fun)();
+      if ( cur_val > max_val ) {
+	max_val = cur_val;
+	best = test;
+      }
+      test = test->next;
+    }
+    return RemoveNode(best);
+  }
+
+  T * PopDoubleMax(double (T::*fun)() const) {
+    if (size == 0) return NULL;
+    tListNode<T> * test = root.next;
+    tListNode<T> * best = test;
+    double max_val = (test->data->*fun)();
+    while (test != &root) {
+      const double cur_val = (test->data->*fun)();
+      if ( cur_val > max_val ) {
+	max_val = cur_val;
+	best = test;
+      }
+      test = test->next;
+    }
+    return RemoveNode(best);
+  }
+public:
+  tList() : size(0), it_count(0) { }
+  ~tList() { Clear(); }
+private:
+  tList(tList & _list) { ; }  // Never should be used...
+};
+
+////////////////////
+//  tListIterator
+
+template <class T> tListIterator<T>::tListIterator(tList<T> & _list)
+  : list(_list), node(&(_list.root))
+{
+  list.AddIterator(this);
+}
+
+template <class T> tListIterator<T>::~tListIterator()
+{
+  list.RemoveIterator(this);
+}
+
+template <class T> void tListIterator<T>::Reset()
+{
+  node = &(list.root);
+}
+
+template <class T> T * tListIterator<T>::Get()
+{
+  return node->data;
+}
+
+template <class T> T * tListIterator<T>::Next()
+{
+  node = node->next;
+  return node->data;
+}
+
+template <class T> T * tListIterator<T>::Prev()
+{
+  node = node->prev;
+  return node->data;
+}
+
+template <class T> bool tListIterator<T>::Find(T * test_data)
+{
+  for (node = list.root.next;
+       node != &(list.root);
+       node = node->next) {
+    if (node->data == test_data) return true;
+  }
+  return false;
+}
+
+template <class T> bool tListIterator<T>::AtRoot() const
+{
+  return (node == &(list.root));
+}
+
+template <class T> bool tListIterator<T>::AtEnd() const
+{
+  return (node->next == &(list.root));
+}
+
+template <class T> T* tListIterator<T>::Remove()
+{
+  return list.RemoveNode(node);
+}
+
+/////////////////////////
+//  tConstListIterator
+
+template <class T> tConstListIterator<T>::tConstListIterator(const tList<T> & _list)
+  : list(_list), node(&(_list.root))
+{
+  list.AddIterator(this);
+}
+
+template <class T> tConstListIterator<T>::~tConstListIterator()
+{
+  list.RemoveIterator(this);
+}
+
+template <class T> void tConstListIterator<T>::Reset()
+{
+  node = &(list.root);
+}
+
+template <class T> const T * tConstListIterator<T>::Get()
+{
+  return node->data;
+}
+
+template <class T> const T * tConstListIterator<T>::Next()
+{
+  node = node->next;
+  return node->data;
+}
+
+template <class T> const T * tConstListIterator<T>::Prev()
+{
+  node = node->prev;
+  return node->data;
+}
+
+template <class T> bool tConstListIterator<T>::Find(const T * test_data)
+{
+  for (node = list.root.next;
+       node != &(list.root);
+       node = node->next) {
+    if (node->data == test_data) return true;
+  }
+  return false;
+}
+
+template <class T> bool tConstListIterator<T>::AtRoot() const
+{
+  return (node == &(list.root));
+}
+
+template <class T> bool tConstListIterator<T>::AtEnd() const
+{
+  return (node->next == &(list.root));
+}
+
+#endif
Index: avida/current/source/tools/tMatrix.hh
diff -u /dev/null avida/current/source/tools/tMatrix.hh:1.8
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/tMatrix.hh	Tue Nov 25 09:38:01 2003
@@ -0,0 +1,139 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+/*
+   tMatrix.hh
+   Matrix Templates
+
+   Constructor:
+     tMatrix( int rows, int cols )
+     tMatrix( const tMatrix & rhs )
+
+   Interface:
+     tMatrix & operator= ( const tMatrix & rhs )
+
+     unsigned int GetNumRows () const
+     unsigned int GetNumCols () const
+       returns the size of the array
+
+     const T& ElementAt ( const int row, col ) const
+           T& ElementAt ( const int row, col )
+     const T& operator() ( const int row, col ) const
+           T& operator() ( const int row, col )
+       return the element at position in the matrix
+
+     const tArray<T>& operator[] ( const int row ) const
+           tArray<T>& operator[] ( const int row )
+       return the array at the row in the matrix.
+
+
+*/
+
+#ifndef TMATRIX_HH
+#define TMATRIX_HH
+
+#include <assert.h>
+
+#ifndef TARRAY_HH
+#include "tArray.hh"
+#endif
+
+/**
+ * This class provides a matrix template.
+ **/ 
+
+template <class T> class tArray; // access
+
+template <class T> class tMatrix {
+protected:
+  // Internal Variables
+  tArray<T> * data;  // Data Elements
+  int num_rows;
+public:
+  int GetNumRows() const { return num_rows; }
+  int GetNumCols() const { return data[0].GetSize(); }
+
+  void ResizeClear(const int _rows, const int _cols){
+    if (_rows != GetNumRows()) {
+      num_rows = _rows;
+      assert(_rows > 0); // Invalid size specified for matrix resize
+      if( data != NULL )  delete [] data;  // remove old data if exists
+      data = new tArray<T>[_rows];  // Allocate block for data
+      assert(data != NULL); // Memory Allocation Error: Out of Memory?
+    }
+    for (int i = 0; i < GetNumRows(); i++) data[i].ResizeClear(_cols);
+  }
+
+  void Resize(int _rows, int _cols) {
+    // Rows and cols must be > 0
+    assert(_rows > 0 && _cols > 0); // Invalid size specified for matrix resize
+
+    if( data != NULL )  {
+      tArray<T> * new_data = new tArray<T>[_rows];
+      for (int i = 0; i < GetNumRows() && i < _rows; i++) {
+	new_data[i] = data[i];
+      }
+      delete [] data;  // remove old data if exists
+      data = new_data;
+    } else {
+      data = new tArray<T>[_rows];  // Allocate block for data
+    }
+    assert(data != NULL); // Memory Allocation Error: Out of Memory?
+    num_rows = _rows;
+
+    for (int i = 0; i < _rows; i++) data[i].Resize(_cols);
+  }
+
+  T & ElementAt(int _row, int _col) { return data[_row][_col]; }
+  const T & ElementAt(int _row, int _col) const { return data[_row][_col]; }
+
+        T & operator()(int _r, int _c)       { return ElementAt(_r, _c); }
+  const T & operator()(int _r, int _c) const { return ElementAt(_r, _c); }
+
+        tArray<T> & operator[](int row)       { return data[row]; }
+  const tArray<T> & operator[](int row) const { return data[row]; }
+
+  void SetAll(const T & value) {
+    for (int i = 0; i < num_rows; i++) {
+      data[i].SetAll(value);
+    }
+  }
+
+
+public:
+  // Default Constructor
+  explicit tMatrix() : data(NULL), num_rows(0) { ResizeClear(1,1); }
+
+  // Constructor
+  explicit tMatrix(const int _rows, const int _cols) :
+    data(NULL), num_rows(0) {
+      ResizeClear(_rows, _cols);
+  }
+
+  // Assingment Operator
+  tMatrix & operator= (const tMatrix & rhs){
+    if( GetNumRows() != rhs.GetNumRows() || GetNumCols() != rhs.GetNumCols()) {
+      ResizeClear(rhs.GetNumRows(), rhs.GetNumCols());
+    }
+    for (int row = 0; row < GetNumRows(); row++) {
+      for (int col = 0; col < GetNumCols(); col++) {
+	data[row][col] = rhs.data[row][col];
+      }
+    }
+    return *this;
+  }
+
+  // Copy constructor
+  explicit tMatrix(const tMatrix & rhs) : data(NULL), num_rows(0) {
+    this->operator=(rhs);
+  }
+
+  // Destructor
+  virtual ~tMatrix(){ if(data!=NULL) delete [] data; }
+};
+
+#endif // TARRAY_HH
Index: avida/current/source/tools/tMemTrack.hh
diff -u /dev/null avida/current/source/tools/tMemTrack.hh:1.3
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/tMemTrack.hh	Tue Nov 25 09:38:01 2003
@@ -0,0 +1,43 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef TMEM_TRACK_HH
+#define TMEM_TRACK_HH
+
+template <class T> class tMemTrack {
+private:
+  static int obj_count;
+public:
+  // These "New" commands can only be used with no arguments.
+  static T * New() {
+    obj_count++;
+    return new T;
+  }
+  static T * New(int count) {
+    obj_count += count;
+    return new T[count];
+  }
+
+  static void Free(T * ptr) {
+    obj_count--;
+    free ptr;
+  }
+  static void Free(T * ptr, int count) {
+    obj_count -= count;
+    free [] ptr;
+  }
+
+  // This New and Free just help keep track of things handled elsewhere...
+  static void MarkNew() { obj_count++; }
+  static void MarkFree() { obj_count--; }
+
+ 
+  // And some methods to keep track of what's going on...
+  static int GetCount() { return obj_count; }
+};
+
+#endif
Index: avida/current/source/tools/tVector.hh
diff -u /dev/null avida/current/source/tools/tVector.hh:1.7
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/tVector.hh	Tue Nov 25 09:38:01 2003
@@ -0,0 +1,165 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef TVECTOR_HH
+#define TVECTOR_HH
+
+/**
+ * This class provides a vector template.
+ **/ 
+
+template <class T> class tVector {
+private:
+  T *		_data;
+  int		_size;
+  int		_capacity;
+  int		_capIncrement;
+
+public:
+  tVector(void): _size(0), _capacity(1), _capIncrement(-1) {
+    _data = new T[_capacity];
+    #ifdef EXCEPTION_HANDLING
+    if(_data == NULL) throw InsufficientMemory();
+    #endif
+  }
+
+  tVector(int cap, int incr = -1): _size(0), _capacity(cap),
+				  _capIncrement(incr){
+    _data = new T[_capacity];
+    #ifdef EXCEPTION_HANDLING
+    if(_data == NULL) throw InsufficientMemory();
+    #endif
+  }
+
+
+  tVector(const tVector &v): _size(v._size), _capacity(v._capacity),
+			   _capIncrement(v._capIncrement)
+  {
+    _data = new T[_capacity];
+    #ifdef EXCEPTION_HANDLING
+    if(_data == NULL) throw InsufficientMemory();
+    #endif
+    for(int i = 0; i < _size; i++) {
+      _data[i] = v._data[i];
+    }
+  }
+
+  ~tVector() {
+    if(_data) delete [] _data;
+  }
+
+public:
+  int Size(void) const {
+    return _size;
+  }
+
+  int Capacity(void) const {
+    return _capacity;
+  }
+
+  void Add(T data) {
+    if(Size() + 1 > Capacity()) { // if we have to allocate new space, do so
+      T* newdata;
+      if(_capIncrement == -1) {
+	newdata = new T[Capacity() * 2];
+	#ifdef EXCEPTION_HANDLING
+	if(newdata == NULL) throw InsufficientMemory();
+	#endif
+	_capacity = Capacity() * 2;
+      }
+      else {
+	newdata = new T[Capacity() + _capIncrement];
+	#ifdef EXCEPTION_HANDLING
+	if(newdata == NULL) throw InsufficientMemory();
+	#endif
+	_capacity = Capacity() + _capIncrement;
+      }
+
+      for(int i = 0; i < Size(); i++) {
+	newdata[i] = _data[i];
+      }
+      newdata[_size++] = data;
+      delete [] _data;
+      _data = newdata;
+      return;
+    }
+    else { // no need to allocate new data
+      _data[_size++] = data;
+      return;
+    }
+  }
+
+  void Remove(T data) {
+    int i, j;
+    for(i = 0; _data[i] != data && i < Size(); i++);
+    if(i < Size()) {
+      T *newdata = new T[Capacity()];
+      for(j = 0; j < i; j++) {
+	newdata[j] = _data[j];
+      }
+      for(; j < Size() - 1; j++) {
+	newdata[j] = _data[j + 1];
+      }
+      delete [] _data;
+      _data = newdata;
+      --_size;
+      return;
+    }
+    return;
+  }
+
+  void RemoveAt(int idx) {
+    int i, j;
+    if(idx >= 0 && idx < Size()) {
+      T *newdata = new T[Capacity()];
+      for(i = 0; i < idx; i++) {
+	newdata[i] = _data[i];
+      }
+      for(; i < Size() - 1; i++) {
+	newdata[i] = _data[i + 1];
+      }
+      delete [] _data;
+      _data = newdata;
+      --_size;
+      return;
+    }
+    return;
+  }
+
+  void Clear(void) {
+    delete [] _data;
+    _data = new T[Capacity()];
+    _size = 0;
+  }
+
+public:
+  T& operator[](int idx) {
+    assert_error( idx >= 0, "Lower Bounds Error" );
+    assert_error( idx < Size(), "Upper Bounds Error" );
+    if(idx >= 0 && idx < Size()) { // it is in range
+      return _data[idx];
+    }
+    #ifdef EXCEPTION_HANDLING
+    throw IndexOutofRangeError(idx);
+    #endif
+    return _data[0];
+  }
+
+  T operator[](int idx) const {
+    assert_error( idx >= 0, "Lower Bounds Error" );
+    assert_error( idx < Size(), "Upper Bounds Error" );
+    if(idx >= 0 && idx < Size()) {
+      return _data[idx];
+    }
+    #ifdef EXCEPTION_HANDLING
+    throw IndexOutofRangeError(idx);
+    #endif
+    return _data[0];
+  }
+};
+
+#endif
Index: avida/current/source/tools/tools.cc
diff -u /dev/null avida/current/source/tools/tools.cc:1.11
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/tools.cc	Tue Nov 25 09:38:01 2003
@@ -0,0 +1,55 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef TOOLS_HH
+#include "tools.hh"
+#endif
+
+#include <iostream>
+#include <errno.h>
+#include <sys/stat.h>
+#include <stdio.h>
+
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+
+#ifdef WIN32
+# ifndef WIN32_MKDIR_HACK_HH
+#  include "win32_mkdir_hack.hh"
+# endif
+#endif
+
+cRandom g_random;
+
+using namespace std;
+
+bool cTools::MkDir(const cString & dirname, bool verbose)
+{
+  if (verbose) cout << "Checking for directory '" << dirname << "'..." << endl;
+
+  FILE * fp = fopen ( dirname(), "r" );
+  if (fp == 0) {
+    if (errno == ENOENT) {
+      if (verbose) cout << "  ...not found.  Has to be created..." << endl;
+      if (mkdir( dirname(), (S_IRWXU|S_IRWXG|S_IRWXO) )) {
+	if (verbose) cerr << "  ...ERROR!  Failed to create directory '"
+			  << dirname << "'.  This may cause problems..."
+			  << endl;
+	return false;
+      }
+
+      if (verbose) cout << "  ...done!" << endl;
+      return true;
+    }
+
+    if (verbose) cout << "  ...ERROR! -- Failed to open directory!  This may cause problems." << endl;
+    return false;
+  }
+
+  return true;
+}
Index: avida/current/source/tools/tools.hh
diff -u /dev/null avida/current/source/tools/tools.hh:1.10
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/tools.hh	Tue Nov 25 09:38:01 2003
@@ -0,0 +1,30 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+// This file is for misc. objects which are of general use...
+
+#ifndef TOOLS_HH
+#define TOOLS_HH
+
+#ifndef RANDOM_HH
+#include "random.hh"
+#endif
+
+extern cRandom g_random;
+
+/*
+ *   Filesystem tools...
+ */
+
+class cString;
+
+class cTools {
+public:
+  static bool MkDir(const cString & dirname, bool verbose=false);
+};
+
+#endif
Index: avida/current/source/tools/weighted_index.cc
diff -u /dev/null avida/current/source/tools/weighted_index.cc:1.6
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/weighted_index.cc	Tue Nov 25 09:38:01 2003
@@ -0,0 +1,98 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2002 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef WEIGHTED_INDEX_HH
+#include "weighted_index.hh"
+#endif
+#include <iostream>
+
+
+using namespace std;
+
+
+cWeightedIndex::cWeightedIndex(int in_size)
+  : size(in_size)
+  , item_weight(size)
+  , subtree_weight(size)
+{
+  item_weight.SetAll(0);
+  subtree_weight.SetAll(0);
+}
+
+cWeightedIndex::~cWeightedIndex()
+{
+}
+
+void cWeightedIndex::AdjustSubtree(int id, double weight_change)
+{
+  subtree_weight[id] += weight_change;
+  if (id != 0) {
+    AdjustSubtree(GetParent(id), weight_change);
+  }
+}
+
+void cWeightedIndex::SetWeight(int id, double in_weight)
+{
+  const double weight_change = in_weight - item_weight[id];
+  item_weight[id] = in_weight;
+  AdjustSubtree(id, weight_change);
+}
+
+// This order of testing is about 10% faster than the one used below.
+// Alas, it scans the array out of bounds...  For a real test we need to
+// look at timings in optimized mode.
+// int cWeightedIndex::FindPosition(double position, int root_id)
+// {
+//   // Check left...
+//   const int left_id = GetLeftChild(root_id);
+//   if (position < subtree_weight[left_id]) {
+//     return FindPosition(position, left_id);
+//   }
+
+//   // Then right...
+//   position -= subtree_weight[left_id];
+//   const int right_id = GetRightChild(root_id);
+//   if (position < subtree_weight[right_id]) {
+//     return FindPosition(position, right_id);
+//   }
+  
+//   // Then just return this!
+//   return root_id;
+// }
+
+int cWeightedIndex::FindPosition(double position, int root_id)
+{
+//   cout << "Seeking " << position
+//        << " at root " << root_id 
+//        << " subtree size = " << subtree_weight[root_id]
+//        << " (left=" << subtree_weight[GetLeftChild(root_id)]
+//        << " , right=" << subtree_weight[GetRightChild(root_id)]
+//        << " , this=" << item_weight[root_id] << ")"
+//        << endl;
+  assert(position < subtree_weight[root_id]);
+
+  // First, see if we should just return this node.
+  if (position < item_weight[root_id]) {
+    return root_id;
+  }
+
+  // If not, then see if we should search in the left subtree...
+  position -= item_weight[root_id];
+  const int left_id = GetLeftChild(root_id);
+  assert (left_id < size);
+  if (position < subtree_weight[left_id]) {
+    return FindPosition(position, left_id);
+  }
+
+  // Otherwise we must look in the right subtree...
+  position -= subtree_weight[left_id];
+  const int right_id = GetRightChild(root_id);
+  assert (right_id < size);
+  assert (position < subtree_weight[right_id]);
+  return FindPosition(position, right_id);
+}
+
Index: avida/current/source/tools/weighted_index.hh
diff -u /dev/null avida/current/source/tools/weighted_index.hh:1.3
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/weighted_index.hh	Tue Nov 25 09:38:01 2003
@@ -0,0 +1,48 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef WEIGHTED_INDEX_HH
+#define WEIGHTED_INDEX_HH
+
+#ifndef TARRAY_HH
+#include "tArray.hh"
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/**
+ * This class allows indecies to be assigned a "weight" and then indexed by
+ * that weight.
+ **/
+
+template <class T> class tArray; // aggregate
+
+class cWeightedIndex {
+protected:
+  int size;
+  tArray<double> item_weight;
+  tArray<double> subtree_weight;
+
+  void AdjustSubtree(int id, double weight_change);
+public:
+  cWeightedIndex(int in_size);
+  ~cWeightedIndex();
+
+  void SetWeight(int id, double weight);
+  double GetWeight(int id) { return item_weight[id]; }
+
+  double GetTotalWeight() { return subtree_weight[0]; }
+  int FindPosition(double position, int root_id=0);
+
+  int GetParent(int id)     { return (id-1) / 2; }
+  int GetLeftChild(int id)  { return 2*id + 1; }
+  int GetRightChild(int id) { return 2*id + 2; }
+};
+
+#endif
Index: avida/current/source/tools/win32_mkdir_hack.hh
diff -u /dev/null avida/current/source/tools/win32_mkdir_hack.hh:1.4
--- /dev/null	Tue Nov 25 09:38:03 2003
+++ avida/current/source/tools/win32_mkdir_hack.hh	Tue Nov 25 09:38:01 2003
@@ -0,0 +1,23 @@
+#ifndef WIN32_MKDIR_HACK_HH
+#define WIN32_MKDIR_HACK_HH
+
+/*
+FIXME:  mkdir undefined in win32, need a cleaner workaround.
+any prefers where to put this?
+-- kgn
+*/
+#ifdef WIN32
+# include <direct.h>
+# ifndef ACCESSPERMS
+#  define ACCESSPERMS 0
+# endif
+# ifndef mkdir
+#  define mkdir(path, ignored_mode) _mkdir(path)
+# endif
+# ifndef mode_t
+#  define mode_t UINT
+# endif
+#endif
+
+
+#endif
Index: avida/current/source/tools/Makefile.am
diff -u avida/current/source/tools/Makefile.am:1.19 avida/current/source/tools/Makefile.am:1.20
--- avida/current/source/tools/Makefile.am:1.19	Thu Jul 17 10:49:44 2003
+++ avida/current/source/tools/Makefile.am	Tue Nov 25 09:38:00 2003
@@ -1,32 +1,66 @@
 
 
-libtools_a_SOURCES = block_struct.cc	block_struct.hh \
-		b_struct2.cc	b_struct2.hh    \
-		data_entry.cc	data_entry.hh	\
-		data_manager.cc	data_manager.hh \
-		datafile.cc	datafile.hh	\
-		file.cc		file.hh         \
-		help.cc		help.hh         \
-		message_display.cc	message_display.hh	\
-    message_display_hdrs.hh \
-		merit.cc	merit.hh	\
-		random.cc	random.hh	\
-		slice.cc	slice.hh	\
-		stat.cc		stat.hh         \
-		string.cc	string.hh	\
-		string_list.cc	string_list.hh	\
-		string_util.cc	string_util.hh	\
-		tools.cc	tools.hh	\
-		weighted_index.cc	weighted_index.hh	\
-				functions.hh	\
-				int.hh		\
-				tArray.hh	\
-				tBuffer.hh	\
-				tDictionary.hh	\
-				tList.hh	\
-				tMatrix.hh	\
-				tVector.hh \
-				win32_mkdir_hack.hh
+SOURCE_DIR = $(srcdir)/..
+SOURCE_INC = -I$(SOURCE_DIR)
+EVENT_DIR = $(SOURCE_DIR)/event
+EVENT_INC = -I$(EVENT_DIR)
+# CPU_DIR = $(SOURCE_DIR)/cpu
+# CPU_INC = -I$(CPU_DIR)
+TOOLS_DIR = $(SOURCE_DIR)/tools
+TOOLS_INC = -I$(TOOLS_DIR)
+# MAIN_DIR = $(SOURCE_DIR)/main
+# MAIN_INC = -I$(MAIN_DIR)
+
+INCLUDES = $(EVENT_INC) $(SOURCE_INC) 
+
+libtools_a_SOURCES = \
+  block_struct.cc block_struct.hh \
+  const_schedule.cc const_schedule.hh \
+  count_tracker.cc count_tracker.hh \
+  data_entry.cc data_entry.hh \
+  data_file.cc data_file.hh \
+  data_file_manager.cc data_file_manager.hh \
+  data_manager_base.cc	data_manager_base.hh \
+  default_message_display.cc	default_message_display.hh \
+  double_sum.cc double_sum.hh \
+  file.cc file.hh \
+  fixed_block.cc fixed_block.hh \
+  fixed_coords.hh \
+  functions.hh \
+	genesis.cc genesis.hh \
+  help_alias.cc help_alias.hh \
+  help_manager.cc help_manager.hh \
+  help_type.cc help_type.hh \
+  histogram.cc histogram.hh \
+  indexed_block_struct.cc indexed_block_struct.hh \
+	init_file.cc init_file.hh \
+  int_sum.cc int_sum.hh \
+  integrated_schedule.cc integrated_schedule.hh \
+  integrated_schedule_node.cc integrated_schedule_node.hh \
+  message_display.cc message_display.hh \
+  message_display_hdrs.hh \
+  merit.cc merit.hh \
+  prob_schedule.cc prob_schedule.hh \
+  random.cc random.hh \
+  ref_block.cc ref_block.hh \
+  running_average.cc running_average.hh \
+  scaled_block.cc scaled_block.hh \
+  schedule.cc schedule.hh \
+  string.cc string.hh \
+  string_iterator.cc string_iterator.hh \
+  string_list.cc string_list.hh \
+  string_util.cc string_util.hh \
+  tools.cc tools.hh \
+  tArray.hh \
+  tBuffer.hh \
+  tDataEntryBase.hh \
+  tDictionary.hh \
+  tList.hh \
+  tMatrix.hh \
+  tVector.hh \
+  uint.hh \
+  weighted_index.cc weighted_index.hh \
+  win32_mkdir_hack.hh
 
 noinst_LIBRARIES = libtools.a
 

Index: avida/current/source/cpu/4stack_head.cc
+++ avida/current/source/cpu/4stack_head.cc
/////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef FOURSTACK_HEAD_HH
#include "4stack_head.hh"
#endif

#ifndef CPU_MEMORY_HH
#include "cpu_memory.hh"
#endif
#ifndef HARDWARE_BASE_HH
#include "hardware_base.hh"
#endif
#ifndef INST_SET_HH
#include "inst_set.hh"
#endif
#ifndef INSTRUCTION_HH
#include "instruction.hh"
#endif

#include <assert.h>

c4StackHead::c4StackHead() : cCPUHead() { mem_space=0; }

c4StackHead::c4StackHead(cHardwareBase * in_hardware, int in_pos, int in_mem_space) 
  : cCPUHead(in_hardware, in_pos) { mem_space = in_mem_space; }

c4StackHead::c4StackHead(const c4StackHead & in_head) : cCPUHead(in_head) 
{ 
  mem_space = in_head.mem_space; 
}

void c4StackHead::Adjust()
{
  assert(cur_hardware != NULL);
  assert(main_hardware != NULL);

  const int mem_size = GetMemory().GetSize();

  // If we are still in range, stop here!
  if (position >= 0 && position < mem_size) return;

  // If the memory is gone, just stick it at the begining of its parent.
  if (mem_size == 0) {
    cur_hardware = main_hardware;
    position = 0;
  }
  else if (position <= 0) { position = 0; }
  else if (position >= mem_size) {
    // Always loop into the begining of the owner hardware.
    cur_hardware = main_hardware;
    position -= mem_size;
    while (position >= GetMemory().GetSize()) {
      // position back at the begining of the creature.
      position %= GetMemory().GetSize();
    }
  }
}

void c4StackHead::Reset(int in_mem_space, cHardwareBase * new_hardware)
{
  if (new_hardware) main_hardware = new_hardware;
  cur_hardware  = new_hardware;
  position = 0;
  mem_space = in_mem_space;
}

void c4StackHead::Set(int new_pos, int in_mem_space, cHardwareBase * in_hardware)
{
  position = new_pos;
  if (in_hardware) cur_hardware = in_hardware;
  mem_space = in_mem_space;
  Adjust();
}

void c4StackHead::Set(const c4StackHead & in_head)
{
  position = in_head.position;
  cur_hardware = in_head.cur_hardware;
  mem_space = in_head.mem_space;
  Adjust();
}

void c4StackHead::LoopJump(int jump)
{
  position += jump;

  // If we are out of range, bring back in.
  if (position < 0 || position >= GetMemory().GetSize()) {
    position %= GetMemory().GetSize();
    if (position <= 0) position += GetMemory().GetSize();
  }
}

const cCPUMemory & c4StackHead::GetMemory() const
{
  assert(cur_hardware != NULL);
  return cur_hardware->GetMemory(mem_space);
}

cCPUMemory & c4StackHead::GetMemory()
{
  assert(cur_hardware != NULL);
  return cur_hardware->GetMemory(mem_space);
}

const cInstruction & c4StackHead::GetInst() const
{
  assert(position >= 0);
  assert(position < GetMemory().GetSize());
  return GetMemory()[position];
}

const cInstruction & c4StackHead::GetInst(int offset) const 
{
  int new_pos = position + offset;
  return GetMemory()[new_pos];
}


void c4StackHead::SetInst(const cInstruction & value)
{
  assert(cur_hardware != NULL);
#ifdef WRITE_PROTECTION
  if (main_hardware == cur_hardware) GetMemory()[position] = value;
#else
  GetMemory()[position] = value;
  if (main_hardware != cur_hardware) cur_hardware->SetModified();
#endif
}

void c4StackHead::InsertInst(const cInstruction & value)
{
  assert(cur_hardware != NULL);
#ifdef WRITE_PROTECTION
  if (main_hardware == cur_hardware) GetMemory().Insert(position, value);
#else
  GetMemory().Insert(position, value);
  if (main_hardware != cur_hardware) cur_hardware->SetModified();
#endif
}

void c4StackHead::RemoveInst()
{
  assert(cur_hardware != NULL);
#ifdef WRITE_PROTECTION
  if (main_hardware == cur_hardware) GetMemory().Remove(position);
#else
  GetMemory().Remove(position);
  if (main_hardware != cur_hardware) cur_hardware->SetModified();
#endif
}

const cInstruction & c4StackHead::GetNextInst()
{
  return (AtEnd()) ? cInstSet::GetInstError() : GetMemory()[position+1];
}

bool & c4StackHead::FlagCopied()
{
  assert(cur_hardware != NULL);
  return GetMemory().FlagCopied(position);     
}

bool & c4StackHead::FlagMutated()
{
  assert(cur_hardware != NULL);
  return GetMemory().FlagMutated(position);    
}

bool & c4StackHead::FlagExecuted()
{
  assert(cur_hardware != NULL);
  return GetMemory().FlagExecuted(position);   
}

bool & c4StackHead::FlagBreakpoint()
{
  assert(cur_hardware != NULL);
  return GetMemory().FlagBreakpoint(position); 
}

bool & c4StackHead::FlagPointMut()
{
  assert(cur_hardware != NULL);
  return GetMemory().FlagPointMut(position);   
}

bool & c4StackHead::FlagCopyMut()
{
  assert(cur_hardware != NULL);
  return GetMemory().FlagCopyMut(position);    
}

c4StackHead & c4StackHead::operator=(const c4StackHead & in_cpu_head)
{
  main_hardware = in_cpu_head.main_hardware;
  cur_hardware  = in_cpu_head.cur_hardware;
  position = in_cpu_head.position;
  mem_space = in_cpu_head.mem_space;
  return *this;
}

bool c4StackHead::operator==(const c4StackHead & in_cpu_head) const 
{
  return (cur_hardware == in_cpu_head.cur_hardware) && 
    (position == in_cpu_head.position) &&
    (mem_space == in_cpu_head.mem_space);
}
  
bool c4StackHead::AtEnd() const
{
  return (position + 1 == GetMemory().GetSize());
}

bool c4StackHead::InMemory() const
{
  return (position >= 0 && position < GetMemory().GetSize());
}


Index: avida/current/source/cpu/4stack_head.hh
+++ avida/current/source/cpu/4stack_head.hh
/////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef FOURSTACK_HEAD_HH
#define FOURSTACK_HEAD_HH

#ifndef CPU_HEAD_HH
#include "cpu_head.hh"
#endif
#ifndef DEFS_HH
#include "defs.hh"
#endif

class cCodeLabel;
class cCPUMemory;
class cGenome;
class cHardwareBase;
class cInstruction;

class c4StackHead : public cCPUHead {
private:
  int mem_space;

public:

  c4StackHead();
  c4StackHead(cHardwareBase * in_hardware, int in_pos = 0, int mem_space = 0);
  c4StackHead(const c4StackHead & in_cpu_head);

  void Adjust();
  void Reset(int in_mem_space=0, cHardwareBase * new_hardware = NULL);
  void Set(int new_pos, int in_mem_space = 0, cHardwareBase * in_hardware = NULL);
  void Set(const c4StackHead & in_head);
  void LoopJump(int jump);
  const cCPUMemory & GetMemory() const;
  cCPUMemory & GetMemory();
  const cInstruction & GetInst() const;
  const cInstruction & GetInst(int offset) const;

  int GetMemSpace() const { return mem_space; }

  void SetInst(const cInstruction & value);
  void InsertInst(const cInstruction & in_char);
  void RemoveInst();
  const cInstruction & GetNextInst();

  bool & FlagCopied();
  bool & FlagMutated();
  bool & FlagExecuted();
  bool & FlagBreakpoint();
  bool & FlagPointMut();
  bool & FlagCopyMut();

  // Operator Overloading...
  c4StackHead & operator=(const c4StackHead & in_cpu_head);
  bool operator==(const c4StackHead & in_cpu_head) const; 
  bool AtEnd() const;
  bool InMemory() const;
};

#endif

Index: avida/current/source/cpu/code_label.cc
+++ avida/current/source/cpu/code_label.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2002 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#include "code_label.hh"

#include "tools.hh" // for g_memory & g_debug



using namespace std;



////////////////////////////////
// cCodeLabel stuff...
////////////////////////////////

cCodeLabel::cCodeLabel()
  : size(0)
{
}

cCodeLabel::cCodeLabel(const cCodeLabel &in_label)
  : nop_sequence(in_label.nop_sequence)
  , size(in_label.size)
{
}

cCodeLabel::~cCodeLabel()
{
}

bool cCodeLabel::OK()
{
  bool result = true;

  assert (size <= MAX_LABEL_SIZE);
  assert (size <= nop_sequence.GetSize());
  for (int i = 0; i < size; i++) {
    assert (nop_sequence[i] < MAX_NOPS);
  }

  return result;
}

bool cCodeLabel::operator==(const cCodeLabel & other_label) const
{
  if (size != other_label.GetSize()) {
    return false;
  }

  for (int i = 0; i < size; i++) {
    if (nop_sequence[i] != other_label[i]) {
      return false;
    }
  }

  return true;
}


// This function returns true if the sub_label can be found within
// the label affected.
int cCodeLabel::FindSublabel(cCodeLabel & sub_label)
{
  bool error = false;

  for (int offset = 0; offset <= size - sub_label.GetSize(); offset++) {
    for (int i = 0; i < sub_label.GetSize(); i++) {
      if (nop_sequence[i + offset] != sub_label[i]) {
	error = true;
	break;
      }
    }
    if (!error) return offset;
    error = false;
  }

  return -1;
}

void cCodeLabel::SaveState(ostream & fp)
{
//   assert(fp.good());
//   fp<<"cCodeLabel"<<" ";

//   fp<<"|"; // marker

//   fp << size << " " << base << " ";
//   for( int i=0; i < size; ++i ){
//     fp<<nop_sequence[i];
//   }
//   fp<<endl;
}


void cCodeLabel::LoadState(istream & fp)
{
//   assert(fp.good());
//   cString foo;
//   fp>>foo;
//   assert( foo == "cCodeLabel");

//   char marker;
//   fp>>marker;
//   assert( marker == '|' );

//   fp.get(size);
//   fp.get(base);
//   for( int i=0; i<MAX_LABEL_SIZE; ++i ){
//     fp.get(nop_sequence[i]);
//   }
}




Index: avida/current/source/cpu/code_label.hh
+++ avida/current/source/cpu/code_label.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef CODE_LABEL_HH
#define CODE_LABEL_HH

#ifndef CPU_DEFS_HH
#include "cpu_defs.hh"        // #defines only
#endif
#ifndef DEFS_HH
#include "defs.hh"
#endif
#ifndef STRING_HH
#include "string.hh"
#endif
#ifndef TARRAY_HH
#include "tArray.hh"
#endif
#ifndef TOOLS_HH
#include "tools.hh"
#endif

/**
 * The cCodeLabel class is used to identify a label within the genotype of
 * a creature, and aid in its manipulation.
 **/

class cCodeLabel {
private:
  tArray<char> nop_sequence;
  int size;
  //const int base;
public:
  cCodeLabel();//int in_base=MAX_NOPS);
  cCodeLabel(const cCodeLabel &in_label);
  ~cCodeLabel();

  bool OK();
  bool operator==(const cCodeLabel & other_label) const;
  bool operator!=(const cCodeLabel & other_label) const
    { return !(operator==(other_label)); }
  char operator[](int position) const { return (int) nop_sequence[position]; }
  int FindSublabel(cCodeLabel & sub_label);

  void Clear() { size = 0; }
  inline void AddNop(int nop_num);
  inline void Rotate(const int rot, const int base);

  int GetSize() const { return size; }
  //int GetBase() const { return base; }
  inline cString AsString() const;
  inline int AsInt(const int base) const;

  void SaveState(std::ostream & fp);
  void LoadState(std::istream & fp);
};

void cCodeLabel::AddNop(int nop_num) {
  assert (nop_num < MAX_NOPS);

  if (size < MAX_LABEL_SIZE) {
    if (size == nop_sequence.GetSize()) {
      nop_sequence.Resize(size+1);
    }
    nop_sequence[size++] = (char) nop_num;
  }
}

void cCodeLabel::Rotate(const int rot, const int base)
{
  //for (int i = 0; i < size; i++) {
  //  nop_sequence[i] += rot;
  //  if (nop_sequence[i] == 3) nop_sequence[i]++; //IGNORING NOP-D FOR NOW!
  //  if (nop_sequence[i] >= base) nop_sequence[i] -= base;
  //}
  for (int i = 0; i < size; i++) {
    nop_sequence[i] += rot;
    //if (nop_sequence[i] == 3) nop_sequence[i]++; //IGNORING NOP-D FOR NOW!
    if (nop_sequence[i] >= base) nop_sequence[i] -= base;
  }
}


cString cCodeLabel::AsString() const
{
  cString out_string;
  for (int i = 0; i < size; i++) {
    out_string += (char) nop_sequence[i] + 'A';
  }

  return out_string;
}

int cCodeLabel::AsInt(const int base) const
{
  int value = 0;

  for (int i = 0; i < size; i++) {
    value *= base;
    value += nop_sequence[i];
  }

  return value;
}

#endif

Index: avida/current/source/cpu/cpu_head.cc
+++ avida/current/source/cpu/cpu_head.cc
/////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef CPU_HEAD_HH
#include "cpu_head.hh"
#endif

#ifndef CPU_MEMORY_HH
#include "cpu_memory.hh"
#endif
#ifndef CODE_LABEL_HH
#include "code_label.hh"
#endif
#ifndef GENOME_HH
#include "genome.hh"
#endif
#ifndef HARDWARE_BASE_HH
#include "hardware_base.hh"
#endif
#ifndef INST_SET_HH
#include "inst_set.hh"
#endif
#ifndef INSTRUCTION_HH
#include "instruction.hh"
#endif

#include <assert.h>

class cHardwareBase; // access
class cCPUMemory; // access
class cCodeLabel; // access
class cInstSet; // access

cCPUHead::cCPUHead() {
  main_hardware = NULL;
  cur_hardware = NULL;
  position = 0;
}

cCPUHead::cCPUHead(cHardwareBase * in_hardware, int in_pos) {
  main_hardware = in_hardware;
  cur_hardware  = in_hardware;

  position = in_pos;
  if (in_pos) Adjust();
}

cCPUHead::cCPUHead(const cCPUHead & in_cpu_head) {
  main_hardware = in_cpu_head.main_hardware;
  cur_hardware  = in_cpu_head.cur_hardware;
  position = in_cpu_head.position;
}



void cCPUHead::Adjust()
{
  assert(cur_hardware != NULL);
  assert(main_hardware != NULL);

  const int mem_size = cur_hardware->GetMemory().GetSize();

  // If we are still in range, stop here!
  if (position >= 0 && position < mem_size) return;

  // If the memory is gone, just stick it at the begining of its parent.
  if (mem_size == 0) {
    cur_hardware = main_hardware;
    position = 0;
  }
  else if (position <= 0) { position = 0; }
  else if (position >= mem_size) {
    // Always loop into the begining of the owner hardware.
    cur_hardware = main_hardware;
    position -= mem_size;
    while (position >= GetMemory().GetSize()) {
      // position back at the begining of the creature.
      position %= GetMemory().GetSize();
    }
  }

}



/////////////////////////////////////////////////////////////////////////
// Method: cCPUHead::FindLabel(direction)
//
// Search in 'direction' (+ or - 1) from this head for the compliment of
//  the label in 'next_label' and return a head to the resulting pos.
//
/////////////////////////////////////////////////////////////////////////

cCPUHead cCPUHead::FindLabel(const cCodeLabel & label, int direction)
{
  // Make sure the label is of size > 0.
  if (label.GetSize() == 0) {
    return *this;
  }

  int found_pos = -1;

  // Call special functions depending on if jump is forwards or backwards.
  if( direction < 0 ) {
    found_pos =
      FindLabel_Backward(label, GetMemory(), GetPosition() - label.GetSize());
  }

  // Jump forwards.
  else {
    found_pos = FindLabel_Forward(label, GetMemory(), GetPosition());
  }

  if (found_pos >= 0) {
    // Return the last line of the found label, or the starting point.
    cCPUHead search_head(*this);
    search_head.Set(found_pos - 1);
    return search_head;
  }

  // It wasn't found; return the starting position of the instruction pointer.
  return *this;
}

void cCPUHead::Reset(cHardwareBase * new_hardware) {
  if (new_hardware) main_hardware = new_hardware;
  cur_hardware  = new_hardware;
  position = 0;
}

void cCPUHead::Set(int new_pos, cHardwareBase * in_hardware)
{
  position = new_pos;
  if (in_hardware) cur_hardware = in_hardware;
  Adjust();
}


void cCPUHead::Jump(int jump)
{
  position += jump;
  Adjust();
}

void cCPUHead::LoopJump(int jump)
{
  position += jump;

  // If we are out of range, bring back in.
  if (position < 0 || position >= GetMemory().GetSize()) {
    position %= GetMemory().GetSize();
    if (position <= 0) position += GetMemory().GetSize();
  }
}

void cCPUHead::AbsJump(int jump)
{
  position += jump;
}

void cCPUHead::Advance()
{
  position++;
  Adjust();
}

void cCPUHead::Retreat()
{
  position--;
  Adjust();
}


const cCPUMemory & cCPUHead::GetMemory() const
{
  assert(cur_hardware != NULL);
  return cur_hardware->GetMemory();
}


const cInstruction & cCPUHead::GetInst() const
{
  assert(position >= 0);
  assert(position < GetMemory().GetSize());
  return GetMemory()[position];
}

const cInstruction & cCPUHead::GetInst(int offset) const {
  int new_pos = position + offset;

  return GetMemory()[new_pos];
}


void cCPUHead::SetInst(const cInstruction & value)
{
  assert(cur_hardware != NULL);
#ifdef WRITE_PROTECTION
  if (main_hardware == cur_hardware) cur_hardware->GetMemory()[position] = value;
#else
  cur_hardware->GetMemory()[position] = value;
  if (main_hardware != cur_hardware) cur_hardware->SetModified();
#endif
}


void cCPUHead::InsertInst(const cInstruction & value)
{
  assert(cur_hardware != NULL);
#ifdef WRITE_PROTECTION
  if (main_hardware == cur_hardware) cur_hardware->GetMemory().Insert(position, value);
#else
  cur_hardware->GetMemory().Insert(position, value);
  if (main_hardware != cur_hardware) cur_hardware->SetModified();
#endif
}

void cCPUHead::RemoveInst()
{
  assert(cur_hardware != NULL);
#ifdef WRITE_PROTECTION
  if (main_hardware == cur_hardware) cur_hardware->GetMemory().Remove(position);
#else
  cur_hardware->GetMemory().Remove(position);
  if (main_hardware != cur_hardware) cur_hardware->SetModified();
#endif
}

const cInstruction & cCPUHead::GetNextInst()
{
  return (AtEnd()) ? cInstSet::GetInstError() : GetMemory()[position+1];
}



bool & cCPUHead::FlagCopied()
{
  assert(cur_hardware != NULL);
  return cur_hardware->GetMemory().FlagCopied(position);     
}

bool & cCPUHead::FlagMutated()
{
  assert(cur_hardware != NULL);
  return cur_hardware->GetMemory().FlagMutated(position);    
}

bool & cCPUHead::FlagExecuted()
{
  assert(cur_hardware != NULL);
  return cur_hardware->GetMemory().FlagExecuted(position);   
}

bool & cCPUHead::FlagBreakpoint()
{
  assert(cur_hardware != NULL);
  return cur_hardware->GetMemory().FlagBreakpoint(position); 
}

bool & cCPUHead::FlagPointMut()
{
  assert(cur_hardware != NULL);
  return cur_hardware->GetMemory().FlagPointMut(position);   
}

bool & cCPUHead::FlagCopyMut()
{
  assert(cur_hardware != NULL);
  return cur_hardware->GetMemory().FlagCopyMut(position);    
}

cCPUHead & cCPUHead::operator=(const cCPUHead & in_cpu_head)
{
  main_hardware = in_cpu_head.main_hardware;
  cur_hardware  = in_cpu_head.cur_hardware;
  position = in_cpu_head.position;
  return *this;
}


cCPUHead & cCPUHead::operator++()
{
  position++;
  Adjust();
  return *this;
}

cCPUHead & cCPUHead::operator--()
{
  position--;
  Adjust();
  return *this;
}

cCPUHead & cCPUHead::operator++(int)
{
  return operator++();
}

cCPUHead & cCPUHead::operator--(int)
{
  return operator--();
}

  
// Search forwards for search_label from _after_ position pos in the
// memory.  Return the first line _after_ the the found label.  It is okay
// to find search label's match inside another label.

int cCPUHead::FindLabel_Forward(const cCodeLabel & search_label,
				   const cGenome & search_mem, int pos)
{ 
  assert (pos < search_mem.GetSize() && pos >= 0);

  int search_start = pos;
  int label_size = search_label.GetSize();
  bool found_label = false;
  const cInstSet & inst_set = main_hardware->GetInstSet();

  // Move off the template we are on.
  pos += label_size;
  
  // Search until we find the complement or exit the memory.
  while (pos < search_mem.GetSize()) {

    // If we are within a label, rewind to the beginning of it and see if
    // it has the proper sub-label that we're looking for.

    if (inst_set.IsNop(search_mem[pos])) {
      // Find the start and end of the label we're in the middle of.

      int start_pos = pos;
      int end_pos = pos + 1;
      while (start_pos > search_start &&
	     inst_set.IsNop( search_mem[start_pos - 1] )) {
	start_pos--;
      }
      while (end_pos < search_mem.GetSize() &&
	     inst_set.IsNop( search_mem[end_pos] )) {
	end_pos++;
      }
      int test_size = end_pos - start_pos;

      // See if this label has the proper sub-label within it.
      int max_offset = test_size - label_size + 1;
      for (int offset = start_pos; offset < start_pos + max_offset; offset++) {

	// Test the number of matches for this offset.
	int matches;
	for (matches = 0; matches < label_size; matches++) {
	  if (search_label[matches] !=
	      inst_set.GetNopMod( search_mem[offset + matches] )) {
	    break;
	  }
	}

	// If we have found it, break out of this loop!
	if (matches == label_size) {
	  found_label = true;
	  break;
	}
      }

      // If we've found the complement label, set the position to the end of
      // the label we found it in, and break out.

      if (found_label == true) {
	pos = end_pos;
	break;
      }

      // We haven't found it; jump pos to just after the current label being
      // checked.
      pos = end_pos;
    }

    // Jump up a block to the next possible point to find a label,
    pos += label_size;
  }

  // If the label was not found return a -1.
  if (found_label == false) pos = -1;

  return pos;
}

// Search backwards for search_label from _before_ position pos in the
// memory.  Return the first line _after_ the the found label.  It is okay
// to find search label's match inside another label.

int cCPUHead::FindLabel_Backward(const cCodeLabel & search_label,
				   const cGenome & search_mem, int pos)
{ 
  assert (pos < search_mem.GetSize());
     
  int search_start = pos;
  int label_size = search_label.GetSize();
  bool found_label = false;
  const cInstSet & inst_set = main_hardware->GetInstSet();

  // Move off the template we are on.
  pos -= label_size;
  
  // Search until we find the complement or exit the memory.
  while (pos >= 0) {
    // If we are within a label, rewind to the beginning of it and see if
    // it has the proper sub-label that we're looking for.

    if (inst_set.IsNop( search_mem[pos] )) {
      // Find the start and end of the label we're in the middle of.

      int start_pos = pos;
      int end_pos = pos + 1;
      while (start_pos > 0 && inst_set.IsNop(search_mem[start_pos - 1])) {
	start_pos--;
      }
      while (end_pos < search_start &&
	     inst_set.IsNop( search_mem[end_pos] )) {
	end_pos++;
      }
      int test_size = end_pos - start_pos;

      // See if this label has the proper sub-label within it.
      int max_offset = test_size - label_size + 1;
      for (int offset = start_pos; offset < start_pos + max_offset; offset++) {

	// Test the number of matches for this offset.
	int matches;
	for (matches = 0; matches < label_size; matches++) {
	  if (search_label[matches] !=
	      inst_set.GetNopMod( search_mem[offset + matches] )) {
	    break;
	  }
	}

	// If we have found it, break out of this loop!
	if (matches == label_size) {
	  found_label = true;
	  break;
	}
      }

      // If we've found the complement label, set the position to the end of
      // the label we found it in, and break out.

      if (found_label == true) {
	pos = end_pos;
	break;
      }

      // We haven't found it; jump pos to just before the current label
      // being checked.
      pos = start_pos - 1;
    }

    // Jump up a block to the next possible point to find a label,
    pos -= label_size;
  }

  // If the label was not found return a -1.
  if (found_label == false) pos = -1;

  return pos;
}

bool cCPUHead::operator==(const cCPUHead & in_cpu_head) const {
  return (cur_hardware == in_cpu_head.cur_hardware) &&
    (position == in_cpu_head.position);
}

bool cCPUHead::AtEnd() const
{
  return (position + 1 == GetMemory().GetSize());
}

bool cCPUHead::InMemory() const
{
  return (position >= 0 && position < GetMemory().GetSize());
}

int cCPUHead::TestParasite() const
{
  // If CPU has a head in another creature, mark it as a parasite.
  return (cur_hardware != main_hardware);
}

Index: avida/current/source/cpu/cpu_head.hh
+++ avida/current/source/cpu/cpu_head.hh
/////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef CPU_HEAD_HH
#define CPU_HEAD_HH

#ifndef DEFS_HH
#include "defs.hh"
#endif

class cHardwareBase;
class cCodeLabel;
class cGenome;
class cCPUMemory;

/**
 * The cCPUHead class contains a pointer to locations in memory for a CPU.
 **/

class cHardwareBase;
class cCodeLabel;
class cGenome;
class cInstruction;

class cCPUHead {
protected:
  cHardwareBase * main_hardware;
  cHardwareBase * cur_hardware;
  int position;

  int FindLabel_Forward(const cCodeLabel & search_label,
			const cGenome & search_mem, int pos);
  int FindLabel_Backward(const cCodeLabel & search_label,
			 const cGenome & search_mem, int pos);
public:
  cCPUHead();
  cCPUHead(cHardwareBase * in_hardware, int in_pos = 0);
  cCPUHead(const cCPUHead & in_cpu_head);
  virtual ~cCPUHead() { ; }
  
  /**
   * This function keeps the position within the range of the current memory.
   **/
  virtual void Adjust();

  virtual void Reset(cHardwareBase * new_hardware = NULL);
  
  /**
   * Set the new position of the head (and adjust it into range in Set()).
   **/

  virtual void Set(int new_pos, cHardwareBase * in_hardware = NULL);
  
  void AbsSet(int new_pos) { position = new_pos; }
  
  virtual void Set(const cCPUHead & in_head) {
    position = in_head.position;
    cur_hardware  = in_head.cur_hardware;
  }

  /**
   * Increment the new position of the head by 'jump'.
   **/

  void Jump(int jump);
  virtual void LoopJump(int jump);
  void AbsJump(int jump);
  
  // Other manipulation functions.
  void Advance();
  void Retreat();
  cCPUHead FindLabel(const cCodeLabel & label, int direction=1);

  // Accessors.
  int GetPosition() const { return position; }
  virtual const cCPUMemory & GetMemory() const;
  cHardwareBase * GetCurHardware() const { return cur_hardware; }
  cHardwareBase * GetMainHardware() const { return main_hardware; }
  virtual const cInstruction & GetInst() const;
  virtual const cInstruction & GetInst(int offset) const;
  // int GetFlag(int id) const;

  virtual void SetInst(const cInstruction & value);
  virtual void InsertInst(const cInstruction & in_char);
  virtual void RemoveInst();
  virtual const cInstruction & GetNextInst();

  virtual bool & FlagCopied();
  virtual bool & FlagMutated();
  virtual bool & FlagExecuted();
  virtual bool & FlagBreakpoint();
  virtual bool & FlagPointMut();
  virtual bool & FlagCopyMut();

  // Operator Overloading...
  virtual cCPUHead & operator=(const cCPUHead & in_cpu_head);
  cCPUHead & operator++();
  cCPUHead & operator--();
  cCPUHead & operator++(int);
  cCPUHead & operator--(int);

  inline int operator-(const cCPUHead & in_cpu_head) {
    if (cur_hardware != in_cpu_head.cur_hardware) return 0;
    else return position - in_cpu_head.position;
  }
  virtual bool operator==(const cCPUHead & in_cpu_head) const;

  // Bool Tests...
  inline bool AtFront() const { return (position == 0); }
  virtual bool AtEnd() const;
  virtual bool InMemory() const;

  // Test functions...
  int TestParasite() const;
};

#endif

Index: avida/current/source/cpu/cpu_test_info.cc
+++ avida/current/source/cpu/cpu_test_info.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef CPU_TEST_INFO_HH
#include "cpu_test_info.hh"
#endif

#ifndef ORGANISM_HH
#include "organism.hh"
#endif
#ifndef PHENOTYPE_HH
#include "phenotype.hh"
#endif

#include <assert.h>

/////////////////
// cCPUTestInfo
/////////////////

cCPUTestInfo::cCPUTestInfo(int max_tests)
  : generation_tests(max_tests)  // These vars not reset on Clear()
  , test_threads(false)
  , print_threads(false)
  , trace_execution(false)
  , trace_task_order(false)
  , use_random_inputs(false)
  , org_array(max_tests)
{
  org_array.SetAll(NULL);
  Clear();
}


cCPUTestInfo::~cCPUTestInfo()
{
  for (int i = 0; i < generation_tests; i++) {
    if (org_array[i] != NULL) delete org_array[i];
  }
}


void cCPUTestInfo::Clear()
{
  is_viable = false;
  max_depth = -1;
  depth_found = -1;
  max_cycle = 0;
  cycle_to = -1;

  for (int i = 0; i < generation_tests; i++) {
    if (org_array[i] == NULL) break;
    delete org_array[i];
    org_array[i] = NULL;
  }
}
 

void cCPUTestInfo::SetTraceExecution(const cString & filename)
{
  trace_execution = true;
  trace_fp.open(filename);
  assert (trace_fp.good() == true); // Unable to open trace file.
}


double cCPUTestInfo::GetGenotypeFitness()
{
  if (org_array[0] != NULL) return org_array[0]->GetPhenotype().GetFitness();
  return 0.0;
}


double cCPUTestInfo::GetColonyFitness()
{
  if (IsViable()) return GetColonyOrganism()->GetPhenotype().GetFitness();
  return 0.0;
}

Index: avida/current/source/cpu/cpu_test_info.hh
+++ avida/current/source/cpu/cpu_test_info.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef CPU_TEST_INFO_HH
#define CPU_TEST_INFO_HH

#include <fstream>

#ifndef CPU_DEFS_HH
#include "cpu_defs.hh"
#endif
#ifndef TARRAY_HH
#include "tArray.hh"
#endif

class cOrganism;
class cString;

class cCPUTestInfo {
  friend class cTestCPU;
private:
  // Inputs...
  const int generation_tests; // Maximum depth in generations to test
  bool test_threads;          // Should a report of threading be saved?
  bool print_threads;         // Should the report be printed?
  bool trace_execution;       // Should we trace this CPU?
  bool trace_task_order;      // Should we keep track of ordering of tasks?
  bool use_random_inputs;     // Should we give the organism random inputs?
  std::ofstream trace_fp;

  // Outputs...
  bool is_viable;         // Is this organism colony forming?
  int max_depth;          // Deepest tests went...
  int depth_found;        // Depth actually found (often same as max_depth)
  int max_cycle;          // Longest cycle found.
  int cycle_to;           // Cycle path of the last genotype.

  tArray<cOrganism *> org_array;

public:
  cCPUTestInfo(int max_tests=TEST_CPU_GENERATIONS);
  ~cCPUTestInfo();

  void Clear();
 
  // Input Setup
  void TestThreads(bool _test=true) { test_threads = _test; }
  void PrintThreads(bool _print=true) { print_threads = _print; }
  void TraceTaskOrder(bool _trace=true) { trace_task_order = _trace; }
  void UseRandomInputs(bool _rand=true) { use_random_inputs = _rand; }
  void SetTraceExecution(const cString & filename="trace.dat");

  // Input Accessors
  int GetGenerationTests() const { return generation_tests; }
  bool GetTestThreads() const { return test_threads; }
  bool GetPrintThreads() const { return print_threads; }
  bool GetTraceTaskOrder() const { return trace_task_order; }
  bool GetUseRandomInputs() const { return use_random_inputs; }
  bool GetTraceExecution() const { return trace_execution; }
  std::ofstream & GetTraceFP() { return trace_fp; }


  // Output Accessors
  bool IsViable() const { return is_viable; }
  int GetMaxDepth() const { return max_depth; }
  int GetDepthFound() const { return depth_found; }
  int GetMaxCycle() const { return max_cycle; }
  int GetCycleTo() const { return cycle_to; }

  // Genotype Stats...
  cOrganism * GetTestOrganism(int level=0) {
    assert(org_array[level] != NULL);
    return org_array[level];
  }

  cOrganism * GetColonyOrganism() {
    const int depth_used = (depth_found == -1) ? 0 : depth_found;
    assert(org_array[depth_used] != NULL);
    return org_array[depth_used];
  }

  // And just because these are so commonly used...
  double GetGenotypeFitness();
  double GetColonyFitness();
};

#endif

Index: avida/current/source/cpu/hardware_4stack_constants.hh
+++ avida/current/source/cpu/hardware_4stack_constants.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef HARDWARE_4STACK_CONSTANTS_HH
#define HARDWARE_4STACK_CONSTANTS_HH

//new-style constant declarations - law 
static const int NUM_LOCAL_STACKS = 3;
static const int NUM_GLOBAL_STACKS = 1;
static const int NUM_STACKS = NUM_LOCAL_STACKS + NUM_GLOBAL_STACKS;
static const int STACK_AX = 0;
static const int STACK_BX = 1;
static const int STACK_CX = 2;
static const int STACK_DX = 3;
static const int NUM_NOPS_4STACK = 4;
static const int NUM_MEMORY_SPACES = 4; 

#endif

Index: avida/current/source/cpu/hardware_4stack_thread.cc
+++ avida/current/source/cpu/hardware_4stack_thread.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef HARDWARE_4STACK_THREAD_HH
#include "hardware_4stack_thread.hh"
#endif

using namespace std;

/////////////////////////
//  cHardware4Stack_Thread
/////////////////////////

cHardware4Stack_Thread::cHardware4Stack_Thread(cHardwareBase * in_hardware, int _id)
  : input_buf(INPUT_BUF_SIZE),
    output_buf(OUTPUT_BUF_SIZE)
{
  Reset(in_hardware, _id);
}

cHardware4Stack_Thread::cHardware4Stack_Thread(const cHardware4Stack_Thread & in_thread, int _id)
  : input_buf(INPUT_BUF_SIZE),
    output_buf(OUTPUT_BUF_SIZE)
{
   id = _id;
   if (id == -1) id = in_thread.id;
   for (int i = 0; i < NUM_LOCAL_STACKS; i++) {
     local_stacks[i] = in_thread.local_stacks[i];
   }
   for (int i = 0; i < NUM_HEADS; i++) {
     heads[i] = in_thread.heads[i];
   }
   input_pointer = in_thread.input_pointer;
   owner = in_thread.owner;
}

cHardware4Stack_Thread::~cHardware4Stack_Thread() {}

void cHardware4Stack_Thread::operator=(const cHardware4Stack_Thread & in_thread)
{
  id = in_thread.id;
  for (int i = 0; i < NUM_LOCAL_STACKS; i++) {
    local_stacks[i] = in_thread.local_stacks[i];
  }
  for (int i = 0; i < NUM_HEADS; i++) {
    heads[i] = in_thread.heads[i];
  }
  input_pointer = in_thread.input_pointer;
  input_buf = in_thread.input_buf;
  output_buf = in_thread.output_buf;
  owner = in_thread.owner;
}

void cHardware4Stack_Thread::Reset(cHardwareBase * in_hardware, int _id)
{
  id = _id;

  for (int i = 0; i < NUM_LOCAL_STACKS; i++) local_stacks[i].Clear();
  for (int i = 0; i < NUM_HEADS; i++) heads[i].Reset(0, in_hardware);

  cur_head = HEAD_IP;
  input_pointer = 0;
  input_buf.Clear();
  output_buf.Clear();
  read_label.Clear();
  next_label.Clear();
  owner = NULL;
}

void cHardware4Stack_Thread::SaveState(ostream & fp){
  assert(fp.good());
  fp << "cHardware4Stack_Thread" << endl;

  // stacks (NOT WORKING! -law)
  for( int i=0; i<NUM_STACKS; ++i ){
    local_stacks[i].SaveState(fp);
  }

  // heads (@TCC does not handle parasites!!!)
  for( int i=0; i<NUM_HEADS; ++i ){
    fp<<heads[i].GetPosition()<<endl;
  }

  fp<<"|"; // marker
  fp<<cur_head;
  fp<<input_pointer;
  fp<<endl;

  // IO buffers
  input_buf.SaveState(fp);
  output_buf.SaveState(fp);

  // Code labels
  read_label.SaveState(fp);
  next_label.SaveState(fp);
}

void cHardware4Stack_Thread::LoadState(istream & fp){
  assert(fp.good());
  cString foo;
  fp >> foo;
  assert( foo == "cHardware4Stack_Thread");

  // stacks (NOT WORKING!  -law)
  for( int i=0; i<NUM_STACKS; ++i ){
    local_stacks[i].LoadState(fp);
  }

  // heads (@TCC does not handle parasites!!!)
  for( int i=0; i<NUM_HEADS; ++i ){
    int pos;
    fp>>pos;
    heads[i].AbsSet(pos);
  }

  char marker; fp>>marker; assert( marker == '|' );
  /* YIKES!  data loss below: */ 
  char the_cur_head = cur_head;
  char the_input_pointer = input_pointer;
  fp.get(the_cur_head);
  fp.get(the_input_pointer);

  // IO buffers
  input_buf.LoadState(fp);
  output_buf.LoadState(fp);

  // Code labels
  read_label.LoadState(fp);
  next_label.LoadState(fp);
}

Index: avida/current/source/cpu/hardware_4stack_thread.hh
+++ avida/current/source/cpu/hardware_4stack_thread.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef HARDWARE_4STACK_THREAD_HH
#define HARDWARE_4STACK_THREAD_HH

#include <istream>
#include <ostream>

#ifndef CODE_LABEL_HH
#include "code_label.hh"
#endif
#ifndef CPU_STACK_HH
#include "cpu_stack.hh"
#endif
#ifndef FOURSTACK_HEAD_HH
#include "4stack_head.hh"
#endif
#ifndef HARDWARE_4STACK_CONSTANTS_HH
#include "hardware_4stack_constants.hh"
#endif
#ifndef TBUFFER_HH
#include "tBuffer.hh"
#endif

/**
 * This class is needed to run several threads on a single genome.
 *
 * @see cCPUStack, c4StackHead, cHardware4Stack
 **/

class c4StackHead; // aggregate
class cCodeLabel; // aggregate
class cCPUStack; // aggregate
class cHardwareBase;
class cInjectGenotype;
template <class T> class tBuffer; // aggregate

struct cHardware4Stack_Thread {
private:
  int id;
public:
  c4StackHead heads[NUM_HEADS];
  UCHAR cur_head;
  cCPUStack local_stacks[NUM_LOCAL_STACKS];

  int input_pointer;
  bool advance_ip;         // Should the IP advance after this instruction?
  tBuffer<int> input_buf;
  tBuffer<int> output_buf;
  cCodeLabel read_label;
  cCodeLabel next_label;
  // If this thread was spawned by Inject, this will point to the genotype 
  // of the parasite running the thread.  Otherwise, it will be NULL.
  cInjectGenotype* owner;
public:
  cHardware4Stack_Thread(cHardwareBase * in_hardware=NULL, int _id=-1);
  cHardware4Stack_Thread(const cHardware4Stack_Thread & in_thread, int _id=-1);
  ~cHardware4Stack_Thread();

  void operator=(const cHardware4Stack_Thread & in_thread);

  void Reset(cHardwareBase * in_hardware, int _id);
  int GetID() const { return id; }
  void SetID(int _id) { id = _id; }

  void SaveState(std::ostream & fp);
  void LoadState(std::istream & fp);
};

#endif

Index: avida/current/source/cpu/hardware_cpu_thread.cc
+++ avida/current/source/cpu/hardware_cpu_thread.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef HARDWARE_CPU_THREAD_HH
#include "hardware_cpu_thread.hh"
#endif

using namespace std;

/////////////////////////
//  cHardwareCPU_Thread
/////////////////////////

cHardwareCPU_Thread::cHardwareCPU_Thread(cHardwareBase * in_hardware, int _id)
  : input_buf(INPUT_BUF_SIZE),
    output_buf(OUTPUT_BUF_SIZE)
{
  Reset(in_hardware, _id);
}

cHardwareCPU_Thread::cHardwareCPU_Thread(const cHardwareCPU_Thread & in_thread, int _id)
  : input_buf(INPUT_BUF_SIZE),
    output_buf(OUTPUT_BUF_SIZE)
{
   id = _id;
   if (id == -1) id = in_thread.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;
   input_pointer = in_thread.input_pointer;
}

cHardwareCPU_Thread::~cHardwareCPU_Thread() {}

void cHardwareCPU_Thread::operator=(const cHardwareCPU_Thread & in_thread)
{
  id = in_thread.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;
  input_pointer = in_thread.input_pointer;
  input_buf = in_thread.input_buf;
  output_buf = in_thread.output_buf;
}

void cHardwareCPU_Thread::Reset(cHardwareBase * in_hardware, int _id)
{
  id = _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 = HEAD_IP;
  input_pointer = 0;
  input_buf.Clear();
  output_buf.Clear();
  read_label.Clear();
  next_label.Clear();
}




void cHardwareCPU_Thread::SaveState(ostream & fp){
  assert(fp.good());
  fp << "cHardwareCPU_Thread" << endl;

  // registers
  for( int i=0; i<NUM_REGISTERS; ++i ){
    fp<<reg[i]<<endl;
  }

  // heads (@TCC does not handle parasites!!!)
  for( int i=0; i<NUM_HEADS; ++i ){
    fp<<heads[i].GetPosition()<<endl;
  }

  stack.SaveState(fp);

  fp<<"|"; // marker
  fp<<cur_stack;
  fp<<cur_head;
  fp<<input_pointer;
  fp<<endl;

  // IO buffers
  input_buf.SaveState(fp);
  output_buf.SaveState(fp);

  // Code labels
  read_label.SaveState(fp);
  next_label.SaveState(fp);
}



void cHardwareCPU_Thread::LoadState(istream & fp){
  assert(fp.good());
  cString foo;
  fp >> foo;
  assert( foo == "cHardwareCPU_Thread");

  // registers
  for( int i=0; i<NUM_REGISTERS; ++i ){
    fp>>reg[i];
  }

  // heads (@TCC does not handle parasites!!!)
  for( int i=0; i<NUM_HEADS; ++i ){
    int pos;
    fp>>pos;
    heads[i].AbsSet(pos);
  }

  // stack
  stack.LoadState(fp);

  char marker; fp>>marker; assert( marker == '|' );
  /* YIKES!  data loss below: */
  char the_cur_stack = cur_stack;
  char the_cur_head = cur_head;
  char the_input_pointer = input_pointer;
  fp.get(the_cur_stack);
  fp.get(the_cur_head);
  fp.get(the_input_pointer);

  // IO buffers
  input_buf.LoadState(fp);
  output_buf.LoadState(fp);

  // Code labels
  read_label.LoadState(fp);
  next_label.LoadState(fp);
}

Index: avida/current/source/cpu/hardware_cpu_thread.hh
+++ avida/current/source/cpu/hardware_cpu_thread.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef HARDWARE_CPU_THREAD_HH
#define HARDWARE_CPU_THREAD_HH

#include <istream>
#include <ostream>

#ifndef CODE_LABEL_HH
#include "code_label.hh"
#endif
#ifndef CPU_DEFS_HH
#include "cpu_defs.hh"
#endif
#ifndef CPU_HEAD_HH
#include "cpu_head.hh"
#endif
#ifndef CPU_STACK_HH
#include "cpu_stack.hh"
#endif
#ifndef TBUFFER_HH
#include "tBuffer.hh"
#endif

/**
 * This class is needed to run several threads on a single genome.
 *
 * @see cCPUStack, cCPUHead, cHardwareCPU
 **/

class cCodeLabel; // aggregate;
class cCPUHead; // aggregate
class cCPUStack; // aggregate
class cHardwareBase;
template <class T> class tBuffer; // aggregate

struct cHardwareCPU_Thread {
private:
  int id;
public:
  int reg[NUM_REGISTERS];
  cCPUHead heads[NUM_HEADS];
  cCPUStack stack;
  UCHAR cur_stack;              // 0 = local stack, 1 = global stack.
  UCHAR cur_head;

  int input_pointer;
  tBuffer<int> input_buf;
  tBuffer<int> output_buf;
  cCodeLabel read_label;
  cCodeLabel next_label;
public:
  cHardwareCPU_Thread(cHardwareBase * in_hardware=NULL, int _id=-1);
  cHardwareCPU_Thread(const cHardwareCPU_Thread & in_thread, int _id=-1);
  ~cHardwareCPU_Thread();

  void operator=(const cHardwareCPU_Thread & in_thread);

  void Reset(cHardwareBase * in_hardware, int _id);
  int GetID() const { return id; }
  void SetID(int _id) { id = _id; }

  void SaveState(std::ostream & fp);
  void LoadState(std::istream & fp);
};

#endif

Index: avida/current/source/cpu/memory_flags.cc
+++ avida/current/source/cpu/memory_flags.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef MEMORY_FLAGS_HH
#include "memory_flags.hh"
#endif

//////////////////
//  cMemoryFlags
//////////////////

void cMemoryFlags::Clear()
{
  copied = false;
  mutated = false;
  executed = false;
  breakpoint = false;
  point_mut = false;
  copy_mut = false;
  injected = false;
}

Index: avida/current/source/cpu/memory_flags.hh
+++ avida/current/source/cpu/memory_flags.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef MEMORY_FLAGS_HH
#define MEMORY_FLAGS_HH

class cMemoryFlags {
  friend class cCPUMemory;
protected:
  bool copied;      // Has this site been copied?
  bool mutated;     // Has this site been mutated?
  bool executed;    // Has this site been executed?
  bool breakpoint;  // Has a breakpoint been set at this position?
  bool point_mut;   // Has there been a point mutation here?
  bool copy_mut;    // Has there been a copy mutation here?
  bool injected;    // Was this instruction injected into the genome?

public:
  cMemoryFlags() { Clear(); }
  ~cMemoryFlags() { ; }

  void Clear();
};

#endif

Index: avida/current/source/event/event_list_entry.cc
+++ avida/current/source/event/event_list_entry.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef EVENT_LIST_ENTRY_HH
#include "event_list_entry.hh"
#endif


/////////////////
//  cEventListEntry
/////////////////


cEventListEntry::cEventListEntry( cEvent * event,
				  cEventTriggers::eTriggerVariable trigger,
				  double start,
				  double interval,
				  double stop,
				  cEventListEntry * prev,
				  cEventListEntry * next ) :
  m_event( event ),
  m_trigger( trigger ),
  m_start( start ),
  m_interval( interval ),
  m_stop( stop ),
  m_original_start( start ),
  m_prev( prev ),
  m_next( next )
{
}


cEventListEntry::~cEventListEntry()
{
  delete m_event;
}

Index: avida/current/source/event/event_list_entry.hh
+++ avida/current/source/event/event_list_entry.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef EVENT_LIST_ENTRY_HH
#define EVENT_LIST_ENTRY_HH

#include <assert.h>

#ifndef EVENT_HH
#include "event.hh"
#endif
#ifndef EVENT_TRIGGERS_HH
#include "event_triggers.hh"
#endif

/**
 * This class holds a single event in the event list. It is used by the class
 * @ref cEventList. There is no need to use it in any other context.
 **/

class cEvent; // access
class cEventTriggers; // access

class cEventListEntry {
private:
  cEvent *m_event;

  cEventTriggers::eTriggerVariable m_trigger;
  double m_start;
  double m_interval;
  double m_stop;
  double m_original_start;

  cEventListEntry *m_prev;
  cEventListEntry *m_next;


   // not implemented, prevents inadvertent wrong instantiation
  cEventListEntry();
  cEventListEntry( const cEventListEntry & );
  cEventListEntry& operator=( const cEventListEntry& );
public:
  // creators
  cEventListEntry( cEvent *event = NULL,
		   cEventTriggers::eTriggerVariable trigger
		                   = cEventTriggers::UPDATE,
		   double start = cEventTriggers::TRIGGER_BEGIN,
		   double interval = cEventTriggers::TRIGGER_ONCE,
		   double stop = cEventTriggers::TRIGGER_END,
		   cEventListEntry *prev = NULL,
		   cEventListEntry *next = NULL );

  virtual ~cEventListEntry();


  // manipulators
  void Setup( cEvent *event,
	      cEventTriggers::eTriggerVariable trigger,
	      double start = cEventTriggers::TRIGGER_BEGIN,
	      double interval = cEventTriggers::TRIGGER_ONCE,
	      double stop = cEventTriggers::TRIGGER_END ){
    m_event = event;
    m_trigger = trigger;
    m_start = start;
    m_original_start = start;
    m_interval = interval;
    m_stop = stop;
  }

  void SetPrev(cEventListEntry * prev) { m_prev = prev; }
  void SetNext(cEventListEntry * next) { m_next = next; }

  void NextInterval() { m_start += m_interval; }
  void Reset() { m_start = m_original_start; }


  // accessors
  cEvent* GetEvent() const {
    assert(m_event!=NULL); return m_event; }

  const cString& GetName() const {
    assert(m_event!=NULL); return m_event->GetName(); }
  const cString& GetArgs() const {
    assert(m_event!=NULL); return m_event->GetArgs(); }

  cEventTriggers::eTriggerVariable  GetTrigger()  const { return m_trigger; }
  double            GetStart()    const { return m_start; }
  double            GetInterval() const { return m_interval; }
  double            GetStop()     const { return m_stop; }

  cEventListEntry*  GetPrev()     const { return m_prev; }
  cEventListEntry*  GetNext()     const { return m_next; }

};

#endif

Index: avida/current/source/event/event_list_iterator.cc
+++ avida/current/source/event/event_list_iterator.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef EVENT_LIST_ITERATOR_HH
#include "event_list_iterator.hh"
#endif

#ifndef EVENT_LIST_HH
#include "event_list.hh"
#endif

using namespace std;

/////////////////
//  cEventListIterator
//  added by kaben.
/////////////////

void
cEventListIterator::PrintEvent(ostream & os){
  cEventList::PrintEvent(m_node, os);
}


Index: avida/current/source/event/event_list_iterator.hh
+++ avida/current/source/event/event_list_iterator.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef EVENT_LIST_ITERATOR_HH
#define EVENT_LIST_ITERATOR_HH

#include <ostream>

#ifndef EVENT_LIST_ENTRY_HH
#include "event_list_entry.hh"
#endif

/**
 * sort of an iterator for cEventList;
 * doesn't allow access to its cEventListEntry, but will allow its entry
 * to be printed to an ostream.
 * added by Kaben.
 **/

class cEventListEntry; // access

class cEventListIterator {
private:
  cEventListEntry *m_node;
public:
  cEventListIterator() : m_node(0) {}
  cEventListIterator(cEventListEntry *node) : m_node(node) {}
  cEventListIterator(const cEventListIterator &it) : m_node(it.m_node) {}

  void PrintEvent(std::ostream & os = std::cout);

  bool operator==(const cEventListIterator &it) const {
    return m_node == it.m_node;
  }
  bool operator!=(const cEventListIterator &it) const {
    return m_node != it.m_node;
  }
  cEventListIterator& operator++() {
    m_node = m_node->GetNext();
    return *this;
  }
};

#endif

Index: avida/current/source/event/event_triggers.cc
+++ avida/current/source/event/event_triggers.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef EVENT_TRIGGERS_HH
#include "event_triggers.hh"
#endif

#include <float.h>           // for DBL_MIN
#include <iostream>

using namespace std;

/////////////////
//  cEventTriggers
/////////////////

double const cEventTriggers::TRIGGER_BEGIN = DBL_MIN;
double const cEventTriggers::TRIGGER_END = DBL_MAX;
double const cEventTriggers::TRIGGER_ALL = 0;
double const cEventTriggers::TRIGGER_ONCE = DBL_MAX;

double cEventTriggers::GetTriggerValue( eTriggerVariable trigger ) const
{
  // Returns TRIGGER_END if invalid, TRIGGER_BEGIN for IMMEDIATE
  double t_val = TRIGGER_END;
  switch( trigger ){
  case IMMEDIATE:
    t_val = TRIGGER_BEGIN;
    break;
  case UPDATE:
    t_val = GetUpdate();
    break;
  case GENERATION:
    t_val = GetGeneration();
    break;
  default:
    cerr << "Unknown Trigger in cEventTriggers::GetTriggerValue"  << endl;
  }
  return t_val;
}

Index: avida/current/source/event/event_triggers.hh
+++ avida/current/source/event/event_triggers.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef EVENT_TRIGGERS_HH
#define EVENT_TRIGGERS_HH

/**
 * This class is used to physically separate the whole event list business
 * from the world an so on. You have to derive from this object and fill
 * in the purely virtual functions with the appropriate contents.
 **/

class cEventTriggers {
public:
  enum eTriggerVariable { UPDATE, GENERATION, IMMEDIATE, UNDEFINED };

  static const double TRIGGER_BEGIN;
  static const double TRIGGER_END;
  static const double TRIGGER_ALL;
  static const double TRIGGER_ONCE;

private:
  // not implemented. prevents inadvertend wrong instantiation.
  cEventTriggers( const cEventTriggers& );
  cEventTriggers& operator=( const cEventTriggers& );
public:
  cEventTriggers() {}
  
  virtual double GetUpdate() const = 0;
  virtual double GetGeneration() const = 0;

  double GetTriggerValue( eTriggerVariable trigger ) const;
};

#endif

Index: avida/current/source/event/population_event.cc
+++ avida/current/source/event/population_event.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef POPULATION_EVENT_HH
#include "population_event.hh"
#endif

#ifndef EVENT_HH
#include "event.hh"
#endif
#ifndef STRING_HH
#include "string.hh"
#endif

cPopulationEvent::cPopulationEvent(const cString & name, const cString & args):
   cEvent(name, args)
{
}

Index: avida/current/source/event/population_event.hh
+++ avida/current/source/event/population_event.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef POPULATION_EVENT_HH
#define POPULATION_EVENT_HH

#ifndef EVENT_HH
#include "event.hh"
#endif

class cString;
class cPopulation;

class cPopulationEvent : public cEvent {
private:
  // not implemented. prevents inadvertend wrong instantiation.
  cPopulationEvent();
  cPopulationEvent( const cPopulationEvent & );
  const cPopulationEvent& operator=( cPopulationEvent & );

  
protected:
  cPopulation *population;
  
public:
  cPopulationEvent(const cString & name, const cString & args);

  void SetPopulation( cPopulation *pop ){ population = pop; }
};

#endif

Index: avida/current/source/main/analyze_command.hh
+++ avida/current/source/main/analyze_command.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef ANALYZE_COMMAND_HH
#define ANALYZE_COMMAND_HH

#ifndef STRING_HH
#include "string.hh"
#endif

// cAnalyzeCommand     : A command in a loaded program

class cString; // aggregate
template <class T> class tList;

class cAnalyzeCommand {
protected:
  cString command;
  cString args;
public:
  cAnalyzeCommand(const cString & _command, const cString & _args)
    : command(_command), args(_args) { command.ToUpper(); }
  virtual ~cAnalyzeCommand() { ; }

  const cString & GetCommand() { return command; }
  const cString & GetArgs() const { return args; }
  cString GetArgs() { return args; }
  virtual tList<cAnalyzeCommand> * GetCommandList() { return NULL; }
};

#endif

Index: avida/current/source/main/analyze_command_def.hh
+++ avida/current/source/main/analyze_command_def.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef ANALYZE_COMMAND_DEF_HH
#define ANALYZE_COMMAND_DEF_HH

#ifndef ANALYZE_COMMAND_DEF_BASE_HH
#include "analyze_command_def_base.hh"
#endif
#ifndef STRING_HH
#include "string.hh"
#endif

class cAnalyze;
class cString; // aggregate
class cAnalyzeCommand;

class cAnalyzeCommandDef : public cAnalyzeCommandDefBase {
private:
  void (cAnalyze::*CommandFunction)(cString);
public:
  cAnalyzeCommandDef(const cString & _name, void (cAnalyze::*_cf)(cString))
    : cAnalyzeCommandDefBase(_name), CommandFunction(_cf) { ; }
  virtual ~cAnalyzeCommandDef() { ; }

  virtual void Run(cAnalyze * analyze, const cString & args,
		   cAnalyzeCommand & command) const {
    (void) command; // used in other types of command defininitions.
    (analyze->*CommandFunction)(args);
  }
};

#endif

Index: avida/current/source/main/analyze_command_def_base.hh
+++ avida/current/source/main/analyze_command_def_base.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef ANALYZE_COMMAND_DEF_BASE_HH
#define ANALYZE_COMMAND_DEF_BASE_HH

#ifndef STRING_HH
#include "string.hh"
#endif

class cString; // aggregate
class cAnalyze;
class cAnalyzeCommand;

class cAnalyzeCommandDefBase {
protected:
  cString name;
public:
  cAnalyzeCommandDefBase(const cString & _name) : name(_name) { ; }
  virtual ~cAnalyzeCommandDefBase() { ; }

  virtual void Run(cAnalyze * analyze, const cString & args,
		   cAnalyzeCommand & command) const = 0;
  virtual bool IsFlowCommand() { return false; }

  const cString & GetName() const { return name; }
};

#endif

Index: avida/current/source/main/analyze_flow_command.hh
+++ avida/current/source/main/analyze_flow_command.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef ANALYZE_FLOW_COMMAND_HH
#define ANALYZE_FLOW_COMMAND_HH

#ifndef ANALYZE_COMMAND_HH
#include "analyze_command.hh"
#endif
#ifndef TLIST_HH
#include "tList.hh"
#endif

// cAnalyzeFlowCommand : A cAnalyzeCommand containing other commands

template <class T> class tList; // aggregate
class cString;

class cAnalyzeFlowCommand : public cAnalyzeCommand {
protected:
  tList<cAnalyzeCommand> command_list;
public:
  cAnalyzeFlowCommand(const cString & _command, const cString & _args)
    : cAnalyzeCommand(_command, _args) { ; }
  virtual ~cAnalyzeFlowCommand() {
    while ( command_list.GetSize() > 0 ) delete command_list.Pop();
  }

  tList<cAnalyzeCommand> * GetCommandList() { return &command_list; }
};

#endif

Index: avida/current/source/main/analyze_flow_command_def.hh
+++ avida/current/source/main/analyze_flow_command_def.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef ANALYZE_FLOW_COMMAND_DEF_HH
#define ANALYZE_FLOW_COMMAND_DEF_HH

#ifndef ANALYZE_COMMAND_HH
#include "analyze_command.hh"
#endif
#ifndef ANALYZE_COMMAND_DEF_BASE_HH
#include "analyze_command_def_base.hh"
#endif
#ifndef STRING_HH
#include "string.hh"
#endif
#ifndef TLIST_HH
#include "tList.hh"
#endif

class cAnalyze;
template <class T> class tList;
class cAnalyzeCommand; // access
class cString; // aggregate

class cAnalyzeFlowCommandDef : public cAnalyzeCommandDefBase {
private:
  void (cAnalyze::*CommandFunction)(cString, tList<cAnalyzeCommand> &);
public:
  cAnalyzeFlowCommandDef(const cString &_name,
	 void (cAnalyze::*_cf)(cString, tList<cAnalyzeCommand> &))
    : cAnalyzeCommandDefBase(_name), CommandFunction(_cf) { ; }
  virtual ~cAnalyzeFlowCommandDef() { ; }
			 
  virtual void Run(cAnalyze * analyze, const cString & args,
		   cAnalyzeCommand & command) const {
    (analyze->*CommandFunction)(args, *(command.GetCommandList()) );
  }

  virtual bool IsFlowCommand() { return true; }
};

#endif

Index: avida/current/source/main/analyze_function.hh
+++ avida/current/source/main/analyze_function.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef ANALYZE_FUNCTION_HH
#define ANALYZE_FUNCTION_HH

#ifndef ANALYZE_COMMAND_HH
#include "analyze_command.hh"
#endif
#ifndef STRING_HH
#include "string.hh"
#endif
#ifndef TLIST_HH
#include "tList.hh"
#endif

// cAnalyzeFunction    : User-defined function

class cString; // aggregate
template <class T> class tList; // aggregate
class cAnalyzeCommand;

class cAnalyzeFunction {
private:
  cString name;
  tList<cAnalyzeCommand> command_list;
public:
  cAnalyzeFunction(const cString & _name) : name(_name) { ; }
  ~cAnalyzeFunction() { 
    while ( command_list.GetSize() > 0 ) delete command_list.Pop();
  }

  const cString & GetName() { return name; }
  tList<cAnalyzeCommand> * GetCommandList() { return &command_list; }
};

#endif

Index: avida/current/source/main/analyze_genotype.cc
+++ avida/current/source/main/analyze_genotype.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef ANALYZE_GENOTYPE_HH
#include "analyze_genotype.hh"
#endif

#ifndef CONFIG_HH
#include "config.hh"
#endif
#ifndef CPU_TEST_INFO_HH
#include "cpu_test_info.hh"
#endif
#ifndef INST_SET_HH
#include "inst_set.hh"
#endif
#ifndef LANDSCAPE_HH
#include "landscape.hh"
#endif
#ifndef ORGANISM_HH
#include "organism.hh"
#endif
#ifndef PHENOTYPE_HH
#include "phenotype.hh"
#endif
#ifndef TEST_CPU_HH
#include "test_cpu.hh"
#endif

using namespace std;

//////////////////////
//  cAnalyzeGenotype
//////////////////////

cAnalyzeGenotype::cAnalyzeGenotype(cString symbol_string,
				   cInstSet & in_inst_set)
  : genome(symbol_string)
  , inst_set(in_inst_set)
  , name("")
  , aligned_sequence("")
  , tag("")
  , viable(false)
  , id_num(-1)
  , parent_id(-1)
  , num_cpus(0)
  , total_cpus(0)
  , update_born(0)
  , update_dead(0)
  , depth(0)
  , length(0)
  , copy_length(0)
  , exe_length(0)
  , merit(0.0)
  , gest_time(INT_MAX)
  , fitness(0.0)
  , errors(0)
  , task_counts(0)
  , fitness_ratio(0.0)
  , efficiency_ratio(0.0)
  , comp_merit_ratio(0.0)
  , parent_dist(0)
  , ancestor_dist(0)
  , parent_muts("")
  , landscape_stats(NULL)
{
  // Make sure that the sequences jive with the inst_set
  for (int i = 0; i < genome.GetSize(); i++) {
    if (genome[i].GetOp() >= inst_set.GetSize()) {
      cerr << "Error: Trying to load instruction " << genome[i].GetOp()
	   << ".  Max in set is" << inst_set.GetSize() - 1
	   << endl;
    }
  }
}

cAnalyzeGenotype::cAnalyzeGenotype(const cGenome & _genome,
				   cInstSet & in_inst_set)
  : genome(_genome)
  , inst_set(in_inst_set)
  , name("")
  , aligned_sequence("")
  , tag("")
  , viable(false)
  , id_num(-1)
  , parent_id(-1)
  , num_cpus(0)
  , total_cpus(0)
  , update_born(0)
  , update_dead(0)
  , depth(0)
  , length(0)
  , copy_length(0)
  , exe_length(0)
  , merit(0.0)
  , gest_time(INT_MAX)
  , fitness(0.0)
  , errors(0)
  , task_counts(0)
  , fitness_ratio(0.0)
  , efficiency_ratio(0.0)
  , comp_merit_ratio(0.0)
  , parent_dist(0)
  , ancestor_dist(0)
  , parent_muts("")
  , landscape_stats(NULL)
{
}

cAnalyzeGenotype::cAnalyzeGenotype(const cAnalyzeGenotype & _gen)
  : genome(_gen.genome)
  , inst_set(_gen.inst_set)
  , name(_gen.name)
  , aligned_sequence(_gen.aligned_sequence)
  , tag(_gen.tag)
  , viable(_gen.viable)
  , id_num(_gen.id_num)
  , parent_id(_gen.parent_id)
  , num_cpus(_gen.num_cpus)
  , total_cpus(_gen.total_cpus)
  , update_born(_gen.update_born)
  , update_dead(_gen.update_dead)
  , depth(_gen.depth)
  , length(_gen.length)
  , copy_length(_gen.copy_length)
  , exe_length(_gen.exe_length)
  , merit(_gen.merit)
  , gest_time(_gen.gest_time)
  , fitness(_gen.fitness)
  , errors(_gen.errors)
  , task_counts(_gen.task_counts)
  , fitness_ratio(_gen.fitness_ratio)
  , efficiency_ratio(_gen.efficiency_ratio)
  , comp_merit_ratio(_gen.comp_merit_ratio)
  , parent_dist(_gen.parent_dist)
  , ancestor_dist(_gen.ancestor_dist)
  , parent_muts(_gen.parent_muts)
  , landscape_stats(NULL)
{
  if (_gen.landscape_stats != NULL) {
    landscape_stats = new cAnalyzeLandscape;
    *landscape_stats = *(_gen.landscape_stats);
  }
}

cAnalyzeGenotype::~cAnalyzeGenotype()
{
  if (landscape_stats != NULL) delete landscape_stats;
}


int cAnalyzeGenotype::CalcMaxGestation() const
{
  return cConfig::GetTestCPUTimeMod() * genome.GetSize();
}

void cAnalyzeGenotype::CalcLandscape() const
{
  if (landscape_stats != NULL) return;

  landscape_stats = new cAnalyzeLandscape;
  cLandscape landscape(genome, inst_set);
  landscape.Process(1);
  landscape_stats->frac_dead = landscape.GetProbDead();
  landscape_stats->frac_neg  = landscape.GetProbNeg();
  landscape_stats->frac_neut = landscape.GetProbNeut();
  landscape_stats->frac_pos  = landscape.GetProbPos();
}

void cAnalyzeGenotype::Recalculate(cAnalyzeGenotype * parent_genotype)
{
    // Build the test info for printing.
  cCPUTestInfo test_info;
  test_info.TestThreads();
  // test_info.TraceTaskOrder();

  // Use the inst lib for this genotype...
  cInstSet * inst_set_backup = cTestCPU::GetInstSet();
  cTestCPU::SetInstSet(&inst_set);
  cTestCPU::TestGenome(test_info, genome);
  cTestCPU::SetInstSet(inst_set_backup);

  viable = test_info.IsViable();

  cOrganism * test_organism = test_info.GetTestOrganism();
  cPhenotype & test_phenotype = test_organism->GetPhenotype();

  length = test_organism->GetGenome().GetSize();
  copy_length = test_phenotype.GetCopiedSize();
  exe_length = test_phenotype.GetExecutedSize();
  merit = test_phenotype.GetMerit().GetDouble();
  gest_time = test_phenotype.GetGestationTime();
  fitness = test_phenotype.GetFitness();
  errors = test_phenotype.GetLastNumErrors();
  div_type = test_phenotype.GetDivType();
  task_counts = test_phenotype.GetLastTaskCount();

  // Setup a new parent stats if we have a parent to work with.
  if (parent_genotype != NULL) {
    fitness_ratio = GetFitness() / parent_genotype->GetFitness();
    efficiency_ratio = GetEfficiency() / parent_genotype->GetEfficiency();
    comp_merit_ratio = GetCompMerit() / parent_genotype->GetCompMerit();
    parent_dist = cStringUtil::EditDistance(genome.AsString(),
		    parent_genotype->GetGenome().AsString(), parent_muts);
    ancestor_dist = parent_genotype->GetAncestorDist() + parent_dist;
  }
}


void cAnalyzeGenotype::PrintTasks(ofstream & fp, int min_task, int max_task)
{
  if (max_task == -1) max_task = task_counts.GetSize();

  for (int i = min_task; i < max_task; i++) {
    fp << task_counts[i] << " ";
  }
}

void cAnalyzeGenotype::SetSequence(cString _sequence)
{
  cGenome new_genome(_sequence);
  genome = new_genome;
}


double cAnalyzeGenotype::GetFracDead() const
{
  CalcLandscape();  // Make sure the landscape is calculated...
  return landscape_stats->frac_dead;
}

double cAnalyzeGenotype::GetFracNeg() const
{
  CalcLandscape();  // Make sure the landscape is calculated...
  return landscape_stats->frac_neg;
}

double cAnalyzeGenotype::GetFracNeut() const
{
  CalcLandscape();  // Make sure the landscape is calculated...
  return landscape_stats->frac_neut;
}

double cAnalyzeGenotype::GetFracPos() const
{
  CalcLandscape();  // Make sure the landscape is calculated...
  return landscape_stats->frac_pos;
}


cString cAnalyzeGenotype::GetTaskList() const
{
  const int num_tasks = task_counts.GetSize();
  cString out_string(num_tasks);
  
  for (int i = 0; i < num_tasks; i++) {
    const int cur_count = task_counts[i];
    if (cur_count < 10) {
      out_string[i] = '0' + cur_count;
    }
    else if (cur_count < 30) {
      out_string[i] = 'X';
    }
    else if (cur_count < 80) {
      out_string[i] = 'L';
    }
    else if (cur_count < 300) {
      out_string[i] = 'C';
    }
    else if (cur_count < 800) {
      out_string[i] = 'D';
    }
    else if (cur_count < 3000) {
      out_string[i] = 'M';
    }
    else {
      out_string[i] = '+';
    }
  }

  return out_string;
}


cString cAnalyzeGenotype::GetHTMLSequence() const
{
  cString text_genome = genome.AsString();
  cString html_code("<tt>");

  cString diff_info = parent_muts;
  char mut_type = 'N';
  int mut_pos = -1;

  cString cur_mut = diff_info.Pop(',');
  if (cur_mut != "") {
    mut_type = cur_mut[0];
    cur_mut.ClipFront(1); cur_mut.ClipEnd(1);
    mut_pos = cur_mut.AsInt();
  }

  int ins_count = 0;
  for (int i = 0; i < genome.GetSize(); i++) {
    char symbol = text_genome[i];
    if (i != mut_pos) html_code += symbol;
    else {
      // Figure out the information for the type of mutation we had...
      cString color;
      if (mut_type == 'M') {
	color = "#FF0000";	
      } else if (mut_type == 'I') {
	color = "#00FF00";
	ins_count++;
      } else { // if (mut_type == 'D') {
	color = "#0000FF";
	symbol = '*';
	i--;  // Rewind - we didn't read the handle character yet!
      }

      // Move on to the next mutation...
      cur_mut = diff_info.Pop(',');
      if (cur_mut != "") {
	mut_type = cur_mut[0];
	cur_mut.ClipFront(1); cur_mut.ClipEnd(1);
	mut_pos = cur_mut.AsInt();
	if (mut_type == 'D') mut_pos += ins_count;
      } else mut_pos = -1;

      // Tack on the current symbol...
      cString symbol_string;
      symbol_string.Set("<b><font color=\"%s\">%c</font></b>",
			color(), symbol);
      html_code += symbol_string;
    }
  }

  html_code += "</tt>";

  return html_code;
}

Index: avida/current/source/main/analyze_genotype.hh
+++ avida/current/source/main/analyze_genotype.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef ANALYZE_GENOTYPE_HH
#define ANALYZE_GENOTYPE_HH

#ifndef FUNCTIONS_HH
#include "functions.hh"
#endif
#ifndef GENOME_HH
#include "genome.hh"
#endif
#ifndef STRING_HH
#include "string.hh"
#endif
#ifndef STRING_LIST_HH
#include "string_list.hh"
#endif
#ifndef STRING_UTIL_HH
#include "string_util.hh"
#endif
#ifndef TARRAY_HH
#include "tArray.hh"
#endif

// cAnalyzeGenotype    : Collection of information about loaded genotypes

class cGenome; // aggregate
class cInstSet;
class cString; // aggregate
template <class T> class tArray; // aggregate
class cStringList; // aggregate
class cStringUtil; // access

class cAnalyzeGenotype {
private:
  cGenome genome;            // Full Genome
  cInstSet & inst_set;       // Instruction set used in this genome
  cString name;              // Name, if one was provided in loading
  cString aligned_sequence;  // Sequence (in ASCII) after alignment
  cString tag;               // All genotypes in a batch can be tagged

  bool viable;

  // Group 1 : Load-in Stats (Only obtained if available for input file)
  int id_num;
  int parent_id;
  int num_cpus;
  int total_cpus;
  int update_born;
  int update_dead;
  int depth;

  // Group 2 : Basic Execution Stats (Obtained from test CPUs)
  int length;
  int copy_length;
  int exe_length;
  double merit;
  int gest_time;
  double fitness;
  int errors;
  double div_type;

  tArray<int> task_counts;

  // Group 3 : Stats requiring parental genotype (Also from test CPUs)
  double fitness_ratio;
  double efficiency_ratio;
  double comp_merit_ratio;
  int parent_dist;
  int ancestor_dist;
  cString parent_muts;

  // Group 4 : Landscape stats (obtained from testing all possible mutations)
  class cAnalyzeLandscape {
  public:
    double frac_dead;
    double frac_neg;
    double frac_neut;
    double frac_pos;
    cAnalyzeLandscape() : frac_dead(0.0), frac_neg(0.0),
			  frac_neut(0.0), frac_pos(0.0) { ; }
  };
  mutable cAnalyzeLandscape * landscape_stats;

  // Group 5 : More complex stats (obtained indvidually, through tests)
  cString task_order;

  cStringList special_args; // These are args placed after a ':' in details...

  int NumCompare(double new_val, double old_val) const {
    if (new_val == old_val) return  0;
    else if (new_val == 0)       return -2;
    else if (old_val == 0)       return +2;
    else if (new_val < old_val)  return -1;
    // else if (new_val > old_val)
    return +1;
  }

  int CalcMaxGestation() const;
  void CalcLandscape() const;
public:
  cAnalyzeGenotype(cString symbol_string, cInstSet & in_inst_set);
  cAnalyzeGenotype(const cGenome & _genome, cInstSet & in_inst_set);
  cAnalyzeGenotype(const cAnalyzeGenotype & _gen);
  ~cAnalyzeGenotype();

  const cStringList & GetSpecialArgs() { return special_args; }
  void SetSpecialArgs(const cStringList & _args) { special_args = _args; }

  void Recalculate(cAnalyzeGenotype * parent_genotype=NULL);
  void PrintTasks(std::ofstream & fp, int min_task=0, int max_task=-1);

  // Set...
  void SetSequence(cString _sequence);
  
  void SetName(const cString & _name) { name = _name; }
  void SetAlignedSequence(const cString & _seq) { aligned_sequence = _seq; }
  void SetTag(const cString & _tag) { tag = _tag; }

  void SetViable(bool _viable) { viable = _viable; }

  void SetID(int _id) { id_num = _id; }
  void SetParentID(int _id) { parent_id = _id; }
  void SetNumCPUs(int _cpus) { num_cpus = _cpus; }
  void SetTotalCPUs(int _cpus) { total_cpus = _cpus; }
  void SetUpdateBorn(int _born) { update_born = _born; }
  void SetUpdateDead(int _dead) { update_dead = _dead; }
  void SetDepth(int _depth) { depth = _depth; }

  void SetLength(int _length) { length = _length; }
  void SetCopyLength(int _length) { copy_length = _length; }
  void SetExeLength(int _length) { exe_length = _length; }
  void SetMerit(double _merit) { merit = _merit; }
  void SetGestTime(int _gest) { gest_time = _gest; }
  void SetFitness(double _fitness) { fitness = _fitness; }
  void SetDivType(double _div_type) { div_type = _div_type; }
  void SetParentDist(int _dist) { parent_dist = _dist; }
  void SetAncestorDist(int _dist) { ancestor_dist = _dist; }

  void SetParentMuts(const cString & in_muts) { parent_muts = in_muts; }
  void SetTaskOrder(const cString & in_order) { task_order = in_order; }

//    void SetFracDead(double in_frac);
//    void SetFracNeg(double in_frac);
//    void SetFracNeut(double in_frac);
//    void SetFracPos(double in_frac);

  // Accessors...
  const cGenome & GetGenome() const { return genome; }
  const cString & GetName() const { return name; }
  const cString & GetAlignedSequence() const { return aligned_sequence; }
  const cString & GetTag() const { return tag; }

  bool GetViable() const { return viable; }

  int GetID() const { return id_num; }
  int GetParentID() const { return parent_id; }
  int GetParentDist() const { return parent_dist; }
  int GetAncestorDist() const { return ancestor_dist; }
  int GetNumCPUs() const { return num_cpus; }
  int GetTotalCPUs() const { return total_cpus; }
  int GetLength() const { return length; }
  int GetCopyLength() const { return copy_length; }
  int GetExeLength() const { return exe_length; }
  int GetMinLength() const { return Min(exe_length, copy_length); }
  double GetMerit() const { return merit; }
  double GetCompMerit() const { return merit / (double) GetMinLength(); }
  int GetGestTime() const { return gest_time; }
  double GetEfficiency() const
    { return ((double) GetMinLength()) / (double) gest_time; }
  double GetFitness() const { return fitness; }
  double GetDivType() const { return div_type; }
  int GetUpdateBorn() const { return update_born; }
  int GetUpdateDead() const { return update_dead; }
  int GetDepth() const { return depth; }

  const cString & GetParentMuts() const { return parent_muts; }

  double GetFracDead() const;
  double GetFracNeg() const;
  double GetFracNeut() const;
  double GetFracPos() const;

  double GetFitnessRatio() const { return fitness_ratio; }
  double GetEfficiencyRatio() const { return efficiency_ratio; }
  double GetCompMeritRatio() const { return comp_merit_ratio; }

  const cString & GetTaskOrder() const { return task_order; }
  cString GetTaskList() const;

  cString GetSequence() const { return genome.AsString(); }
  cString GetHTMLSequence() const;

  cString GetMapLink() const {
    return cStringUtil::Stringf("<a href=\"tasksites.%s.html\">Phenotype Map</a>", GetName()());
  }

  int GetNumTasks() const { return task_counts.GetSize(); }
  int GetTaskCount(int task_id) const {
    if (task_id >= task_counts.GetSize()) return 0;
    if (special_args.HasString("binary")) return (task_counts[task_id] > 0);
    return task_counts[task_id];
  }

  // Comparisons...  Compares a genotype to the "previous" one, which is
  // passed in, in one specified phenotype.
  // Return values are:
  //   -2 : Toggle; no longer has phenotype it used to...
  //   -1 : Reduction in strength of phenotype
  //    0 : Identical in phenotype
  //   +1 : Improvement in phenotype
  //   +2 : Toggle; phenotype now present that wasn't.
  int CompareNULL(cAnalyzeGenotype * prev) const { (void) prev; return 0; }
  int CompareArgNULL(cAnalyzeGenotype * prev, int i) const
    { (void) prev; (void) i;  return 0; }
  int CompareLength(cAnalyzeGenotype * prev) const {
    if (GetLength() < MIN_CREATURE_SIZE &&
	prev->GetLength() > MIN_CREATURE_SIZE) return -2;
    if (GetLength() > MIN_CREATURE_SIZE &&
	prev->GetLength() < MIN_CREATURE_SIZE) return 2;
    return 0;
  }
  int CompareMerit(cAnalyzeGenotype * prev) const
    { return NumCompare(GetMerit(), prev->GetMerit()); }
  int CompareCompMerit(cAnalyzeGenotype * prev) const
    { return NumCompare(GetCompMerit(), prev->GetCompMerit()); }
  int CompareGestTime(cAnalyzeGenotype * prev) const {
    const int max_time = CalcMaxGestation();
    const int cur_time = max_time - GetGestTime();
    const int prev_time = max_time - prev->GetGestTime();
    return NumCompare(cur_time, prev_time);
  }
  int CompareEfficiency(cAnalyzeGenotype * prev) const
    { return NumCompare(GetEfficiency(), prev->GetEfficiency()); }
  int CompareFitness(cAnalyzeGenotype * prev) const
    { return NumCompare(GetFitness(), prev->GetFitness()); }
  int CompareTaskCount(cAnalyzeGenotype * prev, int task_id) const
    { return NumCompare(GetTaskCount(task_id), prev->GetTaskCount(task_id)); }
};

#endif

Index: avida/current/source/main/avida_driver_analyze.cc
+++ avida/current/source/main/avida_driver_analyze.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef AVIDA_DRIVER_ANALYZE_HH
#include "avida_driver_analyze.hh"
#endif

#ifndef ANALYZE_HH
#include "analyze.hh"
#endif
#ifndef CONFIG_HH
#include "config.hh"
#endif

#include <iostream>

using namespace std;

//////////////////////////
//  cAvidaDriver_Analyze
//////////////////////////

cAvidaDriver_Analyze::cAvidaDriver_Analyze()
{
}

cAvidaDriver_Analyze::~cAvidaDriver_Analyze()
{
}

void cAvidaDriver_Analyze::Run()
{
  cout << "In analyze mode!!" << endl;
  cAnalyze analyze(cConfig::GetAnalyzeFilename());
}

Index: avida/current/source/main/avida_driver_analyze.hh
+++ avida/current/source/main/avida_driver_analyze.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef AVIDA_DRIVER_ANALYZE_HH
#define AVIDA_DRIVER_ANALYZE_HH

#ifndef AVIDA_DRIVER_BASE_HH
#include "avida_driver_base.hh"
#endif

class cAvidaDriver_Analyze : public cAvidaDriver_Base {
protected:
public:
  cAvidaDriver_Analyze();
  virtual ~cAvidaDriver_Analyze();
  virtual void Run();
};

#endif

Index: avida/current/source/main/avida_driver_base.cc
+++ avida/current/source/main/avida_driver_base.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef AVIDA_DRIVER_BASE_HH
#include "avida_driver_base.hh"
#endif

#ifndef STRING_HH
#include "string.hh"
#endif

#include <iostream>

using namespace std;


// Static variable definitions
cAvidaDriver_Base * cAvidaDriver_Base::main_driver = NULL;

///////////////////////
//  cAvidaDriver_Base
///////////////////////

cAvidaDriver_Base::cAvidaDriver_Base()
  : done_flag(false)
{
}

cAvidaDriver_Base::~cAvidaDriver_Base()
{
}

void cAvidaDriver_Base::ExitProgram(int exit_code)
{
  exit(exit_code);   // If nothing is setup, nothing needs to be shutdown.
}

void cAvidaDriver_Base::NotifyComment(const cString & in_string)
{
  cout << in_string << endl;  // Just output
}

void cAvidaDriver_Base::NotifyWarning(const cString & in_string)
{
  cerr << in_string << endl;  // Just output
}

void cAvidaDriver_Base::NotifyError(const cString & in_string)
{
  cerr << in_string << endl;  // Just output
}

Index: avida/current/source/main/avida_driver_base.hh
+++ avida/current/source/main/avida_driver_base.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef AVIDA_DRIVER_BASE_HH
#define AVIDA_DRIVER_BASE_HH

/**
 *  cAvidaDriver_Base
 *
 *  This class is the base class for driving an avida run (be it in analyze
 *  mode or as a population).  It includes all of the functions that should
 *  be overloaded to make any viewer work.
 **/

class cString;
class cAvidaDriver_Base {
protected:
  bool done_flag;   // This is set to true when run should finish.

public:
  static cAvidaDriver_Base * main_driver;

  cAvidaDriver_Base();
  virtual ~cAvidaDriver_Base();

  virtual void Run() = 0;  // Called when Driver should take over execution.
  virtual void ExitProgram(int exit_code);  // Called on an interupt,

  // There functions are ideally called by avida whenever a message needs to
  // be sent to the user.
  virtual void NotifyComment(const cString & in_string);
  virtual void NotifyWarning(const cString & in_string);
  virtual void NotifyError(const cString & in_string);

  // Called when the driver should stop what its doing for the moment, to
  // let the user see what just happened.
  virtual void SignalBreakpoint() { ; }

  void SetDone() { done_flag = true; }
};

#endif

Index: avida/current/source/main/avida_driver_population.cc
+++ avida/current/source/main/avida_driver_population.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef AVIDA_DRIVER_POPULATION_HH
#include "avida_driver_population.hh"
#endif

#ifndef AVIDA_TRIGGERS_HH
#include "avida_triggers.hh"
#endif
#ifndef CALLBACK_UTIL_HH
#include "callback_util.hh"
#endif
#ifndef CONFIG_HH
#include "config.hh"
#endif
#ifndef EVENT_FACTORY_MANAGER_HH
#include "event_factory_manager.hh"
#endif
#ifndef EVENT_LIST_HH
#include "event_list.hh"
#endif
#ifndef GENEBANK_HH
#include "genebank.hh"
#endif
#ifndef GENOTYPE_HH
#include "genotype.hh"
#endif
#ifndef HARDWARE_BASE_HH
#include "hardware_base.hh"
#endif
#ifndef HARDWARE_FACTORY_HH
#include "hardware_factory.hh"
#endif
#ifndef INIT_FILE_HH
#include "init_file.hh"
#endif
#ifndef ORGANISM_HH
#include "organism.hh"
#endif
#ifndef POPULATION_HH
#include "population.hh"
#endif
#ifndef POPULATION_CELL_HH
#include "population_cell.hh"
#endif
#ifndef POPULATION_EVENT_FACTORY_HH
#include "population_event_factory.hh"
#endif
#ifndef POPULATION_INTERFACE_HH
#include "population_interface.hh"
#endif
#ifndef STRING_HH
#include "string.hh"
#endif
#ifndef TOOLS_HH
#include "tools.hh"
#endif

#include <iostream>

using namespace std;

/////////////////////////////
//  cAvidaDriver_Population
/////////////////////////////

cAvidaDriver_Population::cAvidaDriver_Population(cEnvironment & environment)
  : population(NULL)
  , event_manager(NULL)
  , event_list(NULL)
{
  // Setup Population
  cout << "Initializing Population..." << flush;
  cPopulationInterface default_interface;
  default_interface.SetFun_NewHardware(&cCallbackUtil::CB_NewHardware);
  default_interface.SetFun_Recycle(&cCallbackUtil::CB_RecycleHardware);
  default_interface.SetFun_Divide(&cCallbackUtil::CB_Divide);
  default_interface.SetFun_TestOnDivide(&cCallbackUtil::CB_TestOnDivide);
  default_interface.SetFun_GetNeighbor(&cCallbackUtil::CB_GetNeighbor);
  default_interface.SetFun_NumNeighbors(&cCallbackUtil::CB_GetNumNeighbors);
  default_interface.SetFun_Rotate(&cCallbackUtil::CB_Rotate);
  default_interface.SetFun_Breakpoint(&cCallbackUtil::CB_Breakpoint);
  default_interface.SetFun_TestFitness(&cCallbackUtil::CB_TestFitness);
  default_interface.SetFun_GetInput(&cCallbackUtil::CB_GetInput);
  default_interface.SetFun_GetInputAt(&cCallbackUtil::CB_GetInputAt);
  default_interface.SetFun_Debug(&cCallbackUtil::CB_Debug);
  default_interface.SetFun_GetResources(&cCallbackUtil::CB_GetResources);
  default_interface.SetFun_UpdateResources(&cCallbackUtil::CB_UpdateResources);
  default_interface.SetFun_KillCell(&cCallbackUtil::CB_KillCell);
  default_interface.SetFun_KillSurroundCell(&cCallbackUtil::CB_KillSurroundCell);
  default_interface.SetFun_SendMessage(&cCallbackUtil::CB_SendMessage);
  default_interface.SetFun_InjectParasite(&cCallbackUtil::CB_InjectParasite);

  population = new cPopulation(default_interface, environment);
  cout << " ...done" << endl;

  //Setup Event List
  cout<<"Initializing Event Factory Manager..."<<flush;
  event_manager = new cEventFactoryManager;
  cStats & stats = population->GetStats();
  event_list = new cEventList( event_manager, new cAvidaTriggers(stats) );
  cout<<"...Factories..."<<flush;

  // in principle, one could add more than one event factory here.
  // however, this is not a good idea, because the automatic documentation
  // system cannot cope with this at this point. Claus
  event_manager->AddFactory(new cPopulationEventFactory(population));
  cout<<" ...done"<<endl;

  cout<<"Reading Event List File..."<<flush;
  ReadEventListFile(cConfig::GetEventFilename());
  cout<<" ...done"<<endl;

  // Make sure the directory 'genebank' exits!
  cTools::MkDir("genebank", true);
}

cAvidaDriver_Population::~cAvidaDriver_Population()
{
  if (population != NULL) delete population;
}

void cAvidaDriver_Population::Run()
{
  // cout << "DEBUG: Turning control over to driver..." << endl;

  assert( population != NULL );

  // Process until done...
  while ( !ProcessUpdate() ) {} 
}

bool cAvidaDriver_Population::ProcessUpdate()
{
  GetEvents();
  if (done_flag == true) return true;

  // Increment the Update.
  cStats & stats = population->GetStats();
  stats.IncCurrentUpdate();

  // Handle all data collection for previous update.
  if (stats.GetUpdate() > 0) {
    // Tell the stats object to do update calculations and printing.
    stats.ProcessUpdate();

    // Update all the genotypes for the end of this update.
    cGenebank & genebank = population->GetGenebank();
    for (cGenotype * cur_genotype = genebank.ResetThread(0);
	 cur_genotype != NULL && cur_genotype->GetThreshold();
	 cur_genotype = genebank.NextGenotype(0)) {
      cur_genotype->UpdateReset();
    }
  }

  ProcessOrganisms();

  // Do Point Mutations
  if (cConfig::GetPointMutProb() > 0 ) {
    for (int i = 0; i < population->GetSize(); i++) {
      if (population->GetCell(i).IsOccupied()) {
	population->GetCell(i).GetOrganism()->
	  GetHardware().PointMutate(cConfig::GetPointMutProb());
      }
    }
  }
  

#ifdef DEBUG_CHECK_OK
  // If we're in a debug mode, make sure the population is OK.
  if (population->OK() == false) {
    g_debug.Warning("Population::OK() is failing.");
  }
#endif

  // Do any cleanup in the hardware factory...
  cHardwareFactory::Update();
  
  // Exit conditons...
  if (population->GetNumOrganisms() == 0) done_flag = true;
  
  return done_flag;
}


void cAvidaDriver_Population::NotifyUpdate()
{
  // Nothing here for now.  This method should be overloaded and only
  // run if there is no proper viewer.
}


void cAvidaDriver_Population::GetEvents()
{
  assert(population != NULL);

  if (population->GetSyncEvents() == true) {
    SyncEventList();
    population->SetSyncEvents(false);
  }
  event_list->Process();
}

void cAvidaDriver_Population::ProcessOrganisms()
{
  //  cout << "DEBUG: Running viewer-less update..." << endl;

  // Process the update.
  const int UD_size =
    cConfig::GetAveTimeslice() * population->GetNumOrganisms();
  const double step_size = 1.0 / (double) UD_size;

  for (int i = 0; i < UD_size; i++) {
    if (population->GetNumOrganisms() == 0) {
      done_flag = true;
      break;
    }
    population->ProcessStep(step_size);
  }

  // end of update stats...
  population->CalcUpdateStats();

  // No viewer; print out status for this update....
  cStats & stats = population->GetStats();
  cout << "UD: "  << stats.GetUpdate() << "\t"
       << "Gen: " << stats.SumGeneration().Average() << "\t"
       << "Fit: " << stats.GetAveFitness() << "\t"
       << "Size: " << population->GetNumOrganisms()
       << endl;
}


void cAvidaDriver_Population::
ReadEventListFile(const cString & filename)
{
  cInitFile event_file(filename);

  // Load in the proper event list and set it up.
  event_file.Load();
  event_file.Compress();

  // Loop through the line_list and change the lines to events.
  for (int line_id = 0; line_id < event_file.GetNumLines(); line_id++) {
    event_list->AddEventFileFormat(event_file.GetLine(line_id));
  }

  ////////// Adding events from the Genesis file //////////
  // Max Updates and/or Max Generations
  if( cConfig::GetEndConditionMode() == 0 ){
    if( cConfig::GetMaxUpdates() >= 0 ){
      event_list->AddEvent( cEventTriggers::UPDATE, cConfig::GetMaxUpdates(),
			    cEventTriggers::TRIGGER_ONCE,
			    cEventTriggers::TRIGGER_END, "exit", "");
    }
    if( cConfig::GetMaxGenerations() >= 0 ){
      event_list->AddEvent( cEventTriggers::GENERATION,
			    cConfig::GetMaxGenerations(),
			    cEventTriggers::TRIGGER_ONCE,
			    cEventTriggers::TRIGGER_END, "exit", "");
    }
  }else{
    if( cConfig::GetMaxUpdates() >= 0 && cConfig::GetMaxGenerations() >= 0 ){
      cString max_gen_str;
      max_gen_str.Set("%d",cConfig::GetMaxGenerations());
      cString max_update_str;
      max_update_str.Set("%d",cConfig::GetMaxUpdates());
      event_list->AddEvent( cEventTriggers::UPDATE, cConfig::GetMaxUpdates(),
			    1, cEventTriggers::TRIGGER_END,
			    "exit_if_generation_greater_than", max_gen_str);
      event_list->AddEvent( cEventTriggers::GENERATION,
			    cConfig::GetMaxGenerations(),
			    .01, cEventTriggers::TRIGGER_END,
			    "exit_if_update_greater_than", max_update_str);
    }
  }

}

void cAvidaDriver_Population::SyncEventList()
{
  if( event_list != NULL ){
    event_list->Sync();
  }
}

Index: avida/current/source/main/avida_driver_population.hh
+++ avida/current/source/main/avida_driver_population.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef AVIDA_DRIVER_POPULATION_HH
#define AVIDA_DRIVER_POPULATION_HH

#ifndef AVIDA_DRIVER_BASE_HH
#include "avida_driver_base.hh"
#endif
#ifndef STRING_HH
#include "string.hh"
#endif

class cEnvironment;
class cEventFactoryManager;
class cEventList;
class cString;
class cPopulation;

class cAvidaDriver_Population : public cAvidaDriver_Base {
protected:
  cPopulation * population;
  cEventFactoryManager * event_manager;
  cEventList * event_list;

  void GetEvents();
  /**
   * Processes one complete update.
   *
   * Returns true when finished.
   **/
  virtual bool ProcessUpdate();
  virtual void ProcessOrganisms();
  void ReadEventListFile(const cString & filename="event_list");
  void SyncEventList();
			
public:
  cAvidaDriver_Population(cEnvironment & environment);
  virtual ~cAvidaDriver_Population();

  virtual void Run();
  virtual void NotifyUpdate();
};

#endif

Index: avida/current/source/main/avida_triggers.hh
+++ avida/current/source/main/avida_triggers.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef AVIDA_TRIGGERS_HH
#define AVIDA_TRIGGERS_HH

#ifndef EVENT_TRIGGERS_HH
#include "event_triggers.hh"
#endif
#ifndef STATS_HH
#include "stats.hh"
#endif

/**
 * A small class that determines the correct triggers for the event list.
 * Needed in order to separate the event business from the rest.
 */
class cAvidaTriggers : public cEventTriggers {
private:
  cStats & stats;
public:
  cAvidaTriggers(cStats & _stats) : stats(_stats) { ; }
  double GetUpdate() const { return (double) stats.GetUpdate(); }
  double GetGeneration() const { return stats.SumGeneration().Average(); }
};

#endif

Index: avida/current/source/main/genotype_batch.hh
+++ avida/current/source/main/genotype_batch.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef GENOTYPE_BATCH_HH
#define GENOTYPE_BATCH_HH

#ifndef STRING_HH
#include "string.hh"
#endif
#ifndef TLIST_HH
#include "tList.hh"
#endif

// cGenotypeBatch      : Collection of cAnalyzeGenotypes

template <class T> class tList; // aggregate
class cString; // aggregate
class cAnalyzeGenotype;

class cGenotypeBatch {
private:
  tList<cAnalyzeGenotype> genotype_list;
  cString name;
  bool is_lineage;
  bool is_aligned;
public:
  cGenotypeBatch() : name(""), is_lineage(false), is_aligned(false) { ; }
  ~cGenotypeBatch() { ; }

  tList<cAnalyzeGenotype> & List() { return genotype_list; }
  cString & Name() { return name; }
  bool IsLineage() { return is_lineage; }
  bool IsAligned() { return is_aligned; }

  void SetLineage(bool _val=true) { is_lineage = _val; }
  void SetAligned(bool _val=true) { is_aligned = _val; }

};

#endif

Index: avida/current/source/main/genotype_birth_data.cc
+++ avida/current/source/main/genotype_birth_data.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef GENOTYPE_BIRTH_DATA_HH
#include "genotype_birth_data.hh"
#endif

#ifndef DEFS_HH
#include "defs.hh"
#endif

/////////////////////////
//  cGenotype_BirthData
/////////////////////////

cGenotype_BirthData::cGenotype_BirthData(int in_update_born)
  : update_born(in_update_born)
  , parent_id(-1)
  , parent_distance(-1)
  , gene_depth(0)
  , update_deactivated(-1)
  , parent_genotype(NULL)
  , parent_species(NULL)
  , num_offspring_genotypes(0)
{
}

cGenotype_BirthData::~cGenotype_BirthData()
{
}

Index: avida/current/source/main/genotype_birth_data.hh
+++ avida/current/source/main/genotype_birth_data.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef GENOTYPE_BIRTH_DATA_HH
#define GENOTYPE_BIRTH_DATA_HH

#ifndef COUNT_TRACKER_HH
#include "count_tracker.hh"
#endif

class cGenotype;
class cSpecies;
class cGenotype_BirthData {
public:
  cGenotype_BirthData(int in_update_born);
  ~cGenotype_BirthData();

  cCountTracker birth_track;
  cCountTracker death_track;
  cCountTracker breed_in_track;
  cCountTracker breed_true_track;
  cCountTracker breed_out_track;

  int update_born;      // Update genotype was first created
  int parent_id;        // ID of parent genotype
  int parent_distance;  // Genetic distance from parent genotype
  int gene_depth;       // depth in the phylogenetic tree from ancestor

  int update_deactivated;      // If not, when did it get deactivated?
  cGenotype * parent_genotype; // Pointer to parent genotype...
  cSpecies * parent_species;
  int num_offspring_genotypes; // Num offspring genotypes still in memory.
};

#endif

Index: avida/current/source/main/genotype_control.cc
+++ avida/current/source/main/genotype_control.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef GENOTYPE_CONTROL_HH
#include "genotype_control.hh"
#endif

#ifndef DEFS_HH
#include "defs.hh"
#endif
#ifndef GENEBANK_HH
#include "genebank.hh"
#endif
#ifndef GENOTYPE_HH
#include "genotype.hh"
#endif

///////////////////////
//  cGenotypeControl
///////////////////////

cGenotypeControl::cGenotypeControl(cGenebank & in_gb) : genebank(in_gb)
{
  size = 0;
  best = NULL;
  coalescent = NULL;
  for (int i = 0; i < GENOTYPE_THREADS; i++) threads[i] = NULL;

  historic_list = NULL;
  historic_count = 0;
}

cGenotypeControl::~cGenotypeControl()
{
}

bool cGenotypeControl::OK()
{
  int ret_value = true;

  // Cycle through the list, making sure all connections are proper, size
  // is correct, and all genotypes are OK().

  cGenotype * cur_pos = best;
  for (int i = 0; i < size; i++) {
    if (!cur_pos->OK()) ret_value = false;
    assert (cur_pos->GetNext()->GetPrev() == cur_pos);
    cur_pos = cur_pos->GetNext();
  }

  assert (cur_pos == best);

  return ret_value;
}

void cGenotypeControl::Insert(cGenotype & in_genotype, cGenotype * prev_genotype)
{
  if (prev_genotype == NULL) {
    assert(size == 0); // Destroying a full genotype queue...

    best = &in_genotype;
    best->SetNext(best);
    best->SetPrev(best);
  }
  else {
    in_genotype.SetPrev(prev_genotype);
    in_genotype.SetNext(prev_genotype->GetNext());
    prev_genotype->SetNext(&in_genotype);
    in_genotype.GetNext()->SetPrev(&in_genotype);
  }

  size++;
}

void cGenotypeControl::Remove(cGenotype & in_genotype)
{
  if (size == 1) {
    best = NULL;
  }
  if (&in_genotype == best) {
    best = best->GetNext();
  }

  in_genotype.GetNext()->SetPrev(in_genotype.GetPrev());
  in_genotype.GetPrev()->SetNext(in_genotype.GetNext());
  in_genotype.SetNext(NULL);
  in_genotype.SetPrev(NULL);

  size--;
}

void cGenotypeControl::RemoveHistoric(cGenotype & in_genotype)
{
  if (historic_count == 1) {
    historic_list = NULL;
  }
  if (&in_genotype == historic_list) {
    historic_list = historic_list->GetNext();
  }

  in_genotype.GetNext()->SetPrev(in_genotype.GetPrev());
  in_genotype.GetPrev()->SetNext(in_genotype.GetNext());
  in_genotype.SetNext(NULL);
  in_genotype.SetPrev(NULL);

  historic_count--;
}

void cGenotypeControl::InsertHistoric(cGenotype & in_genotype)
{
  if (historic_count == 0) {
    in_genotype.SetNext(&in_genotype);
    in_genotype.SetPrev(&in_genotype);
  }
  else {
    in_genotype.SetPrev(historic_list->GetPrev());
    in_genotype.SetNext(historic_list);
    historic_list->GetPrev()->SetNext(&in_genotype);
    historic_list->SetPrev(&in_genotype);
  }

  historic_list = &in_genotype;
  historic_count++;
}


int cGenotypeControl::UpdateCoalescent()
{
  // Test to see if any updating needs to be done...
  // Don't update active coalescent genotype, or if there is more than
  // one offspring.
  if (coalescent != NULL &&
      (coalescent->GetNumOrganisms() > 0 ||
       coalescent->GetNumOffspringGenotypes() > 1)) {
    return coalescent->GetDepth();
  }

  // If there is no best, there is nothing to search through...
  if (best == NULL) return -1;

  // Find the new point...
  cGenotype * test_gen = best;
  cGenotype * found_gen = best;
  cGenotype * parent_gen = best->GetParentGenotype();

  while (parent_gen != NULL) {
    // See if this genotype should be the new found genotype...
    if (test_gen->GetNumOrganisms() > 0 ||
	test_gen->GetNumOffspringGenotypes() > 1) {
      found_gen = test_gen;
    }

    // Move to the next genotype...
    test_gen = parent_gen;
    parent_gen = test_gen->GetParentGenotype();
  }

  coalescent = found_gen;

  return coalescent->GetDepth();
}


bool cGenotypeControl::CheckPos(cGenotype & in_genotype)
{
  int next_OK = false;
  int prev_OK = false;

  if (in_genotype.GetNumOrganisms() >= in_genotype.GetNext()->GetNumOrganisms()) {
    next_OK =true;
  }
  if (in_genotype.GetNumOrganisms() <= in_genotype.GetPrev()->GetNumOrganisms()) {
    prev_OK =true;
  }

  if ((&in_genotype == best && next_OK) ||
      (next_OK && prev_OK) ||
      (&in_genotype == best->GetPrev() && prev_OK)) {
    return true;
  }

  return false;
}

void cGenotypeControl::Insert(cGenotype & new_genotype)
{
  // If there is nothing in the list, add this.

  if (size == 0) {
    Insert(new_genotype, NULL);
  }

  // Otherwise tack it on the end.

  else {
    Insert(new_genotype, best->GetPrev());
  }
}

bool cGenotypeControl::Adjust(cGenotype & in_genotype)
{
  if (in_genotype.GetDeferAdjust() == true) return true;

  cGenotype * cur_genotype = in_genotype.GetPrev();

  // Check to see if this genotype should be removed completely.

  if (in_genotype.GetNumOrganisms() == 0) {
    genebank.RemoveGenotype(in_genotype);
    return false;
  }

  // Do not adjust if this was and still is the best genotype, or is
  // otherwise in the proper spot...

  if (CheckPos(in_genotype)) {
    return true;
  }

  // Otherwise, remove it from the queue for just the moment.

  Remove(in_genotype);

  // Also, if this genotype is the best, put it there.

  if (in_genotype.GetNumOrganisms() > best->GetNumOrganisms()) {
    Insert(in_genotype, best->GetPrev());
    best = &in_genotype;
    return true;
  }

  // Finally, find out where this genotype *does* go.

  while (cur_genotype->GetNumOrganisms() >= in_genotype.GetNumOrganisms() &&
	 cur_genotype != best->GetPrev()) {
    cur_genotype = cur_genotype->GetNext();
  }
  while (cur_genotype->GetNumOrganisms() < in_genotype.GetNumOrganisms() &&
	 cur_genotype != best) {
    cur_genotype = cur_genotype->GetPrev();
  }

  Insert(in_genotype, cur_genotype);

  return true;
}


cGenotype * cGenotypeControl::Find(const cGenome & in_genome) const
{
  int i;
  cGenotype * cur_genotype = best;

  for (i = 0; i < size; i++) {
    if (in_genome == cur_genotype->GetGenome()) {
      return cur_genotype;
    }
    cur_genotype = cur_genotype->GetNext();
  }

  return NULL;
}

int cGenotypeControl::FindPos(cGenotype & in_genotype, int max_depth)
{
  cGenotype * temp_genotype = best;
  if (max_depth < 0 || max_depth > size) max_depth = size;

  for (int i = 0; i < max_depth; i++) {
    if (temp_genotype == &in_genotype) return i;
    temp_genotype = temp_genotype->GetNext();
  }

  return -1;
}

cGenotype * cGenotypeControl::Next(int thread)
{
  return threads[thread] = threads[thread]->GetNext();
}

cGenotype * cGenotypeControl::Prev(int thread)
{
  return threads[thread] = threads[thread]->GetPrev();
}

Index: avida/current/source/main/genotype_control.hh
+++ avida/current/source/main/genotype_control.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef GENOTYPE_CONTROL_HH
#define GENOTYPE_CONTROL_HH

#ifndef GENOTYPE_MACROS_HH
#include "genotype_macros.hh"
#endif

class cGenebank;
class cGenome;
class cGenotype;
class cGenotypeControl {
private:
  int size;
  cGenotype * best;
  cGenotype * coalescent;
  cGenotype * threads[GENOTYPE_THREADS];
  cGenebank & genebank;

  cGenotype * historic_list;
  int historic_count;

  void Insert(cGenotype & in_genotype, cGenotype * prev_genotype);
  bool CheckPos(cGenotype & in_genotype);
public:
  cGenotypeControl(cGenebank & in_gb);
  ~cGenotypeControl();

  bool OK();
  void Remove(cGenotype & in_genotype);
  void Insert(cGenotype & new_genotype);
  bool Adjust(cGenotype & in_genotype);

  void RemoveHistoric(cGenotype & in_genotype);
  void InsertHistoric(cGenotype & in_genotype);
  int GetHistoricCount() { return historic_count; }

  int UpdateCoalescent();

  inline int GetSize() const { return size; }
  inline cGenotype * GetBest() const { return best; }
  inline cGenotype * GetCoalescent() const { return coalescent; }

  cGenotype * Find(const cGenome & in_genome) const;
  int FindPos(cGenotype & in_genotype, int max_depth = -1);

  inline cGenotype * Get(int thread) const { return threads[thread]; }
  inline cGenotype * Reset(int thread)
    { return threads[thread] = best; }
  inline cGenotype * ResetHistoric(int thread)
    { return threads[thread] = historic_list; }
  cGenotype * Next(int thread);
  cGenotype * Prev(int thread);
};

#endif

Index: avida/current/source/main/genotype_macros.hh
+++ avida/current/source/main/genotype_macros.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef GENOTYPE_MACROS_HH
#define GENOTYPE_MACROS_HH

#define GENOTYPE_HASH_SIZE 3203    // @CAO Is this an optimal number?
#define SPECIES_HASH_SIZE 101
#define GENOTYPE_THREADS 2

#define SPECIES_RECORD_OFF     0
#define SPECIES_RECORD_FULL    1
#define SPECIES_RECORD_LIMITED 2

#endif

Index: avida/current/source/main/genotype_test_data.cc
+++ avida/current/source/main/genotype_test_data.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef GENOTYPE_TEST_DATA_HH
#include "genotype_test_data.hh"
#endif

////////////////////////
//  cGenotype_TestData
////////////////////////

cGenotype_TestData::cGenotype_TestData()
  : fitness(-1)
{
}

cGenotype_TestData::~cGenotype_TestData()
{
}

Index: avida/current/source/main/genotype_test_data.hh
+++ avida/current/source/main/genotype_test_data.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef GENOTYPE_TEST_DATA_HH
#define GENOTYPE_TEST_DATA_HH

class cGenotype_TestData {
public:
  cGenotype_TestData();
  ~cGenotype_TestData();

  bool is_viable;

  double fitness;
  double merit;
  int gestation_time;
  int executed_size;
  int copied_size;
  double colony_fitness;
  int generations;
};

#endif

Index: avida/current/source/main/inject_genebank_macros.hh
+++ avida/current/source/main/inject_genebank_macros.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef INJECT_GENEBANK_MACROS_HH
#define INJECT_GENEBANK_MACROS_HH

#define INJECTGENOTYPE_HASH_SIZE 307    // @CAO Is this an optimal number?
#define SPECIES_HASH_SIZE 101
#define INJECTGENOTYPE_THREADS 2

#define SPECIES_RECORD_OFF     0
#define SPECIES_RECORD_FULL    1
#define SPECIES_RECORD_LIMITED 2

#endif

Index: avida/current/source/main/inject_genotype_birth_data.cc
+++ avida/current/source/main/inject_genotype_birth_data.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef INJECT_GENOTYPE_BIRTH_DATA_HH
#include "inject_genotype_birth_data.hh"
#endif

#ifndef DEFS_HH
#include "defs.hh"
#endif

/////////////////////////
//  cInjectGenotype_BirthData
/////////////////////////

cInjectGenotype_BirthData::cInjectGenotype_BirthData(int in_update_born)
  : update_born(in_update_born)
  , parent_id(-1)
  , gene_depth(0)
  , update_deactivated(-1)
  , parent_genotype(NULL)
  , num_offspring_genotypes(0)
{
}

cInjectGenotype_BirthData::~cInjectGenotype_BirthData()
{
}

Index: avida/current/source/main/inject_genotype_birth_data.hh
+++ avida/current/source/main/inject_genotype_birth_data.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef INJECT_GENOTYPE_BIRTH_DATA_HH
#define INJECT_GENOTYPE_BIRTH_DATA_HH

#ifndef COUNT_TRACKER_HH
#include "count_tracker.hh"
#endif

class cInjectGenotype;
class cInjectGenotype_BirthData {
public:
  cInjectGenotype_BirthData(int in_update_born);
  ~cInjectGenotype_BirthData();

  cCountTracker birth_track;
  cCountTracker death_track;
  //cCountTracker breed_in_track;
  //cCountTracker breed_true_track;
  //cCountTracker breed_out_track;

  int update_born;      // Update genotype was first created
  int parent_id;        // ID of parent genotype
  //int parent_distance;  // Genetic distance from parent genotype
  int gene_depth;       // depth in the phylogenetic tree from ancestor

  int update_deactivated;      // If not, when did it get deactivated?
  cInjectGenotype * parent_genotype; // Pointer to parent genotype...
  //cSpecies * parent_species;
  int num_offspring_genotypes; // Num offspring genotypes still in memory.
};

#endif

Index: avida/current/source/main/inject_genotype_control.cc
+++ avida/current/source/main/inject_genotype_control.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef INJECT_GENOTYPE_CONTROL_HH
#include "inject_genotype_control.hh"
#endif

#ifndef DEFS_HH
#include "defs.hh"
#endif
#ifndef INJECT_GENEBANK_HH
#include "inject_genebank.hh"
#endif
#ifndef INJECT_GENOTYPE_HH
#include "inject_genotype.hh"
#endif

////////////////////////////
//  cInjectGenotypeControl
////////////////////////////

cInjectGenotypeControl::cInjectGenotypeControl(cInjectGenebank & in_gb) : genebank(in_gb)
{
  size = 0;
  best = NULL;
  coalescent = NULL;
  for (int i = 0; i < INJECTGENOTYPE_THREADS; i++) threads[i] = NULL;

  historic_list = NULL;
  historic_count = 0;
}

cInjectGenotypeControl::~cInjectGenotypeControl()
{
}

bool cInjectGenotypeControl::OK()
{
  int ret_value = true;

  // Cycle through the list, making sure all connections are proper, size
  // is correct, and all genotypes are OK().

  cInjectGenotype * cur_pos = best;
  for (int i = 0; i < size; i++) {
    if (!cur_pos->OK()) ret_value = false;
    assert (cur_pos->GetNext()->GetPrev() == cur_pos);
    cur_pos = cur_pos->GetNext();
  }

  assert (cur_pos == best);

  return ret_value;
}

void cInjectGenotypeControl::Insert(cInjectGenotype & in_inject_genotype, cInjectGenotype * prev_genotype)
{
  if (prev_genotype == NULL) {
    assert(size == 0); // Destroying a full genotype queue...

    best = &in_inject_genotype;
    best->SetNext(best);
    best->SetPrev(best);
  }
  else {
    in_inject_genotype.SetPrev(prev_genotype);
    in_inject_genotype.SetNext(prev_genotype->GetNext());
    prev_genotype->SetNext(&in_inject_genotype);
    in_inject_genotype.GetNext()->SetPrev(&in_inject_genotype);
  }

  size++;
}

void cInjectGenotypeControl::Remove(cInjectGenotype & in_inject_genotype)
{
  if (size == 1) {
    best = NULL;
  }
  if (&in_inject_genotype == best) {
    best = best->GetNext();
  }

  in_inject_genotype.GetNext()->SetPrev(in_inject_genotype.GetPrev());
  in_inject_genotype.GetPrev()->SetNext(in_inject_genotype.GetNext());
  in_inject_genotype.SetNext(NULL);
  in_inject_genotype.SetPrev(NULL);

  size--;
}

void cInjectGenotypeControl::RemoveHistoric(cInjectGenotype & in_inject_genotype)
{
  if (historic_count == 1) {
    historic_list = NULL;
  }
  if (&in_inject_genotype == historic_list) {
    historic_list = historic_list->GetNext();
  }

  in_inject_genotype.GetNext()->SetPrev(in_inject_genotype.GetPrev());
  in_inject_genotype.GetPrev()->SetNext(in_inject_genotype.GetNext());
  in_inject_genotype.SetNext(NULL);
  in_inject_genotype.SetPrev(NULL);

  historic_count--;
}

void cInjectGenotypeControl::InsertHistoric(cInjectGenotype & in_inject_genotype)
{
  if (historic_count == 0) {
    in_inject_genotype.SetNext(&in_inject_genotype);
    in_inject_genotype.SetPrev(&in_inject_genotype);
  }
  else {
    in_inject_genotype.SetPrev(historic_list->GetPrev());
    in_inject_genotype.SetNext(historic_list);
    historic_list->GetPrev()->SetNext(&in_inject_genotype);
    historic_list->SetPrev(&in_inject_genotype);
  }

  historic_list = &in_inject_genotype;
  historic_count++;
}

/*int cInjectGenotypeControl::UpdateCoalescent()
{
  // Test to see if any updating needs to be done...
  // Don't update active coalescent genotype, or if there is more than
  // one offspring.
  if (coalescent != NULL &&
      (coalescent->GetNumInjected() > 0) ||
      coalescent->GetNumOffspringGenotypes() > 1) ) {
    return coalescent->GetDepth();
  }

  // If there is no best, there is nothing to search through...
  if (best == NULL) return -1;

  // Find the new point...
  cInjectGenotype * test_gen = best;
  cInjectGenotype * found_gen = best;
  cInjectGenotype * parent_gen = best->GetParentGenotype();

  while (parent_gen != NULL) {
    // See if this genotype should be the new found genotype...
    if (test_gen->GetNumOrganisms() > 0 ||
	test_gen->GetNumOffspringGenotypes() > 1) {
      found_gen = test_gen;
    }

    // Move to the next genotype...
    test_gen = parent_gen;
    parent_gen = test_gen->GetParentGenotype();
  }

  coalescent = found_gen;

  return coalescent->GetDepth();
}*/


bool cInjectGenotypeControl::CheckPos(cInjectGenotype & in_inject_genotype)
{
  int next_OK = false;
  int prev_OK = false;

  if (in_inject_genotype.GetNumInjected() >= in_inject_genotype.GetNext()->GetNumInjected()) {
    next_OK =true;
  }
  if (in_inject_genotype.GetNumInjected() <= in_inject_genotype.GetPrev()->GetNumInjected()) {
    prev_OK =true;
  }

  if ((&in_inject_genotype == best && next_OK) ||
      (next_OK && prev_OK) ||
      (&in_inject_genotype == best->GetPrev() && prev_OK)) {
    return true;
  }

  return false;
}

void cInjectGenotypeControl::Insert(cInjectGenotype & new_genotype)
{
  // If there is nothing in the list, add this.

  if (size == 0) {
    Insert(new_genotype, NULL);
  }

  // Otherwise tack it on the end.

  else {
    Insert(new_genotype, best->GetPrev());
  }
}

bool cInjectGenotypeControl::Adjust(cInjectGenotype & in_inject_genotype)
{
  //if (in_inject_genotype.GetDeferAdjust() == true) return true;

  cInjectGenotype * cur_inject_genotype = in_inject_genotype.GetPrev();

  // Check to see if this genotype should be removed completely.

  if (in_inject_genotype.GetNumInjected() == 0) {
    genebank.RemoveInjectGenotype(in_inject_genotype);
    return false;
  }

  // Do not adjust if this was and still is the best genotype, or is
  // otherwise in the proper spot...

  if (CheckPos(in_inject_genotype)) {
    return true;
  }

  // Otherwise, remove it from the queue for just the moment.

  Remove(in_inject_genotype);

  // Also, if this genotype is the best, put it there.

  if (in_inject_genotype.GetNumInjected() > best->GetNumInjected()) {
    Insert(in_inject_genotype, best->GetPrev());
    best = &in_inject_genotype;
    return true;
  }

  // Finally, find out where this genotype *does* go.

  while (cur_inject_genotype->GetNumInjected() >= in_inject_genotype.GetNumInjected() &&
	 cur_inject_genotype != best->GetPrev()) {
    cur_inject_genotype = cur_inject_genotype->GetNext();
  }
  while (cur_inject_genotype->GetNumInjected() < in_inject_genotype.GetNumInjected() &&
	 cur_inject_genotype != best) {
    cur_inject_genotype = cur_inject_genotype->GetPrev();
  }

  Insert(in_inject_genotype, cur_inject_genotype);

  return true;
}


cInjectGenotype * cInjectGenotypeControl::Find(const cGenome & in_genome) const
{
  int i;
  cInjectGenotype * cur_inject_genotype = best;

  for (i = 0; i < size; i++) {
    if (in_genome == cur_inject_genotype->GetGenome()) {
      return cur_inject_genotype;
    }
    cur_inject_genotype = cur_inject_genotype->GetNext();
  }

  return NULL;
}

int cInjectGenotypeControl::FindPos(cInjectGenotype & in_inject_genotype, int max_depth)
{
  cInjectGenotype * temp_genotype = best;
  if (max_depth < 0 || max_depth > size) max_depth = size;

  for (int i = 0; i < max_depth; i++) {
    if (temp_genotype == &in_inject_genotype) return i;
    temp_genotype = temp_genotype->GetNext();
  }

  return -1;
}

cInjectGenotype * cInjectGenotypeControl::Next(int thread)
{
  return threads[thread] = threads[thread]->GetNext();
}

cInjectGenotype * cInjectGenotypeControl::Prev(int thread)
{
  return threads[thread] = threads[thread]->GetPrev();
}

Index: avida/current/source/main/inject_genotype_control.hh
+++ avida/current/source/main/inject_genotype_control.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef INJECT_GENOTYPE_CONTROL_HH
#define INJECT_GENOTYPE_CONTROL_HH

#ifndef INJECT_GENEBANK_MACROS_HH
#include "inject_genebank_macros.hh"
#endif

class cGenome;
class cInjectGenotype;
class cInjectGenebank;
class cInjectGenotypeControl {
private:
  int size;
  cInjectGenotype * best;
  cInjectGenotype * coalescent;
  cInjectGenotype * threads[INJECTGENOTYPE_THREADS];
  cInjectGenebank & genebank;

  cInjectGenotype * historic_list;
  int historic_count;

  void Insert(cInjectGenotype & in_inject_genotype, cInjectGenotype * prev_inject_genotype);
  bool CheckPos(cInjectGenotype & in_inject_genotype);
public:
  cInjectGenotypeControl(cInjectGenebank & in_gb);
  ~cInjectGenotypeControl();

  bool OK();
  void Remove(cInjectGenotype & in_inject_genotype);
  void Insert(cInjectGenotype & new_inject_genotype);
  bool Adjust(cInjectGenotype & in_inject_genotype);

  void RemoveHistoric(cInjectGenotype & in_inject_genotype);
  void InsertHistoric(cInjectGenotype & in_inject_genotype);
  int GetHistoricCount() { return historic_count; }

  int UpdateCoalescent();

  inline int GetSize() const { return size; }
  inline cInjectGenotype * GetBest() const { return best; }
  inline cInjectGenotype * GetCoalescent() const { return coalescent; }

  cInjectGenotype * Find(const cGenome & in_genome) const;
  int FindPos(cInjectGenotype & in_inject_genotype, int max_depth = -1);

  inline cInjectGenotype * Get(int thread) const { return threads[thread]; }
  inline cInjectGenotype * Reset(int thread)
    { return threads[thread] = best; }
  inline cInjectGenotype * ResetHistoric(int thread)
    { return threads[thread] = historic_list; }
  cInjectGenotype * Next(int thread);
  cInjectGenotype * Prev(int thread);
};

#endif

Index: avida/current/source/main/inject_genotype_element.hh
+++ avida/current/source/main/inject_genotype_element.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef INJECT_GENOTYPE_ELEMENT_HH
#define INJECT_GENOTYPE_ELEMENT_HH

#ifndef DEFS_HH
#include "defs.hh"
#endif

class cInjectGenotype;
class cInjectGenotypeElement {
private:
  cInjectGenotype * inject_genotype;
  cInjectGenotypeElement * next;
  cInjectGenotypeElement * prev;
public:
  inline cInjectGenotypeElement(cInjectGenotype * in_gen=NULL) : inject_genotype(in_gen) {
    next = NULL;  prev = NULL;
  }
  inline ~cInjectGenotypeElement() { ; }

  inline cInjectGenotype * GetInjectGenotype() const { return inject_genotype; }
  inline cInjectGenotypeElement * GetNext() const { return next; }
  inline cInjectGenotypeElement * GetPrev() const { return prev; }

  inline void SetNext(cInjectGenotypeElement * in_next) { next = in_next; }
  inline void SetPrev(cInjectGenotypeElement * in_prev) { prev = in_prev; }
};

#endif

Index: avida/current/source/main/inject_genotype_queue.cc
+++ avida/current/source/main/inject_genotype_queue.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef INJECT_GENOTYPE_QUEUE_HH
#include "inject_genotype_queue.hh"
#endif

#ifndef INJECT_GENOTYPE_HH
#include "inject_genotype.hh"
#endif

#include <assert.h>

/////////////////////
//  cInjectGenotypeQueue
/////////////////////

cInjectGenotypeQueue::cInjectGenotypeQueue()
{
  size = 0;
  root.SetNext(&root);
  root.SetPrev(&root);
}


cInjectGenotypeQueue::~cInjectGenotypeQueue()
{
  while (root.GetNext() != &root) {
    Remove(root.GetNext());
  }
}

bool cInjectGenotypeQueue::OK()
{
  bool result = true;
  int count = 0;

  for (cInjectGenotypeElement * temp_element = root.GetNext();
       temp_element != &root;
       temp_element = temp_element->GetNext()) {
    assert (temp_element->GetNext()->GetPrev() == temp_element);
    assert (temp_element->GetInjectGenotype()->GetID() >= 0);

    count++;
    assert (count <= size);
  }

  assert (count == size);

  return result;
}

void cInjectGenotypeQueue::Insert(cInjectGenotype & in_inject_genotype)
{
  cInjectGenotypeElement * new_element = new cInjectGenotypeElement(&in_inject_genotype);
  new_element->SetNext(root.GetNext());
  new_element->SetPrev(&root);
  root.GetNext()->SetPrev(new_element);
  root.SetNext(new_element);
  size++;
}

void cInjectGenotypeQueue::Remove(cInjectGenotype & in_inject_genotype)
{
  cInjectGenotypeElement * cur_element;

  for (cur_element = root.GetNext();
       cur_element != &root;
       cur_element = cur_element->GetNext()) {
    if (cur_element->GetInjectGenotype() == &in_inject_genotype) break;
  }

  assert (cur_element != &root);

  Remove(cur_element);
}

void cInjectGenotypeQueue::Remove(cInjectGenotypeElement * in_element)
{
  in_element->GetPrev()->SetNext(in_element->GetNext());
  in_element->GetNext()->SetPrev(in_element->GetPrev());
  in_element->SetNext(NULL);
  in_element->SetPrev(NULL);
  delete(in_element);

  size--;
}

cInjectGenotype * cInjectGenotypeQueue::Find(const cGenome & in_genome) const
{
  for (cInjectGenotypeElement * cur_element = root.GetNext();
       cur_element != &root;
       cur_element = cur_element->GetNext()) {
    if (cur_element->GetInjectGenotype()->GetGenome() == in_genome) {
      return cur_element->GetInjectGenotype();
    }
  }

  return NULL;
}

Index: avida/current/source/main/inject_genotype_queue.hh
+++ avida/current/source/main/inject_genotype_queue.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef INJECT_GENOTYPE_QUEUE_HH
#define INJECT_GENOTYPE_QUEUE_HH

#ifndef INJECT_GENOTYPE_ELEMENT_HH
#include "inject_genotype_element.hh"
#endif

class cInjectGenotype;
class cGenome;
class cInjectGenotypeQueue {
private:
  int size;
  cInjectGenotypeElement root;

  void Remove(cInjectGenotypeElement * in_element);
public:
  cInjectGenotypeQueue();
  ~cInjectGenotypeQueue();

  bool OK();

  void Insert(cInjectGenotype & in_inject_genotype);
  void Remove(cInjectGenotype & in_inject_genotype);
  cInjectGenotype * Find(const cGenome & in_genome) const;
};

#endif

Index: avida/current/source/main/inst_lib_base.hh
+++ avida/current/source/main/inst_lib_base.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef INST_LIB_BASE_HH
#define INST_LIB_BASE_HH

#ifndef INSTRUCTION_HH
#include "instruction.hh"
#endif

class cString;
class cInstLibBase {
public:
  virtual const cString &GetName(const unsigned int id) = 0;
  virtual const cString &GetNopName(const unsigned int id) = 0;
  virtual int GetNopMod(const unsigned int id) = 0;
  virtual int GetNopMod(const cInstruction & inst) = 0;
  virtual int GetSize() = 0;
  virtual int GetNumNops() = 0;
  virtual cInstruction GetInst(const cString & in_name) = 0;
  virtual const cInstruction & GetInstDefault() = 0;
  virtual const cInstruction & GetInstError() = 0;
};

#endif

Index: avida/current/source/main/instruction.cc
+++ avida/current/source/main/instruction.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2001 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#include "instruction.hh"


char cInstruction::GetSymbol() const
{
  if (operand < 26) return operand + 'a';
  if (operand < 52) return operand - 26 + 'A';
  if (operand < 62) return operand - 52 + '0';
  if (operand == 255) return '_';
  return  '?';
}

void cInstruction::SetSymbol(char symbol)
{
  if (symbol >= 'a' && symbol <= 'z') operand = symbol - 'a';
  else if (symbol >= 'A' && symbol <= 'Z') operand = symbol - 'A' + 26;
  else if (symbol >= '0' && symbol <= '9') operand = symbol - '0' + 52;
  else operand = 254;
}


Index: avida/current/source/main/instruction.hh
+++ avida/current/source/main/instruction.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef INSTRUCTION_HH
#define INSTRUCTION_HH

#include <assert.h>

#ifndef DEFS_HH
#include "defs.hh"
#endif

class cInstruction {
private:
  UCHAR operand;

public:
  // Accessors...
  int GetOp() const { return (int) operand; }
  void SetOp(int in_op) { assert(in_op < 256); operand = in_op; }

  // Operators...
  void operator=(const cInstruction & inst)
    { if (this != &inst) operand = inst.operand; }
  bool operator==(const cInstruction & inst) const
    { return (operand == inst.operand); }
  bool operator!=(const cInstruction & inst) const
    { return !(operator==(inst)); }

  // Constructors and Destructor...
  cInstruction() { operand = 0; }
  cInstruction(const cInstruction & _inst) { *this = _inst; }
  explicit cInstruction(int in_op) { SetOp(in_op); }
  ~cInstruction() { ; }

  // Some extra methods to convert too and from alpha-numeric symbols...
  char GetSymbol() const;
  void SetSymbol(char symbol);
};

#endif

Index: avida/current/source/main/local_mutations.cc
+++ avida/current/source/main/local_mutations.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef LOCAL_MUTATIONS_HH
#include "local_mutations.hh"
#endif

#ifndef MUTATION_HH
#include "mutation.hh"
#endif
#ifndef MUTATION_LIB_HH
#include "mutation_lib.hh"
#endif
#ifndef MUTATION_MACROS_HH
#include "mutation_macros.hh"
#endif

/////////////////////
//  cLocalMutations
/////////////////////

cLocalMutations::cLocalMutations(const cMutationLib & _lib, int genome_length)
  : mut_lib(_lib)
  , rates(_lib.GetSize())
{
  // Setup the rates for this specifc organism.
  const tArray<cMutation *> & mut_array = mut_lib.GetMutationArray();
  for (int i = 0; i < rates.GetSize(); i++) {
    if (mut_array[i]->GetScope() == MUTATION_SCOPE_PROP ||
	mut_array[i]->GetScope() == MUTATION_SCOPE_SPREAD) {
      rates[i] = mut_array[i]->GetRate() / (double) genome_length;
    }
    else {
      rates[i] = mut_array[i]->GetRate();
    }
  }

  // Setup the mutation count array.
  counts.Resize(mut_lib.GetSize(), 0);
}

cLocalMutations::~cLocalMutations()
{
}

Index: avida/current/source/main/local_mutations.hh
+++ avida/current/source/main/local_mutations.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef LOCAL_MUTATIONS_HH
#define LOCAL_MUTATIONS_HH

#ifndef TARRAY_HH
#include "tArray.hh"
#endif

class cMutationLib;
class cLocalMutations {
private:
  const cMutationLib & mut_lib;
  tArray<double> rates;
  tArray<int> counts;
public:
  cLocalMutations(const cMutationLib & _lib, int genome_length);
  ~cLocalMutations();

  const cMutationLib & GetMutationLib() const { return mut_lib; }
  double GetRate(int id) const { return rates[id]; }
  int GetCount(int id) const { return counts[id]; }

  void IncCount(int id) { counts[id]++; }
  void IncCount(int id, int num_mut) { counts[id] += num_mut; }
};

#endif

Index: avida/current/source/main/mutation.cc
+++ avida/current/source/main/mutation.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef MUTATION_HH
#include "mutation.hh"
#endif


///////////////
//  cMutation
///////////////

cMutation::cMutation(const cString & _name, int _id, int _trigger,
		     int _scope, int _type, double _rate)
  : name(_name)
    , id(_id)
    , trigger(_trigger)
    , scope(_scope)
    , type(_type)
    , rate(_rate)
{
}

cMutation::~cMutation()
{
}

Index: avida/current/source/main/mutation.hh
+++ avida/current/source/main/mutation.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef MUTATION_HH
#define MUTATION_HH

#ifndef STRING_HH
#include "string.hh"
#endif

class cMutation {
private:
  cString name;
  int id;
  int trigger;
  int scope;
  int type;
  double rate;
public:
  cMutation(const cString & _name, int _id, int _trigger, int _scope,
	    int _type, double _rate);
  ~cMutation();

  const cString & GetName() const { return name; }
  int GetID() const { return id; }
  int GetTrigger() const { return trigger; }
  int GetScope() const { return scope; }
  int GetType() const { return type; }
  double GetRate() const { return rate; }
};

#endif

Index: avida/current/source/main/mutation_lib.cc
+++ avida/current/source/main/mutation_lib.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef MUTATION_LIB_HH
#include "mutation_lib.hh"
#endif

#ifndef MUTATION_HH
#include "mutation.hh"
#endif
#ifndef MUTATION_MACROS_HH
#include "mutation_macros.hh"
#endif

//////////////////
//  cMutationLib
//////////////////

cMutationLib::cMutationLib()
  : trigger_list_array(NUM_MUTATION_TRIGGERS)
{
}

cMutationLib::~cMutationLib()
{
  // Get rid of the trigger lists...  This is not required, but since we
  // are deleting the mutations after this, we should first remove all
  // references to them.
  trigger_list_array.Resize(0);

  // Now delete the actual mutations.
  for (int i = 0; i < mutation_array.GetSize(); i++) {
    delete mutation_array[i];
  }
}

cMutation * cMutationLib::AddMutation(const cString & name, int trigger,
				      int scope, int type, double rate)
{
  // Build the new mutation and drop it in the proper trigger list.
  const int id = GetSize();
  mutation_array.Resize(id+1);
  mutation_array[id] = new cMutation(name, id, trigger, scope, type, rate);
  trigger_list_array[trigger].Push(mutation_array[id]);

  return mutation_array[id];
}

Index: avida/current/source/main/mutation_lib.hh
+++ avida/current/source/main/mutation_lib.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef MUTATION_LIB_HH
#define MUTATION_LIB_HH

#ifndef TARRAY_HH
#include "tArray.hh"
#endif
#ifndef TLIST_HH
#include "tList.hh"
#endif

class cMutation;
class cString;
class cMutationLib {
private:
  tArray<cMutation *> mutation_array;
  tArray< tList<cMutation> > trigger_list_array;
public:
  cMutationLib();
  ~cMutationLib();

  int GetSize() const { return mutation_array.GetSize(); }

  cMutation * AddMutation(const cString & name, int trigger, int scope,
			  int type, double rate);

  const tArray<cMutation *> & GetMutationArray() const
    { return mutation_array; }
  const tList<cMutation> & GetMutationList(int trigger) const
    { return trigger_list_array[trigger]; }
};

#endif

Index: avida/current/source/main/mutation_macros.hh
+++ avida/current/source/main/mutation_macros.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef MUTATION_MACROS_HH
#define MUTATION_MACROS_HH

#define MUTATION_TRIGGER_NONE     0
#define MUTATION_TRIGGER_UPDATE   1
#define MUTATION_TRIGGER_DIVIDE   2
#define MUTATION_TRIGGER_PARENT   3
#define MUTATION_TRIGGER_WRITE    4
#define MUTATION_TRIGGER_READ     5
#define MUTATION_TRIGGER_EXEC     6
#define NUM_MUTATION_TRIGGERS     7

#define MUTATION_SCOPE_GENOME     0
#define MUTATION_SCOPE_LOCAL      1
#define MUTATION_SCOPE_GLOBAL     2
#define MUTATION_SCOPE_PROP       3
#define MUTATION_SCOPE_SPREAD     4

#define MUTATION_TYPE_POINT       0
#define MUTATION_TYPE_INSERT      1
#define MUTATION_TYPE_DELETE      2
#define MUTATION_TYPE_HEAD_INC    3
#define MUTATION_TYPE_HEAD_DEC    4
#define MUTATION_TYPE_TEMP        5
#define MUTATION_TYPE_KILL        6

#endif

Index: avida/current/source/main/mutation_rates.cc
+++ avida/current/source/main/mutation_rates.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef MUTATION_RATES_HH
#include "mutation_rates.hh"
#endif

#ifndef TOOLS_HH
#include "tools.hh"
#endif

////////////////////
//  cMutationRates
////////////////////

cMutationRates::cMutationRates()
{
  Clear();
}

cMutationRates::cMutationRates(const cMutationRates & in_muts)
{
  Copy(in_muts);
}

cMutationRates::~cMutationRates()
{
}

void cMutationRates::Clear()
{
  exec.point_mut_prob = 0.0;
  copy.copy_mut_prob = 0.0;
  divide.ins_mut_prob = 0.0;
  divide.del_mut_prob = 0.0;
  divide.div_mut_prob = 0.0;
  divide.divide_mut_prob = 0.0;
  divide.divide_ins_prob = 0.0;
  divide.divide_del_prob = 0.0;
  divide.parent_mut_prob = 0.0;
  divide.crossover_prob = 0.0;
  divide.aligned_cross_prob = 0.0;
}

void cMutationRates::Copy(const cMutationRates & in_muts)
{
  exec.point_mut_prob = in_muts.exec.point_mut_prob;
  copy.copy_mut_prob = in_muts.copy.copy_mut_prob;
  divide.ins_mut_prob = in_muts.divide.ins_mut_prob;
  divide.del_mut_prob = in_muts.divide.del_mut_prob;
  divide.div_mut_prob = in_muts.divide.div_mut_prob;
  divide.divide_mut_prob = in_muts.divide.divide_mut_prob;
  divide.divide_ins_prob = in_muts.divide.divide_ins_prob;
  divide.divide_del_prob = in_muts.divide.divide_del_prob;
  divide.parent_mut_prob = in_muts.divide.parent_mut_prob;
  divide.crossover_prob = in_muts.divide.crossover_prob;
  divide.aligned_cross_prob = in_muts.divide.aligned_cross_prob;

  //  if (copy.copy_mut_prob != 0) cerr << "Copying non-zero copy mut rate!" << endl;
}

bool cMutationRates::TestPointMut() const
{
  return g_random.P(exec.point_mut_prob);
}

bool cMutationRates::TestCopyMut() const
{
  return g_random.P(copy.copy_mut_prob);
}

bool cMutationRates::TestDivideMut() const
{
  return g_random.P(divide.divide_mut_prob);
}

bool cMutationRates::TestDivideIns() const
{
  return g_random.P(divide.divide_ins_prob);
}

bool cMutationRates::TestDivideDel() const
{
  return g_random.P(divide.divide_del_prob);
}

bool cMutationRates::TestParentMut() const
{
  return g_random.P(divide.parent_mut_prob);
}

bool cMutationRates::TestCrossover() const
{
  return g_random.P(divide.crossover_prob);
}

bool cMutationRates::TestAlignedCrossover() const
{
  return g_random.P(divide.aligned_cross_prob);
}

Index: avida/current/source/main/mutation_rates.hh
+++ avida/current/source/main/mutation_rates.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef MUTATION_RATES_HH
#define MUTATION_RATES_HH

class cMutationRates {
private:
  // Mutations are divided up by when they occur...

  // ...anytime during execution...
  struct sExecMuts {
    double point_mut_prob;
  };
  sExecMuts exec;

  // ...during an instruction copy...
  struct sCopyMuts {
    double copy_mut_prob;
  };
  sCopyMuts copy;

  // ...at the divide...
  struct sDivideMuts {
    double ins_mut_prob;        // Per site
    double del_mut_prob;        // Per site
    double div_mut_prob;        // Per site
    double divide_mut_prob;     // Max one per divide
    double divide_ins_prob;     // Max one per divide
    double divide_del_prob;     // Max one per divide
    double crossover_prob;
    double aligned_cross_prob;
    double parent_mut_prob;
  };
  sDivideMuts divide;
  
  void operator=(const cMutationRates & in_muts)
    { (void) in_muts; } // Disable operator=
public:
  cMutationRates();
  cMutationRates(const cMutationRates & in_muts);
  ~cMutationRates();

  void Clear();
  void Copy(const cMutationRates & in_muts);

  bool TestPointMut() const;
  bool TestCopyMut() const;
  bool TestDivideMut() const;
  bool TestDivideIns() const;
  bool TestDivideDel() const;
  bool TestParentMut() const;
  bool TestCrossover() const;
  bool TestAlignedCrossover() const;

  double GetPointMutProb() const     { return exec.point_mut_prob; }
  double GetCopyMutProb() const      { return copy.copy_mut_prob; }
  double GetInsMutProb() const       { return divide.ins_mut_prob; }
  double GetDelMutProb() const       { return divide.del_mut_prob; }
  double GetDivMutProb() const       { return divide.div_mut_prob; }
  double GetDivideMutProb() const    { return divide.divide_mut_prob; }
  double GetDivideInsProb() const    { return divide.divide_ins_prob; }
  double GetDivideDelProb() const    { return divide.divide_del_prob; }
  double GetParentMutProb() const    { return divide.parent_mut_prob; }
  double GetCrossoverProb() const    { return divide.crossover_prob; }
  double GetAlignedCrossProb() const { return divide.aligned_cross_prob; }

  void SetPointMutProb(double in_prob)  { exec.point_mut_prob  = in_prob; }
  void SetCopyMutProb(double in_prob)   { copy.copy_mut_prob   = in_prob; }
  void SetInsMutProb(double in_prob)    { divide.ins_mut_prob    = in_prob; }
  void SetDelMutProb(double in_prob)    { divide.del_mut_prob    = in_prob; }
  void SetDivMutProb(double in_prob)    { divide.div_mut_prob    = in_prob; }
  void SetDivideMutProb(double in_prob) { divide.divide_mut_prob = in_prob; }
  void SetDivideInsProb(double in_prob) { divide.divide_ins_prob = in_prob; }
  void SetDivideDelProb(double in_prob) { divide.divide_del_prob = in_prob; }
  void SetParentMutProb(double in_prob) { divide.parent_mut_prob = in_prob; }
  void SetCrossoverProb(double in_prob) { divide.crossover_prob  = in_prob; }
  void SetAlignedCrossProb(double in)   { divide.aligned_cross_prob = in; }
};

#endif

Index: avida/current/source/main/mx_code_array.cc
+++ avida/current/source/main/mx_code_array.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef MX_CODE_ARRAY_HH
#include "mx_code_array.hh"
#endif

#ifndef CONFIG_HH
#include "config.hh"
#endif
#ifndef CPU_TEST_INFO_HH
#include "cpu_test_info.hh"
#endif
#ifndef GENOME_HH
#include "genome.hh"
#endif
#ifndef INST_SET_HH
#include "inst_set.hh"
#endif
#ifndef MY_CODE_ARRAY_LESS_THAN_HH
#include "my_code_array_less_than.hh"
#endif
#ifndef ORGANISM_HH
#include "organism.hh"
#endif
#ifndef TEST_CPU_HH
#include "test_cpu.hh"
#endif
#ifndef TOOLS_HH
#include "tools.hh"
#endif

#include <iomanip>

using namespace std;

//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//  cMxCodeArray
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

const int cMxCodeArray::m_max_gestation_time = 1000000000;


cMxCodeArray::cMxCodeArray()
{
  // Initialize the code array as empty.
  size = 0;
  max_size = 0;
  data = NULL;
  m_merit = 0;
  m_gestation_time = m_max_gestation_time;
  m_num_instructions = 0;
}

cMxCodeArray::cMxCodeArray(int n_inst, int in_size, int in_max_size) :m_merit(0), m_gestation_time(m_max_gestation_time), m_num_instructions(n_inst)
{  
  assert (in_max_size == 0 || in_max_size >= in_size);

  // Initialize the code array randomly.
  size = in_size;
  if (in_max_size != 0) max_size = in_max_size;
  else max_size = size;

  data = new cInstruction[max_size];

  for (int i = 0; i < size; i++)
    {
      data[i].SetOp(g_random.GetUInt(cConfig::GetNumInstructions()));
    }

}

cMxCodeArray::cMxCodeArray(const cMxCodeArray &in_code)
{

  size = in_code.size;
  max_size = in_code.max_size;
  m_merit = in_code.m_merit;
  m_gestation_time = in_code.m_gestation_time;
  m_num_instructions = in_code.m_num_instructions;
  m_trans_probs = in_code.m_trans_probs;

  data = new cInstruction[max_size];

  for (int i = 0; i < size; i++)
    {
      data[i] = in_code.data[i];
    }

}


cMxCodeArray::cMxCodeArray(const cGenome &in_code, int in_max_size) :m_merit(0), m_gestation_time(m_max_gestation_time), m_num_instructions(0)
{
  assert (in_max_size == 0 || in_max_size >= in_code.GetSize());

  size = in_code.GetSize();
  if (in_max_size != 0) max_size = in_max_size;
  else max_size = size;

  data = new cInstruction[max_size];

  for (int i = 0; i < size; i++) {
    data[i] = in_code[i];
  }
}


cMxCodeArray::~cMxCodeArray()
{
  // TODO - what is this?
  // g_memory.Remove(C_CODE_ARRAY);

  if (data) delete [] data;
}

void cMxCodeArray::Resize(int new_size)
{
  assert (new_size <= MAX_CREATURE_SIZE);

  // If we are not changing the size, just return.
  if (new_size == size) return;

  // Re-construct the arrays only if we have to...
  if (new_size > max_size || new_size * 4 < max_size) {
    cInstruction * new_data = new cInstruction[new_size];

    for (int i = 0; i < size && i < new_size; i++) {
      new_data[i] = data[i];
    }

    if (data) delete [] data;

    data = new_data;
    max_size = new_size;
  }

  // Fill in the un-filled-in bits...
  for (int i = size; i < new_size; i++) {
    data[i].SetOp(g_random.GetUInt(cConfig::GetNumInstructions()));
  }

  size = new_size;
}

// Resize the arrays, and leave memeory uninitializes! (private method)
void cMxCodeArray::ResetSize(int new_size, int new_max)
{
  assert (new_size >= 0);
  assert (new_max == 0 || new_max >= new_size);

  // If we are clearing it totally, do so.
  if (!new_size) {
    if (data) delete [] data;
    data = NULL;
    size = 0;
    max_size = 0;
    return;
  }

  // If a new max is _not_ being set, see if one needs to be.
  if (new_max == 0 &&
      (max_size < new_size) || (max_size > new_size * 2)) {
    new_max = new_size;
  }

  // If the arrays need to be rebuilt, do so.
  if (new_max != 0 && new_max != max_size) {
    cInstruction * new_data = new cInstruction[new_max];

    if (data) delete [] data;
    data = new_data;
    max_size = new_max;
  }

  // Reset the array size.
  size = new_size;
}

/**
 * Resizes and reinitializes the genome. The previous data is lost.
 **/
void cMxCodeArray::Reset()
{
  // Initialze the array
  if( cConfig::GetAllocMethod() == ALLOC_METHOD_RANDOM ){
    // Randomize the initial contents of the new array.
    Randomize();
  }else{
    // Assume default instuction initialization
    Clear();
  }
}

/**
 * Sets all instructions to @ref cInstruction::GetInstDefault().
 **/
void cMxCodeArray::Clear()
{
  int i;
  for (i = 0; i < size; i++)
    {
      data[i] = cInstSet::GetInstDefault();
    }
}

/**
 * Replaces all instructions in the genome with a sequence of random
 * instructions.
 **/

void cMxCodeArray::Randomize()
{
  int i;
  for (i = 0; i < size; i++)
    {
      data[i].SetOp(g_random.GetUInt(cConfig::GetNumInstructions()));
    }
}

void cMxCodeArray::operator=(const cMxCodeArray & other_code)
{
  // If we need to resize, do so...

  ResetSize(other_code.size);

  // Now that both code arrays are the same size, copy the other one over.

  for (int i = 0; i < size; i++)
    {
      data[i] = other_code.data[i];
    }

    m_merit = other_code.m_merit;
    m_gestation_time = other_code.m_gestation_time;
    m_num_instructions = other_code.m_num_instructions;
    m_trans_probs = other_code.m_trans_probs;
}


/*
 * Let the 0th  instruction be the least significant,
 * so longer codes are always greater.
 */
bool cMxCodeArray::operator<(const cMxCodeArray &other_code) const
{

  if (size < other_code.size)
    return true;
  else if (size > other_code.size)
    return false;

  bool result = false;

  for (int i = size-1; i >= 0; i-- )
    {
      if (data[i].GetOp() < other_code.data[i].GetOp())
	{
	  result = true;
	  break;
	}
      else if (other_code.data[i].GetOp() < data[i].GetOp())
	{
	  result = false;
	  break;
	}
    }

  return result;
}


void cMxCodeArray::CopyDataTo(cGenome & other_code) const
{
  // @CAO this is ugly, but the only option I see...
  other_code = cGenome(size);

  for (int i = 0; i < size; i++) {
    other_code[i] = data[i];
  }
}

bool cMxCodeArray::OK() const
{
  bool result = true;

  assert (size >= 0 && size <= max_size && max_size <= MAX_CREATURE_SIZE);

  return result;
}


int cMxCodeArray::FindInstruction(const cInstruction & inst, int start_index)
{
  assert(start_index < GetSize());
  for(int i=0; i<GetSize(); ++i ){
    if( Get(i) == inst ){
      return i;
    }
  }
  return -1;
}

cString cMxCodeArray::AsString() const
{
  cString out_string(size);
  for (int i = 0; i < size; i++) {
    int cur_char = data[i].GetOp();
    if (cur_char < 26) {
      out_string[i] = cur_char + 'a';
    } else if (cur_char < 52) {
      out_string[i] = cur_char - 26 + 'A';
    } else if (cur_char < 62) {
      out_string[i] = cur_char - 52 + '1';
    } else {
      out_string[i] = '*';
    }
  }

  return out_string;
}


void cMxCodeArray::Get1Mutants(list<cMxCodeArray>& mutants) const
{
  for (int line_num = 0; line_num < size; line_num++)
    {
      int cur_inst = data[line_num].GetOp();

      for (int inst_num = 0; inst_num < m_num_instructions; inst_num++)
	{
	  if (cur_inst == inst_num) continue;

	  cMxCodeArray newMutant(*this);
	  newMutant[line_num].SetOp(inst_num);
	  mutants.push_back(newMutant);
	}
    }
}


/*
  Make a list of the transition probabilities only to those other
  genotypes that are within the given hamming distance of this
  genotype.

  The list is actually implemented as a map from indexes to
  probabilities, where the index is the place of the genotype in
  the complete ordered set of genotypes.

  TODO this seems kind of inefficient that you have to calculate the
  hamming distance twice - maybe I should pass it as a parameter to
  the TransitionProbability function after it is first calculated?  Or
  maybe the threshold should be in the transition probability?
*/

  /* dropped const for win32 -- kgn */
//int cMxCodeArray::MakeTransitionList(const set<cMxCodeArray, MyCodeArrayLessThan > &data_set, int hamDistThresh, double errorRate) const
int cMxCodeArray::MakeTransitionList(set<cMxCodeArray, MyCodeArrayLessThan > &data_set, int hamDistThresh, double errorRate) const
{
  set<cMxCodeArray, MyCodeArrayLessThan >::iterator set_iter;
  int index = 0;
  double totalProb = 0.0;
  int num = 0;

  for (set_iter = data_set.begin(); set_iter != data_set.end(); set_iter++, index++)
    {
      if (HammingDistance(*set_iter) <= hamDistThresh)
	{
	  double transProb =  TransitionProbability(*set_iter, errorRate);
	  m_trans_probs[index] = transProb * GetFitness();
	  totalProb += transProb;
	  num += 1;
	}
      else
	{
	  m_trans_probs[index]= 0.0;
	}
    }

  /* The transition probability for "other"
     index got incremented at the very end of the loop so its pointing
     to the next element now */

  m_trans_probs[index] = (1.0 - totalProb) * GetFitness();

  return num;

}


const map<int, double, less<int> >& cMxCodeArray::GetTransitionList() const
{
  return m_trans_probs;
}


int cMxCodeArray::HammingDistance(const cMxCodeArray &other_gene) const
{
  int distance = 0;

  assert (size == other_gene.GetSize());

  for (int i = 0; i < size; i++)
    {
      if (this->Get(i) != other_gene.Get(i))
	distance++;
    }

  return distance;
}


double cMxCodeArray::TransitionProbability(const cMxCodeArray &other_gene, double errorRate) const
{
  double Q = 0.0;
  assert (size == other_gene.GetSize());

  if ( (*this) == other_gene)
    {
      Q = pow((1-errorRate), size);
    }
  else
    {
      int distance = HammingDistance(other_gene);
      Q = pow((1.0-errorRate), (size -distance)) * pow((errorRate/m_num_instructions),distance);
    }

  return Q;
}

/*
  Used in testing the diagonalization.
*/

void cMxCodeArray::PrintTransitionList(ostream &fp, int size) const
{

  fp.setf(ios::fixed);

  fp << "{" ;

  for (int index=0 ; index < size; index++)
    {
      map<int, double, less<int> >::const_iterator find_results = m_trans_probs.find(index);
      if (find_results == m_trans_probs.end())
	{
	  fp << 0.0 ;
	}
      else
	{
	  fp << setprecision(10) << (*find_results).second ;
	}

      if (index < size-1)
	fp << " , " ;

    }

  fp << "}" ;
}


void cMxCodeArray::CalcFitness()
{
  cGenome temp(1);
  cCPUTestInfo test_info;
  CopyDataTo(temp); 
  cTestCPU::TestGenome(test_info, temp);
  if ( test_info.IsViable() )
    m_gestation_time =
      test_info.GetTestOrganism()->GetPhenotype().GetGestationTime();
  else // if not viable, set a really high gestation time
    m_gestation_time = m_max_gestation_time;
  m_merit = test_info.GetTestOrganism()->GetPhenotype().GetMerit().GetDouble();
}

Index: avida/current/source/main/mx_code_array.hh
+++ avida/current/source/main/mx_code_array.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef MX_CODE_ARRAY_HH
#define MX_CODE_ARRAY_HH

#include <map>
#include <list>
#include <set>
#include <ostream>

#ifndef INSTRUCTION_HH
#include "instruction.hh"
#endif
#ifndef STRING_HH
#include "string.hh"
#endif
#ifndef STRING_UTIL_HH
#include "string_util.hh"
#endif

/**
 * This class stores the genome of an Avida organism only.
 * Cannot be run in a simulation.
 **/

class cGenome;
class MyCodeArrayLessThan;
class cMxCodeArray {
private:
  int size;
  int max_size;
  cInstruction * data;
  double m_merit;
  int m_gestation_time;
  static const int m_max_gestation_time;
  int m_num_instructions;
  mutable std::map<int, double, std::less<int> > m_trans_probs;


public:
  cMxCodeArray();
  explicit cMxCodeArray(int ninst, int in_size=0, int in_max_size=0);
  cMxCodeArray(const cMxCodeArray &in_code);
  cMxCodeArray(const cGenome & in_code, int in_max_size=0);
  virtual ~cMxCodeArray();

  void operator=(const cMxCodeArray &other_code);
  bool operator==(const cMxCodeArray &other_code) const;
  inline cInstruction & operator[](int index);
  bool operator<(const cMxCodeArray &other_code) const;

  void CopyDataTo(cGenome & other_code) const;
  void Resize(int new_size);
  void ResetSize(int new_size, int new_max=0);
  inline int GetSize() const { return size; }
  inline double GetFitness() const {
    if ( m_gestation_time == m_max_gestation_time )
      return 0;
    else return m_merit/m_gestation_time;}
  double GetMerit() const { return m_merit; }
  double GetGestationTime() const { return m_gestation_time; }
  void CalcFitness();

  inline const cInstruction & Get(int index) const {
    assert(index < size);
    return data[index];
  }

  int FindInstruction(const cInstruction & inst, int start_index=0);
  inline bool HasInstruction(const cInstruction & inst){
    return ( FindInstruction(inst) >= 0 ) ? true : false; }

  inline void Set(int index, const cInstruction & value);

  void Reset();
  void Clear();
  void Randomize();
  bool OK() const;
  cString AsString() const;

  cString DebugType() { return "cMxCodeArray"; }
  cString DebugInfo() { return cStringUtil::Stringf("size = %d", size); }
  int DebugSize() { return max_size; }



  /* For Depth Limited Search */
  void Get1Mutants(std::list<cMxCodeArray>& mutants) const;
  void SetNumInstructions(int ninst) {m_num_instructions = ninst;}


  /* For Transition Matrix */
  //int MakeTransitionList(const std::set<cMxCodeArray, MyCodeArrayLessThan >& m_data_set,
  /* dropped const for win32 -- kgn */
  int MakeTransitionList(std::set<cMxCodeArray, MyCodeArrayLessThan >& m_data_set,
                          int hamDistThresh, double errorRate) const;
  const std::map<int, double, std::less<int> >& GetTransitionList() const;
  int HammingDistance(const cMxCodeArray &other_gene) const;
  double TransitionProbability(const cMxCodeArray &other_gene, double errorRate) const;
  void PrintTransitionList(std::ostream &fp, int size) const;
};

cInstruction & cMxCodeArray::operator[](int index)
{
#ifdef DEBUG
  assert(index < size);
  assert(index >= 0);
#endif
  return data[index];
}

inline bool cMxCodeArray::operator==(const cMxCodeArray &other_code) const
{
  // Make sure the sizes are the same.
  if (size != other_code.size) return false;

  // Then go through line by line.
  for (int i = 0; i < size; i++)
    if (data[i].GetOp() != other_code.data[i].GetOp()) return false;

  return true;
}

inline void cMxCodeArray::Set(int index, const cInstruction & value)
{
  operator[](index) = value;
}

#endif

Index: avida/current/source/main/my_code_array_less_than.hh
+++ avida/current/source/main/my_code_array_less_than.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef MY_CODE_ARRAY_LESS_THAN_HH
#define MY_CODE_ARRAY_LESS_THAN_HH

#ifndef MX_CODE_ARRAY_HH
#include "mx_code_array.hh"
#endif

class MyCodeArrayLessThan{
public:
  bool operator()(const cMxCodeArray &x, const cMxCodeArray &y) const
  {
    return x < y;
  }
};

#endif

Index: avida/current/source/main/population_interface.cc
+++ avida/current/source/main/population_interface.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef POPULATION_INTERFACE_HH
#include "population_interface.hh"
#endif

#include <assert.h>

#ifndef NULL
#define NULL 0
#endif

cPopulationInterface::cPopulationInterface()
  : population(NULL)
  , cell_id(-1)
  , fun_new_hardware(NULL)
  , fun_recycle(NULL)
  , fun_divide(NULL)
  , fun_test_on_divide(NULL)
  , fun_get_neighbor(NULL)
  , fun_birth_chamber(NULL)
  , fun_num_neighbors(NULL)
  , fun_rotate(NULL)
  , fun_breakpoint(NULL)
  , fun_test_fitness(NULL)
  , fun_get_input(NULL)
  , fun_get_input_at(NULL)
  , fun_debug(NULL)
  , fun_get_resources(NULL)
  , fun_update_resources(NULL)
  , fun_kill_cell(NULL)
  , fun_kill_surround_cell(NULL)
    , fun_send_message(NULL)
    , fun_inject_parasite(NULL)
{
}


cPopulationInterface::~cPopulationInterface()
{
}

void cPopulationInterface::CopyCallbacks(cPopulationInterface & in_interface)
{
  fun_new_hardware     = in_interface.fun_new_hardware;
  fun_recycle          = in_interface.fun_recycle;
  fun_divide           = in_interface.fun_divide;
  fun_test_on_divide   = in_interface.fun_test_on_divide;
  fun_get_neighbor     = in_interface.fun_get_neighbor;
  fun_birth_chamber    = in_interface.fun_birth_chamber;
  fun_num_neighbors    = in_interface.fun_num_neighbors;
  fun_rotate           = in_interface.fun_rotate;
  fun_breakpoint       = in_interface.fun_breakpoint;
  fun_test_fitness     = in_interface.fun_test_fitness;
  fun_get_input        = in_interface.fun_get_input;
  fun_debug            = in_interface.fun_debug;
  fun_get_resources    = in_interface.fun_get_resources;
  fun_update_resources = in_interface.fun_update_resources;
  fun_kill_cell        = in_interface.fun_kill_cell;
  fun_kill_surround_cell = in_interface.fun_kill_surround_cell;
  fun_send_message     = in_interface.fun_send_message;
  fun_inject_parasite  = in_interface.fun_inject_parasite;
}

cHardwareBase * cPopulationInterface::NewHardware(cOrganism * owner)
{
  assert(fun_new_hardware != NULL);  // All interfaces must have a NewHardware!
  return (*fun_new_hardware)(population, owner);
}


void cPopulationInterface::RecycleHardware(cHardwareBase * out_hardware)
{
  assert(fun_recycle != NULL);  // All interfaces must have a RecycleHArdware!
  (*fun_recycle)(out_hardware);
}


bool cPopulationInterface::Divide(cOrganism * parent, cGenome & child_genome)
{
  assert (fun_divide != NULL);       // All interfaces must have a Divide!
  return (*fun_divide)(population, cell_id, parent, child_genome);  
}

bool cPopulationInterface::TestOnDivide() const
{
  if (population == NULL) return false;
  assert(fun_test_on_divide != NULL);
  return (*fun_test_on_divide)(population, cell_id);
}

cOrganism * cPopulationInterface::GetNeighbor()
{
  if (fun_get_neighbor == NULL) return NULL;

  assert(cell_id >= 0);
  return (*fun_get_neighbor)(population, cell_id);
}

cBirthChamber & cPopulationInterface::GetBirthChamber()
{
  assert(fun_birth_chamber != NULL);
  
  return (*fun_birth_chamber)(population, cell_id);
}

int cPopulationInterface::GetNumNeighbors()
{
  if (fun_num_neighbors == NULL) return 0;

  assert(cell_id >= 0);
  return (*fun_num_neighbors)(population, cell_id);
}

void cPopulationInterface::Rotate(int direction)
{
  if (fun_rotate == NULL) return;

  assert(cell_id >= 0);
  (*fun_rotate)(population, cell_id, direction);
}

void cPopulationInterface::Breakpoint()
{
  if (fun_breakpoint == NULL) return;
  (*fun_breakpoint)();
}

double cPopulationInterface::TestFitness()
{
  if (fun_test_fitness == NULL) return -1.0;
  return (*fun_test_fitness)(population, cell_id);
}

int cPopulationInterface::GetInput()
{
  assert(fun_get_input != NULL);
  return (*fun_get_input)(population, cell_id);
}

int cPopulationInterface::GetInputAt(int & input_pointer)
{
  assert(fun_get_input_at != NULL);
  return (*fun_get_input_at)(population, cell_id, input_pointer);
}

int cPopulationInterface::Debug()
{
  assert(fun_debug != NULL);
  return (*fun_debug)(population, cell_id);
}

const tArray<double> & cPopulationInterface::GetResources()
{
  assert(fun_get_resources != NULL);
  return (*fun_get_resources)(population, cell_id);
}

void cPopulationInterface::UpdateResources(const tArray<double> & res_change)
{
  assert(fun_update_resources != NULL);
  (*fun_update_resources)(population, cell_id, res_change);
}

void cPopulationInterface::Die()
{
  if (fun_kill_cell == NULL) return;
  (*fun_kill_cell)(population, cell_id);
}

void cPopulationInterface::Kaboom()
{
	if (fun_kill_surround_cell == NULL) return;
	(*fun_kill_surround_cell)(population, cell_id);
}

bool cPopulationInterface::SendMessage(cOrgMessage & mess)
{
  if (fun_send_message == NULL) return false;
  return (*fun_send_message)(population, cell_id, mess);
}

bool cPopulationInterface::InjectParasite(cOrganism * parent, 
					  const cGenome & injected_code)
{
  if (fun_inject_parasite == NULL) return false;
  return (*fun_inject_parasite)(population, cell_id, parent, injected_code);
}


Index: avida/current/source/main/population_interface.hh
+++ avida/current/source/main/population_interface.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

// This class is used by organisms to interface with their population.

#ifndef POPULATION_INTERFACE_HH
#define POPULATION_INTERFACE_HH

class cHardwareBase;
class cPopulation;
class cOrganism;
class cGenome;
template <class T> class tArray;
class cOrgMessage;
class cBirthChamber;

typedef cHardwareBase * (*tFunNewHardware)(cPopulation *pop, cOrganism *owner);
typedef void (*tFunRecycle)(cHardwareBase * out_hardware);
typedef bool (*tFunDivide)
  (cPopulation * pop, int cell_id, cOrganism * parent, cGenome & child_genome);
typedef bool (*tFunTestOnDivide)(cPopulation * pop, int cell_id);
typedef cOrganism * (*tFunGetNeighbor)(cPopulation * pop, int cell_id);
typedef cBirthChamber & (*tFunBirthChamber)(cPopulation * pop, int cell_id);
typedef int (*tFunNumNeighbors)(cPopulation * pop, int cell_id);
typedef void (*tFunRotate)(cPopulation * pop, int cell_id, int direction);
typedef void (*tFunBreakpoint)();
typedef double (*tFunTestFitness)(cPopulation * pop, int cell_id);
typedef int (*tFunGetInput)(cPopulation * pop, int cell_id);
typedef int (*tFunGetInputAt)(cPopulation * pop, int cell_id, int & input_pointer);
typedef int (*tFunDebug)(cPopulation * pop, int cell_id);
typedef const tArray<double> & (*tFunGetResources)
  (cPopulation * pop, int cell_id);
typedef void (*tFunUpdateResources)
  (cPopulation * pop, int cell_id, const tArray<double> & res_change);
typedef void (*tFunKillCell)(cPopulation * pop, int death_id);
typedef void (*tFunKillSurroundCell)(cPopulation * pop, int commie_id);
typedef bool (*tFunSendMessage)(cPopulation * pop, int cell_id, cOrgMessage & mess);
typedef bool (*tFunInjectParasite)
  (cPopulation * pop, int cell_id, cOrganism * parent, const cGenome & injected_code);


class cPopulationInterface {
private:
  cPopulation * population;
  int cell_id;

  tFunNewHardware      fun_new_hardware;
  tFunRecycle          fun_recycle;
  tFunDivide           fun_divide;
  tFunTestOnDivide     fun_test_on_divide;
  tFunGetNeighbor      fun_get_neighbor;
  tFunBirthChamber     fun_birth_chamber;
  tFunNumNeighbors     fun_num_neighbors;
  tFunRotate           fun_rotate;
  tFunBreakpoint       fun_breakpoint;
  tFunTestFitness      fun_test_fitness;
  tFunGetInput         fun_get_input;
  tFunGetInputAt       fun_get_input_at;
  tFunDebug            fun_debug;
  tFunGetResources     fun_get_resources;
  tFunUpdateResources  fun_update_resources;
  tFunKillCell		   fun_kill_cell;
  tFunKillSurroundCell fun_kill_surround_cell;
  tFunSendMessage      fun_send_message;
  tFunInjectParasite   fun_inject_parasite;
public:
  cPopulationInterface();
  ~cPopulationInterface();

  cPopulation * GetPopulation() { return population; }
  void SetPopulation(cPopulation * pop) { population = pop; }

  int GetCellID() { return cell_id; }
  void SetCellID(int in_id) { cell_id = in_id; }

  void SetFun_NewHardware(tFunNewHardware fun) { fun_new_hardware = fun; }
  void SetFun_Recycle(tFunRecycle fun) { fun_recycle = fun; }
  void SetFun_Divide(tFunDivide fun) { fun_divide = fun; }
  void SetFun_TestOnDivide(tFunTestOnDivide fun) { fun_test_on_divide = fun; }
  void SetFun_GetNeighbor(tFunGetNeighbor fun) { fun_get_neighbor = fun; }
  void SetFun_BirthChamber(tFunBirthChamber fun) { fun_birth_chamber = fun; }
  void SetFun_NumNeighbors(tFunNumNeighbors fun) { fun_num_neighbors = fun; }
  void SetFun_Rotate(tFunRotate fun) { fun_rotate = fun; }
  void SetFun_Breakpoint(tFunBreakpoint fun) { fun_breakpoint = fun; }
  void SetFun_TestFitness(tFunTestFitness fun) { fun_test_fitness = fun; }
  void SetFun_GetInput(tFunGetInput fun) { fun_get_input = fun; }
  void SetFun_GetInputAt(tFunGetInputAt fun) { fun_get_input_at = fun; }
  void SetFun_Debug(tFunDebug fun) { fun_debug = fun; }
  void SetFun_GetResources(tFunGetResources fun) { fun_get_resources = fun; }
  void SetFun_UpdateResources(tFunUpdateResources fun)
    { fun_update_resources = fun; }
  void SetFun_KillCell(tFunKillCell fun) { fun_kill_cell = fun; }
  void SetFun_KillSurroundCell(tFunKillSurroundCell fun) {fun_kill_surround_cell = fun; }
  void SetFun_SendMessage(tFunSendMessage fun) { fun_send_message = fun; }
  void SetFun_InjectParasite(tFunInjectParasite fun) { fun_inject_parasite = fun; }
  void CopyCallbacks(cPopulationInterface & in_interface);

  // Activate callbacks...
  cHardwareBase * NewHardware(cOrganism * owner);
  void RecycleHardware(cHardwareBase * out_hardware);
  bool Divide(cOrganism * parent, cGenome & child_genome);
  bool TestOnDivide() const;
  cOrganism * GetNeighbor();
  cBirthChamber & GetBirthChamber();
  int GetNumNeighbors();
  void Rotate(int direction=1);
  void Breakpoint();
  double TestFitness();
  int GetInput();
  int GetInputAt(int & input_pointer);
  int Debug();
  const tArray<double> & GetResources();
  void UpdateResources(const tArray<double> & res_change);
  void Die();
  void Kaboom();
  bool SendMessage(cOrgMessage & mess);
  bool InjectParasite(cOrganism * parent, const cGenome & injected_code);
};

#endif

Index: avida/current/source/main/primitive.hh
+++ avida/current/source/main/primitive.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2001 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef PRIMITIVE_HH
#define PRIMITIVE_HH

#ifndef AVIDA_HH
#include "avida.hh"
#endif
#ifndef AVIDA_DRIVER_ANALYZE_HH
#include "avida_driver_analyze.hh"
#endif
#ifndef AVIDA_DRIVER_BASE_HH
#include "avida_driver_base.hh"
#endif
#ifndef AVIDA_DRIVER_POPULATION_HH
#include "avida_driver_population.hh"
#endif
#ifndef CONFIG_HH
#include "config.hh"
#endif
#ifndef ENVIRONMENT_HH
#include "environment.hh"
#endif
#ifndef POPULATION_HH
#include "population.hh"
#endif

#endif

Index: avida/current/source/main/reaction_lib.cc
+++ avida/current/source/main/reaction_lib.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2001 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef REACTION_LIB_HH
#include "reaction_lib.hh"
#endif

#ifndef REACTION_HH
#include "reaction.hh"
#endif

//////////////////
//  cReactionLib
//////////////////

cReactionLib::~cReactionLib()
{
  for (int i = 0; i < reaction_array.GetSize(); i++) {
    delete reaction_array[i];
  }
}


cReaction * cReactionLib::GetReaction(const cString & name) const
{
  for (int i = 0; i < reaction_array.GetSize(); i++) {
    if (reaction_array[i]->GetName() == name) return reaction_array[i];
  }
  return NULL;
}

cReaction * cReactionLib::GetReaction(int id) const
{
  return reaction_array[id];
}


cReaction * cReactionLib::AddReaction(const cString & name)
{
  // If this reaction already exists, just return it.
  cReaction * found_reaction = GetReaction(name);
  if (found_reaction != NULL) return found_reaction;

  // Create a new reaction...
  const int new_id = reaction_array.GetSize();
  cReaction * new_reaction = new cReaction(name, new_id);
  reaction_array.Resize(new_id + 1);
  reaction_array[new_id] = new_reaction;
  return new_reaction;
}

Index: avida/current/source/main/reaction_lib.hh
+++ avida/current/source/main/reaction_lib.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2001 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef REACTION_LIB_HH
#define REACTION_LIB_HH

#ifndef TARRAY_HH
#include "tArray.hh"
#endif

class cReaction;
class cString;

class cReactionLib {
private:
  tArray<cReaction *> reaction_array;
public:
  cReactionLib() { ; }
  ~cReactionLib();

  int GetSize() const { return reaction_array.GetSize(); }
  
  cReaction * AddReaction(const cString & name);
  cReaction * GetReaction(const cString & name) const;
  cReaction * GetReaction(int id) const;
};

#endif

Index: avida/current/source/main/reaction_macros.hh
+++ avida/current/source/main/reaction_macros.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2001 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef REACTION_MACROS_HH
#define REACTION_MACROS_HH

#define REACTION_PROCTYPE_ADD  0
#define REACTION_PROCTYPE_MULT 1
#define REACTION_PROCTYPE_POW  2

#endif

Index: avida/current/source/main/reaction_process.cc
+++ avida/current/source/main/reaction_process.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2001 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef REACTION_PROCESS_HH
#include "reaction_process.hh"
#endif

#ifndef DEFS_HH
#include "defs.hh"
#endif
#ifndef REACTION_MACROS_HH
#include "reaction_macros.hh"
#endif

//////////////////////
//  cReactionProcess
//////////////////////

cReactionProcess::cReactionProcess()
  : resource(NULL)
  , value(1.0)
  , type(REACTION_PROCTYPE_ADD)
  , max_number(1.0)
  , min_number(0.0)
  , max_fraction(1.0)
  , product(NULL)
  , conversion(1.0)
  , lethal(0)
  , detect(NULL)
  , detection_threshold(0.0)
  , detection_error(0.0)
{
}

cReactionProcess::~cReactionProcess()
{
}

Index: avida/current/source/main/reaction_process.hh
+++ avida/current/source/main/reaction_process.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2001 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef REACTION_PROCESS_HH
#define REACTION_PROCESS_HH

class cResource;
class cReactionProcess {
private:
  cResource * resource;  // Resource consumed.
  double value;          // Efficiency.
  int type;              // Method of applying bonuses.
  double max_number;     // Max quantity of resource usable.
  double min_number;     // Minimum quantity of resource needed (otherwise 0)
  double max_fraction;   // Max fraction of avaiable resources useable.
  cResource * product;   // Output resource.
  double conversion;     // Conversion factor.
  bool lethal;			 // Lethality of reaction
  cResource * detect; // Resource Measured
  double detection_threshold;  //Minimum quantity of resource to register as present
  double detection_error;  //Var of Detection Event (as % of resource present)
public:
  cReactionProcess();
  ~cReactionProcess();

  cResource * GetResource() const { return resource; }
  double GetValue() const { return value; }
  int GetType() const { return type; }
  double GetMaxNumber() const { return max_number; }
  double GetMinNumber() const { return min_number; }
  double GetMaxFraction() const { return max_fraction; }
  cResource * GetProduct() const { return product; }
  double GetConversion() const { return conversion; }
  bool GetLethal() const { return lethal; }
  cResource * GetDetect() const { return detect; }
  double GetDetectionThreshold() const { return detection_threshold; }
  double GetDetectionError() const { return detection_error; }

  void SetResource(cResource * _in) { resource = _in; }
  void SetValue(double _in) { value = _in; }
  void SetType(int _in) { type = _in; }
  void SetMaxNumber(double _in) { max_number = _in; }
  void SetMinNumber(double _in) { min_number = _in; }
  void SetMaxFraction(double _in) { max_fraction = _in; }
  void SetProduct(cResource * _in) { product = _in; }
  void SetConversion(double _in) { conversion = _in; }
  void SetLethal(int _in) { lethal = _in; }
  void SetDetect(cResource * _in) { detect = _in; }
  void SetDetectionThreshold(double _in) { detection_threshold = _in; }
  void SetDetectionError(double _in) { detection_error = _in; }
};

#endif

Index: avida/current/source/main/reaction_requisite.cc
+++ avida/current/source/main/reaction_requisite.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2001 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef REACTION_REQUISITE_HH
#include "reaction_requisite.hh"
#endif

#include <limits.h>

////////////////////////
//  cReactionRequisite
////////////////////////

cReactionRequisite::cReactionRequisite()
  : min_task_count(0)
  , max_task_count(INT_MAX)
{
}

cReactionRequisite::~cReactionRequisite()
{
}

Index: avida/current/source/main/reaction_requisite.hh
+++ avida/current/source/main/reaction_requisite.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2001 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef REACTION_REQUISITE_HH
#define REACTION_REQUISITE_HH

#ifndef TLIST_HH
#include "tList.hh"
#endif

class cReaction;
class cReactionRequisite {
private:
  tList<cReaction> prior_reaction_list;
  tList<cReaction> prior_noreaction_list;
  int min_task_count;
  int max_task_count;
public:
  cReactionRequisite();
  ~cReactionRequisite();

  const tList<cReaction> & GetReactions() const { return prior_reaction_list; }
  const tList<cReaction> & GetNoReactions() const
    { return prior_noreaction_list; }
  int GetMinTaskCount() const { return min_task_count; }
  int GetMaxTaskCount() const { return max_task_count; }

  void AddReaction(cReaction * in_reaction) {
    prior_reaction_list.PushRear(in_reaction);
  }
  void AddNoReaction(cReaction * in_reaction) {
    prior_noreaction_list.PushRear(in_reaction);
  }
  void SetMinTaskCount(int min) { min_task_count = min; }
  void SetMaxTaskCount(int max) { max_task_count = max; }
};

#endif

Index: avida/current/source/main/resource_count_macros.hh
+++ avida/current/source/main/resource_count_macros.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2001 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef RESOURCE_COUNT_MACROS_HH
#define RESOURCE_COUNT_MACROS_HH

#define GEOMETRY_GLOBAL 0
#define GEOMETRY_GRID   1
#define GEOMETRY_TORUS  2

#define MAXFLOWPTS 8

#endif

Index: avida/current/source/main/resource_lib.cc
+++ avida/current/source/main/resource_lib.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef RESOURCE_LIB_HH
#include "resource_lib.hh"
#endif

#ifndef RESOURCE_HH
#include "resource.hh"
#endif

using namespace std;

cResourceLib::~cResourceLib()
{
  for (int i = 0; i < resource_array.GetSize(); i++) {
    delete resource_array[i];
  }
}

cResource * cResourceLib::AddResource(const cString & res_name)
{
  const int new_id = resource_array.GetSize();
  cResource * new_resource = new cResource(res_name, new_id);
  resource_array.Resize(new_id + 1);
  resource_array[new_id] = new_resource;
  return new_resource;
}

cResource * cResourceLib::GetResource(const cString & res_name) const
{
  for (int i = 0; i < resource_array.GetSize(); i++) {
    if (resource_array[i]->GetName() == res_name) return resource_array[i];
  }
  cerr << "Error: Unknown resource '" << res_name << "'." << endl;
  return NULL;
}

cResource * cResourceLib::GetResource(int id) const
{
  return resource_array[id];
}

Index: avida/current/source/main/resource_lib.hh
+++ avida/current/source/main/resource_lib.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef RESOURCE_LIB_HH
#define RESOURCE_LIB_HH

#ifndef TARRAY_HH
#include "tArray.hh"
#endif

class cResource;
class cString;
class cResourceLib {
private:
  tArray<cResource *> resource_array;
public:
  cResourceLib() { ; }
  ~cResourceLib();

  int GetSize() const { return resource_array.GetSize(); }

  cResource * AddResource(const cString & res_name);
  cResource * GetResource(const cString & res_name) const;
  cResource * GetResource(int id) const;
};

#endif

Index: avida/current/source/main/resource_macros.hh
+++ avida/current/source/main/resource_macros.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef RESOURCE_MACROS_HH
#define RESOURCE_MACROS_HH

#define GEOMETRY_GLOBAL 0
#define GEOMETRY_GRID   1
#define GEOMETRY_TORUS  2

#endif

Index: avida/current/source/main/spatial_count_elem.cc
+++ avida/current/source/main/spatial_count_elem.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2001 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef SPATIAL_COUNT_ELEM_HH
#include "spatial_count_elem.hh"
#endif

#ifndef RESOURCE_COUNT_MACROS_HH
#include "resource_count_macros.hh"
#endif

cSpatialCountElem::cSpatialCountElem (double initamount) {
    amount = initamount;
    delta=0.0;
    elempt.Resize(MAXFLOWPTS);
    xdist.Resize(MAXFLOWPTS);
    ydist.Resize(MAXFLOWPTS);
    dist.Resize(MAXFLOWPTS);
}
cSpatialCountElem::cSpatialCountElem () {
    amount = 0.0;
    delta=0.0;
    elempt.Resize(MAXFLOWPTS);
    xdist.Resize(MAXFLOWPTS);
    ydist.Resize(MAXFLOWPTS);
    dist.Resize(MAXFLOWPTS);
}
void cSpatialCountElem::SetPtr (int innum, int inelempt, int inxdist, 
                        int inydist, double indist) {
  elempt[innum] = inelempt;
  xdist[innum] = inxdist;
  ydist[innum] = inydist;
  dist[innum] = indist;
}

Index: avida/current/source/main/spatial_count_elem.hh
+++ avida/current/source/main/spatial_count_elem.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2001 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef SPATIAL_COUNT_ELEM_HH
#define SPATIAL_COUNT_ELEM_HH

#ifndef TARRAY_HH
#include "tArray.hh"
#endif

class cSpatialCountElem {
  mutable double amount, delta;
  tArray<int> elempt, xdist, ydist;
  tArray<double> dist;
public:
  cSpatialCountElem (double initamount);
  cSpatialCountElem ();
  void Rate (double ratein) const {delta += ratein;}
  void State () {amount += delta; delta = 0.0;}
  const double GetAmount() const {return amount;}
  void SetPtr (int innum, int inelempt, int inxdist, int  inydist, 
               double indist);
  int GetElemPtr (int innum) {return elempt[innum];}
  int GetPtrXdist (int innum) {return xdist[innum];}
  int GetPtrYdist (int innum) {return ydist[innum];}
  double GetPtrDist (int innum) {return dist[innum];}
  friend void FlowMatter (cSpatialCountElem&, cSpatialCountElem&, double, 
                          double, double, double, int, int, double);
};

#endif

Index: avida/current/source/main/spatial_res_count.cc
+++ avida/current/source/main/spatial_res_count.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2001 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef SPATIAL_RES_COUNT_HH
#include "spatial_res_count.hh"
#endif

#ifndef CONFIG_HH
#include "config.hh"
#endif
#ifndef FUNCTIONS_HH
#include "functions.hh"
#endif

cSpatialResCount::cSpatialResCount(int inworld_x, int inworld_y, 
                  double inxdiffuse, double inydiffuse, double inxgravity, 
                  double inygravity)
                 : grid(inworld_x * inworld_y) {

  int i;
 
  xdiffuse = inxdiffuse;
  ydiffuse = inydiffuse;
  xgravity = inxgravity;
  ygravity = inygravity;
  world_x = inworld_x;
  world_y = inworld_y;
  num_cells = world_x * world_y;
  for (i = 0; i < GetSize(); i++) {
    cSpatialCountElem tmpelem;
    grid[i] = tmpelem;
  } 
  SetPointers();
}

cSpatialResCount::cSpatialResCount(int inworld_x, int inworld_y) 
                 : grid(inworld_x * inworld_y) {
  int i;
 
  xdiffuse = 1.0;
  ydiffuse = 1.0;
  xgravity = 0.0;
  ygravity = 0.0;
  world_x = inworld_x;
  world_y = inworld_y;
  num_cells = world_x * world_y;
  for (i = 0; i < GetSize(); i++) {
    cSpatialCountElem tmpelem;
    grid[i] = tmpelem;
   } 
   SetPointers();
}

cSpatialResCount::cSpatialResCount() {
  int i;
 
  xdiffuse = 1.0;
  ydiffuse = 1.0;
  xgravity = 0.0;
  ygravity = 0.0;
}

void cSpatialResCount::ResizeClear(int inworld_x, int inworld_y) {

  int i;
 
  grid.ResizeClear(inworld_x * inworld_y); 
  world_x = inworld_x;
  world_y = inworld_y;
  num_cells = world_x * world_y;
  for (i = 0; i < GetSize(); i++) {
    cSpatialCountElem tmpelem;
    grid[i] = tmpelem;
   } 
   SetPointers();
}

void cSpatialResCount::SetPointers() {

  /* Pointer 0 will point to the cell above and to the left the current cell
     and will go clockwise around the cell.                               */

  int     i,ii;
  double  SQRT2 = sqrt(2.0);

  /* First treat all cells like they are in a torus */

  for (i = 0; i < GetSize(); i++) {
    grid[i].SetPtr(0 ,Neighbor(i, world_x, world_y, -1, -1), -1, -1, SQRT2);
    grid[i].SetPtr(1 ,Neighbor(i, world_x, world_y,  0, -1),  0, -1, 1.0);
    grid[i].SetPtr(2 ,Neighbor(i, world_x, world_y, +1, -1), +1, -1, SQRT2);
    grid[i].SetPtr(3 ,Neighbor(i, world_x, world_y, +1,  0), +1,  0, 1.0);
    grid[i].SetPtr(4 ,Neighbor(i, world_x, world_y, +1, +1), +1, +1, SQRT2);
    grid[i].SetPtr(5 ,Neighbor(i, world_x, world_y,  0, +1),  0, +1, 1.0);
    grid[i].SetPtr(6 ,Neighbor(i, world_x, world_y, -1, +1), -1, +1, SQRT2);
    grid[i].SetPtr(7 ,Neighbor(i, world_x, world_y, -1,  0), -1,  0, 1.0);
  }
 
  /* Fix links for top, bottom and sides for non-torus */
  
  if (geometry == GEOMETRY_GRID) {
    /* Top and bottom */

    for (i = 0; i < world_x; i++) {
      grid[i].SetPtr(0, -99, -99, -99, -99.0);
      grid[i].SetPtr(1, -99, -99, -99, -99.0);
      grid[i].SetPtr(2, -99, -99, -99, -99.0);
      ii = num_cells-1-i;
      grid[ii].SetPtr(4, -99, -99, -99, -99.0);
      grid[ii].SetPtr(5, -99, -99, -99, -99.0);
      grid[ii].SetPtr(6, -99, -99, -99, -99.0);
    }

    /* fix links for right and left sides */

    for (i = 0; i < world_y; i++) {
      ii = i * world_x;    
      grid[ii].SetPtr(0, -99, -99, -99, -99.0);
      grid[ii].SetPtr(7, -99, -99, -99, -99.0);
      grid[ii].SetPtr(6, -99, -99, -99, -99.0);
      ii = ((i + 1) * world_x) - 1;
      grid[ii].SetPtr(2, -99, -99, -99, -99.0);
      grid[ii].SetPtr(3, -99, -99, -99, -99.0);
      grid[ii].SetPtr(4, -99, -99, -99, -99.0);
    }
  }
}

void cSpatialResCount::CheckRanges() {

  // Check that the x, y ranges of the inflow and outflow rectangles 
  // are valid
  /* check range of inputs */
  if (inflowX1 < 0) { 
    inflowX1 = 0; 
  } else if (inflowX1 > world_x) { 
    inflowX1 = world_x; 
  }
  if (inflowX2 < 0) { 
     inflowX2 = 0; 
  } else if (inflowX2 > world_x) { 
     inflowX2 = world_x; 
  }
  if (inflowY1 < 0) { 
    inflowY1 = 0; 
  } else if (inflowY1 > world_y) { 
    inflowY1 = world_y; 
  }
  if (inflowY2 < 0) { 
    inflowY2 = 0; 
  } else if (inflowY2 > world_y) { 
    inflowY2 = world_y; 
  }

  /* allow for rectangles that cross over the zero X or zero Y boundry */
  if (inflowX2 < inflowX1) { inflowX2 += world_x; }
  if (inflowY2 < inflowY1) { inflowY2 += world_y; }
  if (outflowX1 < 0) { 
    outflowX1 = 0; 
  } else if (outflowX1 > world_x) { 
    outflowX1 = world_x; 
  }
  if (outflowX2 < 0) { 
     outflowX2 = 0; 
  } else if (outflowX2 > world_x) { 
     outflowX2 = world_x; 
  }
  if (outflowY1 < 0) { 
    outflowY1 = 0; 
  } else if (outflowY1 > world_y) { 
    outflowY1 = world_y; 
  }
  if (outflowY2 < 0) { 
    outflowY2 = 0; 
  } else if (outflowY2 > world_y) { 
    outflowY2 = world_y; 
  }

  /* allow for rectangles that cross over the zero X or zero Y boundry */
  if (outflowX2 < outflowX1) { outflowX2 += world_x; }
  if (outflowY2 < outflowY1) { outflowY2 += world_y; }

}

void cSpatialResCount::RateAll(double ratein) {

  int i;
 
  for (i = 0; i < num_cells; i++) {
    grid[i].Rate(ratein);
  } 
}

void cSpatialResCount::StateAll() {

  int i;
 
  for (i = 0; i < num_cells; i++) {
    grid[i].State();
  } 
}

void cSpatialResCount::FlowAll() {

  int     i,k,ii,xdist,ydist;
  double  dist;
 
  for (i = 0; i < num_cells; i++) {
      
    /* because flow is two way we must check only half the neighbors to 
       prevent double flow calculations */

    for (k = 3; k <= 6; k++) {
      ii = grid[i].GetElemPtr(k);
      xdist = grid[i].GetPtrXdist(k);
      ydist = grid[i].GetPtrYdist(k);
      dist = grid[i].GetPtrDist(k);
      if (ii >= 0) {
        FlowMatter(grid[i],grid[ii],xdiffuse,ydiffuse,xgravity,ygravity,
                   xdist, ydist, dist);
      }
    }
  }
}

const double cSpatialResCount::SumAll() const{

  int i;
  double sum = 0.0;

  for (i = 0; i < num_cells; i++) {
    sum += GetAmount(i);
  } 
  return sum;
}


void cSpatialResCount::Source(double amount) const {
  int     i, j, elem;
  double  totalcells;


  totalcells = (inflowY2 - inflowY1 + 1) * (inflowX2 - inflowX1 + 1) * 1.0;
  amount /= totalcells;

  for (i = inflowY1; i <= inflowY2; i++) {
    for (j = inflowX1; j <= inflowX2; j++) {
      elem = (Mod(i,world_y) * world_x) + Mod(j,world_x);
      Rate(elem,amount); 
    }
  }
}

void cSpatialResCount::Sink(double decay) const {

  int     i, j, elem;
  double  deltaamount;


  for (i = outflowY1; i <= outflowY2; i++) {
    for (j = outflowX1; j <= outflowX2; j++) {
      elem = (Mod(i,world_y) * world_x) + Mod(j,world_x);
      deltaamount = Max((GetAmount(elem) * (1.0 - decay)), 0.0);
      Rate(elem,-deltaamount); 
    }
  }
}

Index: avida/current/source/main/spatial_res_count.hh
+++ avida/current/source/main/spatial_res_count.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2001 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef SPATIAL_RES_COUNT_HH
#define SPATIAL_RES_COUNT_HH

#ifndef SPATIAL_COUNT_ELEM_HH
#include "spatial_count_elem.hh"
#endif
#ifndef TARRAY_HH
#include "tArray.hh"
#endif

class cSpatialResCount {
  tArray<cSpatialCountElem> grid;
  double xdiffuse, xgravity, ydiffuse, ygravity;
  int    inflowX1, inflowX2, inflowY1, inflowY2;
  int    outflowX1, outflowX2, outflowY1, outflowY2;
  int    geometry;
  int    world_x, world_y, num_cells;
public:
  cSpatialResCount();
  cSpatialResCount(int inworld_x, int inworld_y);
  cSpatialResCount(int inworld_x, int inworld_y, double inxdiffuse,
        double inydiffuse, double inxgravity, double inygravity);
  void ResizeClear(int inworld_x, int inworld_y);
  void SetPointers();
  void CheckRanges();
  int GetSize () {return grid.GetSize();}
  int GetX () {return world_x;}
  int GetY () {return world_y;}
  cSpatialCountElem Element(int x) {return grid[x];}
  void Rate (int x, double ratein) const {grid[x].Rate(ratein);}
  void Rate (int x, int y, double ratein) const 
      {grid[y * world_x + x].Rate(ratein);}
  void State (int x) {grid[x].State();}
  void State (int x, int y) {grid[y*world_x + x].State();}
  const double GetAmount (int x) const {return grid[x].GetAmount();}
  const double GetAmount (int x, int y) const 
                           {return grid[y*world_x + x].GetAmount();}
  void RateAll (double ratein);
  void StateAll ();
  void FlowAll ();
  const double SumAll() const;
  void Source(double amount) const;
  void Sink(double percent) const;
  void SetGeometry(int in_geometry) { geometry = in_geometry; }
  void SetXdiffuse(double in_xdiffuse) { xdiffuse = in_xdiffuse; }
  void SetXgravity(double in_xgravity) { xgravity = in_xgravity; }
  void SetYdiffuse(double in_ydiffuse) { ydiffuse = in_ydiffuse; }
  void SetYgravity(double in_ygravity) { ygravity = in_ygravity; }
  void SetInflowX1(int in_inflowX1) { inflowX1 = in_inflowX1; }
  void SetInflowX2(int in_inflowX2) { inflowX2 = in_inflowX2; }
  void SetInflowY1(int in_inflowY1) { inflowY1 = in_inflowY1; }
  void SetInflowY2(int in_inflowY2) { inflowY2 = in_inflowY2; }
  void SetOutflowX1(int in_outflowX1) { outflowX1 = in_outflowX1; }
  void SetOutflowX2(int in_outflowX2) { outflowX2 = in_outflowX2; }
  void SetOutflowY1(int in_outflowY1) { outflowY1 = in_outflowY1; }
  void SetOutflowY2(int in_outflowY2) { outflowY2 = in_outflowY2; }
};

#endif

Index: avida/current/source/main/species_control.cc
+++ avida/current/source/main/species_control.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef SPECIES_CONTROL_HH
#include "species_control.hh"
#endif

#ifndef CONFIG_HH
#include "config.hh"
#endif
#ifndef DEFS_HH
#include "defs.hh"
#endif
#ifndef GENOTYPE_HH
#include "genotype.hh"
#endif
#ifndef GENOTYPE_MACROS_HH
#include "genotype_macros.hh"
#endif
#ifndef SPECIES_HH
#include "species.hh"
#endif
#ifndef STATS_HH
#include "stats.hh"
#endif

#include <assert.h>

/////////////////////
//  cSpeciesControl
/////////////////////

cSpeciesControl::cSpeciesControl(cGenebank & in_gb) : genebank(in_gb)
{
}

cSpeciesControl::~cSpeciesControl()
{
}

void cSpeciesControl::Remove(cSpecies & in_species)
{
  switch (in_species.GetQueueType()) {
  case SPECIES_QUEUE_ACTIVE:
    active_queue.Remove(in_species);
    break;
  case SPECIES_QUEUE_INACTIVE:
    inactive_queue.Remove(in_species);
    break;
  case SPECIES_QUEUE_GARBAGE:
    garbage_queue.Remove(in_species);
    break;
  default:
    break;
  }

  in_species.SetQueueType(SPECIES_QUEUE_NONE);
}

void cSpeciesControl::Adjust(cSpecies & in_species)
{
  // Only adjust if this species is in the active queue.

  if (in_species.GetQueueType() == SPECIES_QUEUE_ACTIVE) {
    active_queue.Adjust(in_species);
  }
}

void cSpeciesControl::SetActive(cSpecies & in_species)
{
  Remove(in_species);
  active_queue.InsertRear(in_species);
  in_species.SetQueueType(SPECIES_QUEUE_ACTIVE);
}

void cSpeciesControl::SetInactive(cSpecies & in_species)
{
  Remove(in_species);
  inactive_queue.InsertRear(in_species);
  in_species.SetQueueType(SPECIES_QUEUE_INACTIVE);
}

void cSpeciesControl::SetGarbage(cSpecies & in_species)
{
  Remove(in_species);
  garbage_queue.InsertRear(in_species);
  in_species.SetQueueType(SPECIES_QUEUE_GARBAGE);
}

bool cSpeciesControl::OK()
{
  int ret_value = true;

  // Check the queues.

  assert (active_queue.OK(SPECIES_QUEUE_ACTIVE));
  assert (inactive_queue.OK(SPECIES_QUEUE_INACTIVE));
  assert (garbage_queue.OK(SPECIES_QUEUE_GARBAGE));

  return ret_value;
}

int cSpeciesControl::FindPos(cSpecies & in_species, int max_depth)
{
  cSpecies * temp_species = active_queue.GetFirst();
  if (max_depth < 0 || max_depth > active_queue.GetSize()) {
    max_depth = active_queue.GetSize();
  }

  for (int i = 0; i < max_depth; i++) {
    if (temp_species == &in_species) return i;
    temp_species = temp_species->GetNext();
  }

  return -1;
}

cSpecies * cSpeciesControl::Find(cGenotype & in_genotype, int record_level)
{
  cSpecies * found_species = NULL;
  int cur_count, best_count = MAX_CREATURE_SIZE;
  cSpecies * cur_species;

  if (record_level == SPECIES_RECORD_FULL) {
    cur_species = active_queue.GetFirst();
    int size = active_queue.GetSize();
    for (int i = 0; i < size; i++) {
      cur_count = cur_species->Compare(in_genotype.GetGenome(),
				       cConfig::GetSpeciesThreshold());
      if (cur_count != -1 && cur_count <= cConfig::GetSpeciesThreshold() &&
	  cur_count < best_count) {
	found_species = cur_species;
	best_count = cur_count;
      }
      cur_species = cur_species->GetNext();
    }
  }

  if (record_level == SPECIES_RECORD_LIMITED) {
    cur_species = in_genotype.GetSpecies();

    if (cur_species) {
      int num_diff = cur_species->Compare(in_genotype.GetGenome(),
					  cConfig::GetSpeciesThreshold());
      if (num_diff != -1 && num_diff <= cConfig::GetSpeciesThreshold()) {
	found_species = cur_species;
      }
    }
  }

  return found_species;
}

void cSpeciesControl::Purge(cStats & stats)
{
  cSpecies * cur_species = garbage_queue.GetFirst();
  for (int i = 0; i < garbage_queue.GetSize(); i++) {
    stats.RemoveSpecies(cur_species->GetID(),
			cur_species->GetParentID(),
			cur_species->GetTotalGenotypes(),
			cur_species->GetTotalOrganisms(),
			stats.GetUpdate() - cur_species->GetUpdateBorn());
    cur_species = cur_species->GetNext();
  }
  garbage_queue.Purge();
}

Index: avida/current/source/main/species_control.hh
+++ avida/current/source/main/species_control.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef SPECIES_CONTROL_HH
#define SPECIES_CONTROL_HH

#ifndef SPECIES_QUEUE_HH
#include "species_queue.hh"
#endif

class cGenebank;
class cGenotype;
class cSpecies;
class cStats;
class cSpeciesControl {
private:
  cSpeciesQueue active_queue;
  cSpeciesQueue inactive_queue;
  cSpeciesQueue garbage_queue;
  cGenebank & genebank;
public:
  cSpeciesControl(cGenebank & in_gb);
  ~cSpeciesControl();

  void Remove(cSpecies & in_species);
  void Adjust(cSpecies & in_species);
  void SetInactive(cSpecies & in_species);
  void SetActive(cSpecies & in_species);
  void SetGarbage(cSpecies & in_species);
  void Purge(cStats & stats);

  bool OK();

  int FindPos(cSpecies & in_species, int max_depth = -1);
  cSpecies * Find(cGenotype & in_genotype, int record_level);

  inline cSpecies * GetFirst() const { return active_queue.GetFirst(); }
  inline cSpecies * GetFirstInactive() const
    { return inactive_queue.GetFirst(); }
  inline cSpecies * GetFirstGarbage() const
    { return garbage_queue.GetFirst(); }
  inline int GetSize() const { return active_queue.GetSize(); }
  inline int GetInactiveSize() const { return inactive_queue.GetSize(); }
};

#endif

Index: avida/current/source/main/species_queue.cc
+++ avida/current/source/main/species_queue.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef SPECIES_QUEUE_HH
#include "species_queue.hh"
#endif

#ifndef DEFS_HH
#include "defs.hh"
#endif
#ifndef SPECIES_HH
#include "species.hh"
#endif

///////////////////
//  cSpeciesQueue
///////////////////

cSpeciesQueue::cSpeciesQueue()
{
  size = 0;
  first = NULL;
}

cSpeciesQueue::~cSpeciesQueue()
{
}

void cSpeciesQueue::InsertRear(cSpecies & new_species)
{
  // If the queue doesn't exist, create it with this species as the only
  // element.

  if (!first) {
    first = &new_species;
    first->SetNext(first);
    first->SetPrev(first);
  }

  // Otherwise, put this species at the end of the queue.

  else {
    new_species.SetNext(first);
    new_species.SetPrev(first->GetPrev());
    first->GetPrev()->SetNext(&new_species);
    first->SetPrev(&new_species);
  }

  size++;
}

void cSpeciesQueue::Remove(cSpecies & in_species)
{
  size--;

  // If the queue is now empty, delete it properly.
  if (size == 0) {
    first = NULL;
    return;
  }

  // If we are removing the first element of the queue, slide the queue to
  // the new first before removing it.

  if (first == &in_species) {
    first = in_species.GetNext();
  }

  // Remove the in_species

  in_species.GetPrev()->SetNext(in_species.GetNext());
  in_species.GetNext()->SetPrev(in_species.GetPrev());
  in_species.SetNext(NULL);
  in_species.SetPrev(NULL);
}

void cSpeciesQueue::Adjust(cSpecies & in_species)
{
  // First move it up the list if need be...

  cSpecies * prev_species = in_species.GetPrev();
  while (&in_species != first &&
	 in_species.GetNumThreshold() > prev_species->GetNumThreshold()) {
    // Swap the position of this species with the previous one.
    if (prev_species == first) first = &in_species;

    // Outer connections...
    prev_species->SetNext(in_species.GetNext());
    in_species.GetNext()->SetPrev(prev_species);
    in_species.SetPrev(prev_species->GetPrev());
    prev_species->GetPrev()->SetNext(&in_species);

    // Inner connections...
    prev_species->SetPrev(&in_species);
    in_species.SetNext(prev_species);

    prev_species = in_species.GetPrev();
  }
	
  // Then see if it needs to be moved down.
  cSpecies * next_species = in_species.GetNext();
  while (next_species != first &&
	 in_species.GetNumThreshold() < next_species->GetNumThreshold()) {
    // Swap the position of this species with the next one.
    if (&in_species == first) first = next_species;

    // Outer Connections...
    in_species.SetNext(next_species->GetNext());
    next_species->GetNext()->SetPrev(&in_species);
    next_species->SetPrev(in_species.GetPrev());
    in_species.GetPrev()->SetNext(next_species);

    // Inner Connections...
    in_species.SetPrev(next_species);
    next_species->SetNext(&in_species);

    next_species = in_species.GetNext();
  }
}

void cSpeciesQueue::Purge()
{
  cSpecies * cur_species = first;
  cSpecies * next_species = NULL;

  // Loop through the species deleting them until there is only one left.
  for (int i = 1; i < size; i++) {
    next_species = cur_species->GetNext();
    delete cur_species;
    cur_species = next_species;
  }

  // And delete that last one.
  delete cur_species;
  first = NULL;
  size = 0;
}

bool cSpeciesQueue::OK(int queue_type)
{
  cSpecies * cur_species = NULL;
  int count = 0;
  bool ret_value = true;

  while (first && cur_species != first) {
    // If we are just starting, set cur_species to the first element.
    if (!cur_species) cur_species = first;

    // Check that the list is correct in both directions...

    assert (cur_species->GetNext()->GetPrev() == cur_species);

    // Check to make sure the current species is OK() and that it should
    // indeed be in this list.

    if (!cur_species->OK()) ret_value = false;

    assert (queue_type == cur_species->GetQueueType());
    count++;

    assert (count <= size);

    cur_species = cur_species->GetNext();
  }

  assert (count == size);

  return ret_value;
}

Index: avida/current/source/main/species_queue.hh
+++ avida/current/source/main/species_queue.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef SPECIES_QUEUE_HH
#define SPECIES_QUEUE_HH

class cSpecies;
class cSpeciesQueue {
private:
  int size;
  cSpecies * first;
public:
  cSpeciesQueue();
  ~cSpeciesQueue();

  void InsertRear(cSpecies & new_species);
  void Remove(cSpecies & in_species);
  void Adjust(cSpecies & in_species);
  void Purge();
  bool OK(int queue_type);

  inline int GetSize() const { return size; }
  inline cSpecies * GetFirst() const { return first; }
};

#endif

Index: avida/current/source/main/task_entry.cc
+++ avida/current/source/main/task_entry.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef TASK_ENTRY_HH
#include "task_entry.hh"
#endif

////////////////
//  cTaskEntry
////////////////

cTaskEntry::cTaskEntry(const cString & _name, const cString & _desc,
		       int _id, tTaskTest _test_fun)
  : name(_name)
  , desc(_desc)
  , id(_id)
  , test_fun(_test_fun)
{
}

cTaskEntry::~cTaskEntry()
{
}

Index: avida/current/source/main/task_entry.hh
+++ avida/current/source/main/task_entry.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef TASK_ENTRY_HH
#define TASK_ENTRY_HH

#ifndef STRING_HH
#include "string.hh"
#endif
#ifndef TASK_LIB_HH
#include "task_lib.hh"
#endif

class cTaskEntry {
private:
  cString name;  // Short keyword for task
  cString desc;  // For more human-understandable output...
  int id;
  tTaskTest test_fun;
public:
  cTaskEntry(const cString & _name, const cString & _desc, int _id,
	     tTaskTest _test_fun);
  ~cTaskEntry();

  const cString & GetName()    const { return name; }
  const cString & GetDesc() const { return desc; }
  const int       GetID()      const { return id; }
  const tTaskTest GetTestFun() const { return test_fun; }
};

#endif

Index: avida/current/source/main/task_lib.cc
+++ avida/current/source/main/task_lib.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef TASK_LIB_HH
#include "task_lib.hh"
#endif

#ifndef TASK_ENTRY_HH
#include "task_entry.hh"
#endif

using namespace std;

////////////////////////
//  cTaskLib (public)
////////////////////////

cTaskLib::cTaskLib()
  : input_buffer(3)
  , output_buffer(3)
{
}

cTaskLib::~cTaskLib()
{
  for (int i = 0; i < task_array.GetSize(); i++) {
    delete task_array[i];
  }
}

cTaskEntry * cTaskLib::AddTask(const cString & name)
{
  // Determine if this task is already in the active library.
  for (int i = 0; i < task_array.GetSize(); i++) {
    if (task_array[i]->GetName() == name) {
      assert(task_array[i] != NULL);
      return task_array[i];
    }
  }

  // Match up this name to its corresponding task
  const int start_size = task_array.GetSize();

  if (name == "echo")      NewTask(name, "Echo", &cTaskLib::Task_Echo);
  else if (name == "add")  NewTask(name, "Add",  &cTaskLib::Task_Add);
  else if (name == "sub")  NewTask(name, "Sub",  &cTaskLib::Task_Sub);

  else if (name == "not")   NewTask(name, "Not",    &cTaskLib::Task_Not);
  else if (name == "nand")  NewTask(name, "Nand",   &cTaskLib::Task_Nand);
  else if (name == "and")   NewTask(name, "And",    &cTaskLib::Task_And);
  else if (name == "orn")   NewTask(name, "OrNot",  &cTaskLib::Task_OrNot);
  else if (name == "or")    NewTask(name, "Or",     &cTaskLib::Task_Or);
  else if (name == "andn")  NewTask(name, "AndNot", &cTaskLib::Task_AndNot);
  else if (name == "nor")   NewTask(name, "Nor",    &cTaskLib::Task_Nor);
  else if (name == "xor")   NewTask(name, "Xor",    &cTaskLib::Task_Xor);
  else if (name == "equ")   NewTask(name, "Equals", &cTaskLib::Task_Equ);

  else if (name == "logic_3AA")
    NewTask(name, "Logic 3AA (A+B+C == 0)", &cTaskLib::Task_Logic3in_AA);
  else if (name == "logic_3AB")
    NewTask(name, "Logic 3AB (A+B+C == 1)", &cTaskLib::Task_Logic3in_AB);
  else if (name == "logic_3AC")
    NewTask(name, "Logic 3AC (A+B+C <= 1)", &cTaskLib::Task_Logic3in_AC);
  else if (name == "logic_3AD")
    NewTask(name, "Logic 3AD (A+B+C == 2)", &cTaskLib::Task_Logic3in_AD);
  else if (name == "logic_3AE")
    NewTask(name, "Logic 3AE (A+B+C == 0,2)", &cTaskLib::Task_Logic3in_AE);
  else if (name == "logic_3AF")
    NewTask(name, "Logic 3AF (A+B+C == 1,2)", &cTaskLib::Task_Logic3in_AF);
  else if (name == "logic_3AG")
    NewTask(name, "Logic 3AG (A+B+C <= 2)", &cTaskLib::Task_Logic3in_AG);
  else if (name == "logic_3AH")
    NewTask(name, "Logic 3AH (A+B+C == 3)", &cTaskLib::Task_Logic3in_AH);
  else if (name == "logic_3AI")
    NewTask(name, "Logic 3AI (A+B+C == 0,3)", &cTaskLib::Task_Logic3in_AI);
  else if (name == "logic_3AJ")
    NewTask(name, "Logic 3AJ (A+B+C == 1,3) XOR", &cTaskLib::Task_Logic3in_AJ);
  else if (name == "logic_3AK")
    NewTask(name, "Logic 3AK (A+B+C != 2)", &cTaskLib::Task_Logic3in_AK);
  else if (name == "logic_3AL")
    NewTask(name, "Logic 3AL (A+B+C >= 2)", &cTaskLib::Task_Logic3in_AL);
  else if (name == "logic_3AM")
    NewTask(name, "Logic 3AM (A+B+C != 1)", &cTaskLib::Task_Logic3in_AM);
  else if (name == "logic_3AN")
    NewTask(name, "Logic 3AN (A+B+C != 0)", &cTaskLib::Task_Logic3in_AN);
  else if (name == "logic_3AO")
    NewTask(name, "Logic 3AO (A & ~B & ~C) [3]", &cTaskLib::Task_Logic3in_AO);
  else if (name == "logic_3AP")
    NewTask(name, "Logic 3AP (A^B & ~C)  [3]", &cTaskLib::Task_Logic3in_AP);
  else if (name == "logic_3AQ")
    NewTask(name, "Logic 3AQ (A==B & ~C) [3]", &cTaskLib::Task_Logic3in_AQ);
  else if (name == "logic_3AR")
    NewTask(name, "Logic 3AR (A & B & ~C) [3]", &cTaskLib::Task_Logic3in_AR);
  else if (name == "logic_3AS")
    NewTask(name, "Logic 3AS", &cTaskLib::Task_Logic3in_AS);
  else if (name == "logic_3AT")
    NewTask(name, "Logic 3AT", &cTaskLib::Task_Logic3in_AT);
  else if (name == "logic_3AU")
    NewTask(name, "Logic 3AU", &cTaskLib::Task_Logic3in_AU);
  else if (name == "logic_3AV")
    NewTask(name, "Logic 3AV", &cTaskLib::Task_Logic3in_AV);
  else if (name == "logic_3AW")
    NewTask(name, "Logic 3AW", &cTaskLib::Task_Logic3in_AW);
  else if (name == "logic_3AX")
    NewTask(name, "Logic 3AX", &cTaskLib::Task_Logic3in_AX);
  else if (name == "logic_3AY")
    NewTask(name, "Logic 3AY", &cTaskLib::Task_Logic3in_AY);
  else if (name == "logic_3AZ")
    NewTask(name, "Logic 3AZ", &cTaskLib::Task_Logic3in_AZ);
  else if (name == "logic_3BA")
    NewTask(name, "Logic 3BA", &cTaskLib::Task_Logic3in_BA);
  else if (name == "logic_3BB")
    NewTask(name, "Logic 3BB", &cTaskLib::Task_Logic3in_BB);
  else if (name == "logic_3BC")
    NewTask(name, "Logic 3BC", &cTaskLib::Task_Logic3in_BC);
  else if (name == "logic_3BD")
    NewTask(name, "Logic 3BD", &cTaskLib::Task_Logic3in_BD);
  else if (name == "logic_3BE")
    NewTask(name, "Logic 3BE", &cTaskLib::Task_Logic3in_BE);
  else if (name == "logic_3BF")
    NewTask(name, "Logic 3BF", &cTaskLib::Task_Logic3in_BF);
  else if (name == "logic_3BG")
    NewTask(name, "Logic 3BG", &cTaskLib::Task_Logic3in_BG);
  else if (name == "logic_3BH")
    NewTask(name, "Logic 3BH", &cTaskLib::Task_Logic3in_BH);
  else if (name == "logic_3BI")
    NewTask(name, "Logic 3BI", &cTaskLib::Task_Logic3in_BI);
  else if (name == "logic_3BJ")
    NewTask(name, "Logic 3BJ", &cTaskLib::Task_Logic3in_BJ);
  else if (name == "logic_3BK")
    NewTask(name, "Logic 3BK", &cTaskLib::Task_Logic3in_BK);
  else if (name == "logic_3BL")
    NewTask(name, "Logic 3BL", &cTaskLib::Task_Logic3in_BL);
  else if (name == "logic_3BM")
    NewTask(name, "Logic 3BM", &cTaskLib::Task_Logic3in_BM);
  else if (name == "logic_3BN")
    NewTask(name, "Logic 3BN", &cTaskLib::Task_Logic3in_BN);
  else if (name == "logic_3BO")
    NewTask(name, "Logic 3BO", &cTaskLib::Task_Logic3in_BO);
  else if (name == "logic_3BP")
    NewTask(name, "Logic 3BP", &cTaskLib::Task_Logic3in_BP);
  else if (name == "logic_3BQ")
    NewTask(name, "Logic 3BQ", &cTaskLib::Task_Logic3in_BQ);
  else if (name == "logic_3BR")
    NewTask(name, "Logic 3BR", &cTaskLib::Task_Logic3in_BR);
  else if (name == "logic_3BS")
    NewTask(name, "Logic 3BS", &cTaskLib::Task_Logic3in_BS);
  else if (name == "logic_3BT")
    NewTask(name, "Logic 3BT", &cTaskLib::Task_Logic3in_BT);
  else if (name == "logic_3BU")
    NewTask(name, "Logic 3BU", &cTaskLib::Task_Logic3in_BU);
  else if (name == "logic_3BV")
    NewTask(name, "Logic 3BV", &cTaskLib::Task_Logic3in_BV);
  else if (name == "logic_3BW")
    NewTask(name, "Logic 3BW", &cTaskLib::Task_Logic3in_BW);
  else if (name == "logic_3BX")
    NewTask(name, "Logic 3BX", &cTaskLib::Task_Logic3in_BX);
  else if (name == "logic_3BY")
    NewTask(name, "Logic 3BY", &cTaskLib::Task_Logic3in_BY);
  else if (name == "logic_3BZ")
    NewTask(name, "Logic 3BZ", &cTaskLib::Task_Logic3in_BZ);
  else if (name == "logic_3CA")
    NewTask(name, "Logic 3CA", &cTaskLib::Task_Logic3in_CA);
  else if (name == "logic_3CB")
    NewTask(name, "Logic 3CB", &cTaskLib::Task_Logic3in_CB);
  else if (name == "logic_3CC")
    NewTask(name, "Logic 3CC", &cTaskLib::Task_Logic3in_CC);
  else if (name == "logic_3CD")
    NewTask(name, "Logic 3CD", &cTaskLib::Task_Logic3in_CD);
  else if (name == "logic_3CE")
    NewTask(name, "Logic 3CE", &cTaskLib::Task_Logic3in_CE);
  else if (name == "logic_3CF")
    NewTask(name, "Logic 3CF", &cTaskLib::Task_Logic3in_CF);
  else if (name == "logic_3CG")
    NewTask(name, "Logic 3CG", &cTaskLib::Task_Logic3in_CG);
  else if (name == "logic_3CH")
    NewTask(name, "Logic 3CH", &cTaskLib::Task_Logic3in_CH);
  else if (name == "logic_3CI")
    NewTask(name, "Logic 3CI", &cTaskLib::Task_Logic3in_CI);
  else if (name == "logic_3CJ")
    NewTask(name, "Logic 3CJ", &cTaskLib::Task_Logic3in_CJ);
  else if (name == "logic_3CK")
    NewTask(name, "Logic 3CK", &cTaskLib::Task_Logic3in_CK);
  else if (name == "logic_3CL")
    NewTask(name, "Logic 3CL", &cTaskLib::Task_Logic3in_CL);
  else if (name == "logic_3CM")
    NewTask(name, "Logic 3CM", &cTaskLib::Task_Logic3in_CM);
  else if (name == "logic_3CN")
    NewTask(name, "Logic 3CN", &cTaskLib::Task_Logic3in_CN);
  else if (name == "logic_3CO")
    NewTask(name, "Logic 3CO", &cTaskLib::Task_Logic3in_CO);
  else if (name == "logic_3CP")
    NewTask(name, "Logic 3CP", &cTaskLib::Task_Logic3in_CP);

  else if (name == "math_1AA")
    NewTask(name, "Math 1AA (2X)", &cTaskLib::Task_Math1in_AA);
  else if (name == "math_1AB")
    NewTask(name, "Math 1AB (2X/3)", &cTaskLib::Task_Math1in_AB);  
  else if (name == "math_1AC")
    NewTask(name, "Math 1AC (5X/4)", &cTaskLib::Task_Math1in_AC);  
  else if (name == "math_1AD")
    NewTask(name, "Math 1AD (X^2)", &cTaskLib::Task_Math1in_AD);  
  else if (name == "math_1AE")
    NewTask(name, "Math 1AE (X^3)", &cTaskLib::Task_Math1in_AE);  
  else if (name == "math_1AF")
    NewTask(name, "Math 1AF (sqrt(X))", &cTaskLib::Task_Math1in_AF);  
  else if (name == "math_1AG")
    NewTask(name, "Math 1AG (log(X))", &cTaskLib::Task_Math1in_AG);  
  else if (name == "math_1AH")
    NewTask(name, "Math 1AH (X^2+X^3)", &cTaskLib::Task_Math1in_AH);  
  else if (name == "math_1AI")
    NewTask(name, "Math 1AI (X^2+sqrt(X))", &cTaskLib::Task_Math1in_AI);  
  else if (name == "math_1AJ")
    NewTask(name, "Math 1AJ (abs(X))", &cTaskLib::Task_Math1in_AJ);  
  else if (name == "math_1AK")
    NewTask(name, "Math 1AK (X-5)", &cTaskLib::Task_Math1in_AK);  
  else if (name == "math_1AL")
    NewTask(name, "Math 1AL (-X)", &cTaskLib::Task_Math1in_AL);  
  else if (name == "math_1AM")
    NewTask(name, "Math 1AM (5X)", &cTaskLib::Task_Math1in_AM);  
  else if (name == "math_1AN")
    NewTask(name, "Math 1AN (X/4)", &cTaskLib::Task_Math1in_AN);  
  else if (name == "math_1AO")
    NewTask(name, "Math 1AO (X-6)", &cTaskLib::Task_Math1in_AO);  
  else if (name == "math_1AP")
    NewTask(name, "Math 1AP (X-7)", &cTaskLib::Task_Math1in_AP);  

  else if (name == "math_2AA")
    NewTask(name, "Math 2AA (sqrt(X+Y))", &cTaskLib::Task_Math2in_AA);  
  else if (name == "math_2AB")
    NewTask(name, "Math 2AB ((X+Y)^2)", &cTaskLib::Task_Math2in_AB);  
  else if (name == "math_2AC")
    NewTask(name, "Math 2AC (X%Y)", &cTaskLib::Task_Math2in_AC);  
  else if (name == "math_2AD")
    NewTask(name, "Math 2AD (3X/2+5X/4)", &cTaskLib::Task_Math2in_AD);  
  else if (name == "math_2AE")
    NewTask(name, "Math 2AE (abs(X-5)+abs(Y-6))", &cTaskLib::Task_Math2in_AE);  
  else if (name == "math_2AF")
    NewTask(name, "Math 2AF (XY-X/Y)", &cTaskLib::Task_Math2in_AF);  
  else if (name == "math_2AG")
    NewTask(name, "Math 2AG ((X-Y)^2)", &cTaskLib::Task_Math2in_AG);  
  else if (name == "math_2AH")
    NewTask(name, "Math 2AH (X^2+Y^2)", &cTaskLib::Task_Math2in_AH);  
  else if (name == "math_2AI")
    NewTask(name, "Math 2AI (X^2+Y^3)", &cTaskLib::Task_Math2in_AI);
  else if (name == "math_2AJ")
    NewTask(name, "Math 2AJ ((sqrt(X)+Y)/(X-7))", &cTaskLib::Task_Math2in_AJ);
  else if (name == "math_2AK")
    NewTask(name, "Math 2AK (log(|X/Y|))", &cTaskLib::Task_Math2in_AK);
  else if (name == "math_2AL")
    NewTask(name, "Math 2AL (log(|X|)/Y)", &cTaskLib::Task_Math2in_AL);
  else if (name == "math_2AM")
    NewTask(name, "Math 2AM (X/log(|Y|))", &cTaskLib::Task_Math2in_AM);
  else if (name == "math_2AN")
    NewTask(name, "Math 2AN (X+Y)", &cTaskLib::Task_Math2in_AN);
  else if (name == "math_2AO")
    NewTask(name, "Math 2AO (X-Y)", &cTaskLib::Task_Math2in_AO);
  else if (name == "math_2AP")
    NewTask(name, "Math 2AP (X/Y)", &cTaskLib::Task_Math2in_AP);
  else if (name == "math_2AQ")
    NewTask(name, "Math 2AQ (XY)", &cTaskLib::Task_Math2in_AQ);
  else if (name == "math_2AR")
    NewTask(name, "Math 2AR (sqrt(X)+sqrt(Y))", &cTaskLib::Task_Math2in_AR);
  else if (name == "math_2AS")
    NewTask(name, "Math 2AS (X+2Y)", &cTaskLib::Task_Math2in_AS);
  else if (name == "math_2AT")
    NewTask(name, "Math 2AT (X+3Y)", &cTaskLib::Task_Math2in_AT);
  else if (name == "math_2AU")
    NewTask(name, "Math 2AU (2X+3Y)", &cTaskLib::Task_Math2in_AU);
  else if (name == "math_2AV")
    NewTask(name, "Math 2AV (XY^2)", &cTaskLib::Task_Math2in_AV);

  else if (name == "math_3AA")
    NewTask(name, "Math 3AA (X^2+Y^2+Z^2)", &cTaskLib::Task_Math3in_AA);  
  else if (name == "math_3AB")
    NewTask(name, "Math 3AB (sqrt(X)+sqrt(Y)+sqrt(Z))", &cTaskLib::Task_Math3in_AB);  
  else if (name == "math_3AC")
    NewTask(name, "Math 3AC (X+2Y+3Z)", &cTaskLib::Task_Math3in_AC);  
  /*
  Visual Studio.net 2003 gives compiler error:
    fatal error C1061: compiler limit : blocks nested too deeply
  Sherri fixed this by removing the 'else' in the next line.
  -- K
  */
  //else if (name == "math_3AD")
  //  NewTask(name, "Math 3AD (XY^2+Z^3)", &cTaskLib::Task_Math3in_AD); 
  if (name == "math_3AD")
    NewTask(name, "Math 3AD (XY^2+Z^3)", &cTaskLib::Task_Math3in_AD);  
  else if (name == "math_3AE")
    NewTask(name, "Math 3AE ((X%Y)*Z)", &cTaskLib::Task_Math3in_AE);  
  else if (name == "math_3AF")
    NewTask(name, "Math 3AF ((X+Y)^2+sqrt(Y+Z))", &cTaskLib::Task_Math3in_AF);
  else if (name == "math_3AG")
    NewTask(name, "Math 3AG ((XY)%(YZ))", &cTaskLib::Task_Math3in_AG);  
  else if (name == "math_3AH")
    NewTask(name, "Math 3AH (X+Y+Z)", &cTaskLib::Task_Math3in_AH);  
  else if (name == "math_3AI")
    NewTask(name, "Math 3AI (-X-Y-Z)", &cTaskLib::Task_Math3in_AI);  
  else if (name == "math_3AJ")
    NewTask(name, "Math 3AJ ((X-Y)^2+(Y-Z)^2+(Z-X)^2)", &cTaskLib::Task_Math3in_AJ);  
  else if (name == "math_3AK")
    NewTask(name, "Math 3AK ((X+Y)^2+(Y+Z)^2+(Z+X)^2)", &cTaskLib::Task_Math3in_AK);  
  else if (name == "math_3AL")
    NewTask(name, "Math 3AL ((X-Y)^2+(X-Z)^2)", &cTaskLib::Task_Math3in_AL);  
  else if (name == "math_3AM")
    NewTask(name, "Math 3AM ((X+Y)^2+(Y+Z)^2)", &cTaskLib::Task_Math3in_AM);  
    
 // Make sure we have actuall found a task.

  if (task_array.GetSize() == start_size) {
    cerr << "Unknown task entry '" << name << "'." << endl;
    return NULL;
  }

  // And return the found task.
  return task_array[start_size];
}

const cTaskEntry & cTaskLib::GetTask(int id) const
{
  return *(task_array[id]);
}
  
void cTaskLib::SetupTests(const tBuffer<int> & inputs,
			  const tBuffer<int> & outputs) const
{
  input_buffer = inputs;
  output_buffer = outputs;
  SetupLogicTests(inputs, outputs);
}

void cTaskLib::SetupLogicTests(const tBuffer<int> & inputs,
			       const tBuffer<int> & outputs) const
{
  // Collect the inputs in a useful form.
  const int num_inputs = input_buffer.GetNumStored();
  int test_inputs[3];
  for (int i = 0; i < 3; i++) {
    test_inputs[i] = (num_inputs > i) ? input_buffer[i] : 0;
  }
  int test_output = output_buffer[0];


  // Setup logic_out to test the output for each logical combination...
  // Assuming each bit in logic out to be based on the inputs:
  //
  //  Logic ID Bit: 7 6 5 4 3 2 1 0
  //       Input C: 1 1 1 1 0 0 0 0
  //       Input B: 1 1 0 0 1 1 0 0
  //       Input A: 1 0 1 0 1 0 1 0

  tArray<int> logic_out(8);
  logic_out.SetAll(-1);
 
  // Test all input combos!
  bool func_OK = true;  // Have all outputs been consistant?
  for (int test_pos = 0; test_pos < 32; test_pos++) {
    int logic_pos = 0;
    for (int i = 0; i < 3; i++)  logic_pos += (test_inputs[i] & 1) << i;

    if ( logic_out[logic_pos] != -1 &&
	 logic_out[logic_pos] != (test_output & 1) ) {
      func_OK = false;
      break;
    }
    else {
      logic_out[logic_pos] = test_output & 1;
    }
    
    test_output >>= 1;
    for (int i = 0; i < 3; i++) test_inputs[i] >>= 1;
  }

  // If there were any inconsistancies, deal with them.
  if (func_OK == false) {
    logic_id = -1;
    return;
  }

  // Determine the logic ID number of this task.
  if (num_inputs < 1) {  // 000 -> 001
    logic_out[1] = logic_out[0];
  }
  if (num_inputs < 2) { // 000 -> 010; 001 -> 011
    logic_out[2] = logic_out[0];
    logic_out[3] = logic_out[1];
  }
  if (num_inputs < 3) { // 000->100;  001->101;  010->110;  011->111
    logic_out[4] = logic_out[0];
    logic_out[5] = logic_out[1];
    logic_out[6] = logic_out[2];
    logic_out[7] = logic_out[3];
  }

  // Lets just make sure we've gotten this correct...
  assert(logic_out[0] >= 0 && logic_out[0] <= 1);
  assert(logic_out[1] >= 0 && logic_out[1] <= 1);
  assert(logic_out[2] >= 0 && logic_out[2] <= 1);
  assert(logic_out[3] >= 0 && logic_out[3] <= 1);
  assert(logic_out[4] >= 0 && logic_out[4] <= 1);
  assert(logic_out[5] >= 0 && logic_out[5] <= 1);
  assert(logic_out[6] >= 0 && logic_out[6] <= 1);
  assert(logic_out[7] >= 0 && logic_out[7] <= 1);

  logic_id = 0;
  for (int i = 0; i < 8; i++) logic_id += logic_out[i] << i;
}


double cTaskLib::TestOutput(const cTaskEntry & task) const
{
  tTaskTest test_fun = task.GetTestFun();
  return (this->*test_fun)();
}


////////////////////////
//  cTaskLib (private)
////////////////////////

void cTaskLib::NewTask(const cString & name, const cString & desc,
		       tTaskTest task_fun)
{
  const int id = task_array.GetSize();
  task_array.Resize(id+1);
  task_array[id] = new cTaskEntry(name, desc, id, task_fun);
}


double cTaskLib::Task_Echo() const
{
  const int test_output = output_buffer[0];
  for (int i = 0; i < input_buffer.GetNumStored(); i++) {
    if (input_buffer[i] == test_output) {
      assert(logic_id == 170 || logic_id == 204 || logic_id == 240);
      return 1.0;
    }
  }
  return 0.0;
}


double cTaskLib::Task_Add() const
{
  const int test_output = output_buffer[0];
  for (int i = 0; i < input_buffer.GetNumStored(); i++) {
    for (int j = 0; j < i; j++) {
      if (test_output == input_buffer[i] + input_buffer[j]) return 1.0;
    }
  }
  return 0.0;
}


double cTaskLib::Task_Sub() const
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i++) {
    for (int j = 0; j < input_size; j++) {
      if (i == j) continue;
      if (test_output == input_buffer[i] - input_buffer[j]) return 1.0;
    }
  }
  return 0.0;
}

double cTaskLib::Task_Not() const
{
  if (logic_id == 15 || logic_id == 51 || logic_id == 85) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Nand() const
{
  if (logic_id == 63 || logic_id == 95 || logic_id == 119) return 1.0;
  return 0.0;
}

double cTaskLib::Task_And() const
{
  if (logic_id == 136 || logic_id == 160 || logic_id == 192) return 1.0;
  return 0.0;
}

double cTaskLib::Task_OrNot() const
{
  if (logic_id == 175 || logic_id == 187 || logic_id == 207 ||
      logic_id == 221 || logic_id == 243 || logic_id == 245) return 1.0;

  return 0.0;
}

double cTaskLib::Task_Or() const
{
  if (logic_id == 238 || logic_id == 250 || logic_id == 252) return 1.0;
  return 0.0;
}

double cTaskLib::Task_AndNot() const
{
  if (logic_id == 10 || logic_id == 12 || logic_id == 34 ||
      logic_id == 48 || logic_id == 68 || logic_id == 80) return 1.0;

  return 0.0;
}

double cTaskLib::Task_Nor() const
{
  if (logic_id == 3 || logic_id == 5 || logic_id == 17) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Xor() const
{
  if (logic_id == 60 || logic_id == 90 || logic_id == 102) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Equ() const
{
  if (logic_id == 153 || logic_id == 165 || logic_id == 195) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AA() const
{
  if (logic_id == 1) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AB() const
{
  if (logic_id == 22) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AC() const
{
  if (logic_id == 23) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AD() const
{
  if (logic_id == 104) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AE() const
{
  if (logic_id == 105) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AF() const
{
  if (logic_id == 126) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AG() const
{
  if (logic_id == 127) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AH() const
{
  if (logic_id == 128) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AI() const
{
  if (logic_id == 129) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AJ() const
{
  if (logic_id == 150) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AK() const
{
  if (logic_id == 151) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AL() const
{
  if (logic_id == 232) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AM() const
{
  if (logic_id == 233) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AN() const
{
  if (logic_id == 254) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AO() const
{
  if (logic_id == 2 || logic_id == 4 || logic_id == 16) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AP() const
{
  if (logic_id == 6 || logic_id == 18 || logic_id == 20) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AQ() const
{
  if (logic_id == 7 || logic_id == 19 || logic_id == 21) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AR() const
{
  if (logic_id == 8 || logic_id == 32 || logic_id == 64) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AS() const
{
  if (logic_id == 9 || logic_id == 33 || logic_id == 65) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AT() const
{
  if (logic_id == 14 || logic_id == 50 || logic_id == 84) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AU() const
{
  if (logic_id == 24 || logic_id == 36 || logic_id == 66) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AV() const
{
  if (logic_id == 25 || logic_id == 37 || logic_id == 67) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AW() const
{
  if (logic_id == 30 || logic_id == 54 || logic_id == 86) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AX() const
{
  if (logic_id == 31 || logic_id == 55 || logic_id == 87) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AY() const
{
  if (logic_id == 40 || logic_id == 72 || logic_id == 96) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_AZ() const
{
  if (logic_id == 41 || logic_id == 73 || logic_id == 97) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BA() const
{
  if (logic_id == 42 || logic_id == 76 || logic_id == 112) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BB() const
{
  if (logic_id == 43 || logic_id == 77 || logic_id == 113) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BC() const
{
  if (logic_id == 61 || logic_id == 91 || logic_id == 103) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BD() const
{
  if (logic_id == 62 || logic_id == 94 || logic_id == 118) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BE() const
{
  if (logic_id == 106 || logic_id == 108 || logic_id == 120) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BF() const
{
  if (logic_id == 107 || logic_id == 109 || logic_id == 121) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BG() const
{
  if (logic_id == 110 || logic_id == 122 || logic_id == 124) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BH() const
{
  if (logic_id == 111 || logic_id == 123 || logic_id == 125) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BI() const
{
  if (logic_id == 130 || logic_id == 132 || logic_id == 144) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BJ() const
{
  if (logic_id == 131 || logic_id == 133 || logic_id == 145) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BK() const
{
  if (logic_id == 134 || logic_id == 146 || logic_id == 148) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BL() const
{
  if (logic_id == 135 || logic_id == 147 || logic_id == 149) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BM() const
{
  if (logic_id == 137 || logic_id == 161 || logic_id == 193) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BN() const
{
  if (logic_id == 142 || logic_id == 178 || logic_id == 212) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BO() const
{
  if (logic_id == 143 || logic_id == 179 || logic_id == 213) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BP() const
{
  if (logic_id == 152 || logic_id == 164 || logic_id == 194) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BQ() const
{
  if (logic_id == 158 || logic_id == 182 || logic_id == 214) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BR() const
{
  if (logic_id == 159 || logic_id == 183 || logic_id == 215) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BS() const
{
  if (logic_id == 168 || logic_id == 200 || logic_id == 224) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BT() const
{
  if (logic_id == 169 || logic_id == 201 || logic_id == 225) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BU() const
{
  if (logic_id == 171 || logic_id == 205 || logic_id == 241) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BV() const
{
  if (logic_id == 188 || logic_id == 218 || logic_id == 230) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BW() const
{
  if (logic_id == 189 || logic_id == 219 || logic_id == 231) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BX() const
{
  if (logic_id == 190 || logic_id == 222 || logic_id == 246) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BY() const
{
  if (logic_id == 191 || logic_id == 223 || logic_id == 247) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_BZ() const
{
  if (logic_id == 234 || logic_id == 236 || logic_id == 248) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_CA() const
{
  if (logic_id == 235 || logic_id == 237 || logic_id == 249) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_CB() const
{
  if (logic_id == 239 || logic_id == 251 || logic_id == 253) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_CC() const
{
  if (logic_id == 11 || logic_id == 13 || logic_id == 35 ||
      logic_id == 49 || logic_id == 69 || logic_id == 81) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_CD() const
{
  if (logic_id == 26 || logic_id == 28 || logic_id == 38 ||
      logic_id == 52 || logic_id == 70 || logic_id == 82) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_CE() const
{
  if (logic_id == 27 || logic_id == 29 || logic_id == 39 ||
      logic_id == 53 || logic_id == 71 || logic_id == 83) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_CF() const
{
  if (logic_id == 44 || logic_id == 56 || logic_id == 74 ||
      logic_id == 88 || logic_id == 98 || logic_id == 100) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_CG() const
{
  if (logic_id == 45 || logic_id == 57 || logic_id == 75 ||
      logic_id == 89 || logic_id == 99 || logic_id == 101) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_CH() const
{
  if (logic_id == 46 || logic_id == 58 || logic_id == 78 ||
      logic_id == 92 || logic_id == 114 || logic_id == 116) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_CI() const
{
  if (logic_id == 47 || logic_id == 59 || logic_id == 79 ||
      logic_id == 93 || logic_id == 115 || logic_id == 117) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_CJ() const
{
  if (logic_id == 138 || logic_id == 140 || logic_id == 162 ||
      logic_id == 176 || logic_id == 196 || logic_id == 208) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_CK() const
{
  if (logic_id == 139 || logic_id == 141 || logic_id == 163 ||
      logic_id == 177 || logic_id == 197 || logic_id == 209) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_CL() const
{
  if (logic_id == 154 || logic_id == 156 || logic_id == 166 ||
      logic_id == 180 || logic_id == 198 || logic_id == 210) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_CM() const
{
  if (logic_id == 155 || logic_id == 157 || logic_id == 167 ||
      logic_id == 181 || logic_id == 199 || logic_id == 211) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_CN() const
{
  if (logic_id == 172 || logic_id == 184 || logic_id == 202 ||
      logic_id == 216 || logic_id == 226 || logic_id == 228) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_CO() const
{
  if (logic_id == 173 || logic_id == 185 || logic_id == 203 ||
      logic_id == 217 || logic_id == 227 || logic_id == 229) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Logic3in_CP() const
{
  if (logic_id == 174 || logic_id == 186 || logic_id == 206 ||
      logic_id == 220 || logic_id == 242 || logic_id == 244) return 1.0;
  return 0.0;
}

double cTaskLib::Task_Math1in_AA() const //(2X)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i++) {
    if (test_output == 2 * input_buffer[i]) return 1.0;
  }
  return 0.0; 
}

double cTaskLib::Task_Math1in_AB() const //(2X/3)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    if (test_output == 2 * input_buffer[i] / 3) return 1.0;
  }
  return 0.0;
}

double cTaskLib::Task_Math1in_AC() const //(5X/4)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    if (test_output == 5 * input_buffer[i] / 4) return 1.0;
  }
  return 0.0;
}

double cTaskLib::Task_Math1in_AD() const //(X^2)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    if (test_output == input_buffer[i] * input_buffer[i]) return 1.0;
  }
  return 0.0;
}

double cTaskLib::Task_Math1in_AE() const //(X^3)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    if (test_output == input_buffer[i] * input_buffer[i] * input_buffer[i])
      return 1.0;
  }
  return 0.0;
}

double cTaskLib::Task_Math1in_AF() const //(sqrt(X)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    if (test_output == (int) sqrt((double) abs(input_buffer[i]))) return 1.0;
  }
  return 0.0;
}

double cTaskLib::Task_Math1in_AG() const //(log(X))
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    if (input_buffer[i] <= 0) continue;
    if (test_output == (int) log((double) input_buffer[i])) return 1.0;
  }
  return 0.0;
}

double cTaskLib::Task_Math1in_AH() const //(X^2+X^3)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    if (test_output == input_buffer[i] * input_buffer[i] + input_buffer[i] * input_buffer[i] * input_buffer[i])
      return 1.0;
  }
  return 0.0;
}

double cTaskLib::Task_Math1in_AI() const // (X^2 + sqrt(X))
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    if (test_output == input_buffer[i] * input_buffer[i] + (int) sqrt((double) abs(input_buffer[i]))) 
      return 1.0;
  }
  return 0.0;
}

double cTaskLib::Task_Math1in_AJ() const // abs(X)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    if (test_output == abs(input_buffer[i])) return 1.0;
  }
  return 0.0;
}

double cTaskLib::Task_Math1in_AK() const //(X-5)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    if (test_output == input_buffer[i] - 5) return 1.0;
  }
  return 0.0;
}

double cTaskLib::Task_Math1in_AL() const //(-X)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    if (test_output == 0 - input_buffer[i]) return 1.0;
  }
  return 0.0;
}

double cTaskLib::Task_Math1in_AM() const //(5X)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    if (test_output == 5 * input_buffer[i]) return 1.0;
  }
  return 0.0;
}

double cTaskLib::Task_Math1in_AN() const //(X/4)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    if (test_output == input_buffer[i] / 4) return 1.0;
  }
  return 0.0;
}

double cTaskLib::Task_Math1in_AO() const //(X-6)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    if (test_output == input_buffer[i] - 6) return 1.0;
  }
  return 0.0;
}

double cTaskLib::Task_Math1in_AP() const //(X-7)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    if (test_output == input_buffer[i] - 7) return 1.0;
  }
  return 0.0;
}

double cTaskLib::Task_Math2in_AA() const //(sqrt(X+Y))
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i++) {
    for (int j = 0; j < input_size; j++) {
      if (i == j) continue;
      if (test_output == (int) sqrt((double) abs(input_buffer[i] + input_buffer[j])))
	return 1.0;
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math2in_AB() const  //((X+Y)^2)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i++) {
    for (int j = 0; j < input_size; j++) {
      if (i == j) continue;
      if (test_output == (input_buffer[i] + input_buffer[j]) * 
	  (input_buffer[i] + input_buffer[j])) return 1.0;
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math2in_AC() const //(X%Y)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i++) {
    for (int j = 0; j < input_size; j++) {
      if (i == j) continue;
      if (input_buffer[j] == 0) continue; // mod by zero
      if (test_output == input_buffer[i] % input_buffer[j]) return 1.0;
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math2in_AD() const //(3X/2+5X/4)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i++) {
    for (int j = 0; j < input_size; j++) {
      if (i == j) continue;
      if (test_output == 3 * input_buffer[i] / 2 + 5 * input_buffer[j] / 4)
	return 1.0;
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math2in_AE() const //(abs(X-5)+abs(Y-6))
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i++) {
    for (int j = 0; j < input_size; j++) {
      if (i == j) continue;
      if (test_output == abs(input_buffer[i] - 5) + abs(input_buffer[j] - 6))
	return 1.0;
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math2in_AF() const //(XY-X/Y)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i++) {
    for (int j = 0; j < input_size; j++) {
      if (i == j) continue;
      if (input_buffer[j] == 0) continue;
      if (0-INT_MAX > input_buffer[i] && input_buffer[j] == -1) continue;
      if (test_output == input_buffer[i] * input_buffer[j] - 
	  input_buffer[i] / input_buffer[j]) return 1.0;
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math2in_AG() const //((X-Y)^2)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i++) {
    for (int j = 0; j < input_size; j++) {
      if (i == j) continue;
      if (test_output == (input_buffer[i] - input_buffer[j]) *
	  (input_buffer[i] - input_buffer[j])) return 1.0;
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math2in_AH() const //(X^2+Y^2)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i++) {
    for (int j = 0; j < input_size; j++) {
      if (i == j) continue;
      if (test_output == input_buffer[i] * input_buffer[i] +
	  input_buffer[j] * input_buffer[j]) return 1.0;
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math2in_AI() const //(X^2+Y^3)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i++) {
    for (int j = 0; j < input_size; j++) {
      if (i == j) continue;
      if (test_output == input_buffer[i] * input_buffer[i] + input_buffer[j] * input_buffer[j] * input_buffer[j]) 
	return 1.0;
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math2in_AJ() const //((sqrt(X)+Y)/(X-7))
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i++) {
    for (int j = 0; j < input_size; j++) {
      if (i == j) continue;
      if (input_buffer[i] - 7 == 0) continue;
      if (test_output == ((int) sqrt((double) abs(input_buffer[i])) + input_buffer[j]) / (input_buffer[i] - 7)) return 1.0;
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math2in_AK() const //(log(|X/Y|))
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i++) {
    for (int j = 0; j < input_size; j++) {
      if (i == j || input_buffer[j] == 0 ) continue;
      if (0-INT_MAX > input_buffer[i] && input_buffer[j] == -1) continue;
      if (input_buffer[i] / input_buffer[j] == 0) continue;
      if (test_output == (int) log((double) abs(input_buffer[i] / input_buffer[j])))
	return 1.0;
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math2in_AL() const //(log(|X|)/Y)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i++) {
    for (int j = 0; j < input_size; j++) {
      if (i == j || input_buffer[j] == 0) continue;
      if (test_output == (int) log((double) abs(input_buffer[i])) / input_buffer[j])
	return 1.0;
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math2in_AM() const //(X/log(|Y|))
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i++) {
    for (int j = 0; j < input_size; j++) {
      if (i == j || log((double) abs(input_buffer[j])) == 0) continue;
      if (0-INT_MAX > input_buffer[i] && log((double) abs(input_buffer[j])) == -1) continue;
      if (test_output == input_buffer[i] / (int) log((double) abs(input_buffer[j])))
	return 1.0;
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math2in_AN() const //(X+Y)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i++) {
    for (int j = 0; j < input_size; j++) {
      if (i == j) continue;
      if (test_output == input_buffer[i] + input_buffer[j])
	return 1.0;
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math2in_AO() const //(X-Y)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i++) {
    for (int j = 0; j < input_size; j++) {
      if (i == j) continue;
      if (test_output == input_buffer[i] - input_buffer[j])
	return 1.0;
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math2in_AP() const //(X/Y)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i++) {
    for (int j = 0; j < input_size; j++) {
      if (i == j || input_buffer[j] == 0) continue;
      if (0 - INT_MAX > input_buffer[i] && input_buffer[j] == -1) continue;
      if (test_output == input_buffer[i] / input_buffer[j])
	return 1.0;
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math2in_AQ() const //(XY)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i++) {
    for (int j = 0; j < input_size; j++) {
      if (i == j) continue;
      if (test_output == input_buffer[i] * input_buffer[j])
	return 1.0;
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math2in_AR() const //(sqrt(X)+sqrt(Y))
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i++) {
    for (int j = 0; j < input_size; j++) {
      if (i == j) continue;
      if (test_output == (int) sqrt((double) abs(input_buffer[i])) + (int) sqrt((double) abs(input_buffer[j])))
	return 1.0;
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math2in_AS() const //(X+2Y)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i++) {
    for (int j = 0; j < input_size; j++) {
      if (i == j) continue;
      if (test_output == input_buffer[i] + 2 * input_buffer[j])
	return 1.0;
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math2in_AT() const //(X+3Y)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i++) {
    for (int j = 0; j < input_size; j++) {
      if (i == j) continue;
      if (test_output == input_buffer[i] + 3 * input_buffer[j])
	return 1.0;
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math2in_AU() const //(2X+3Y)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i++) {
    for (int j = 0; j < input_size; j++) {
      if (i == j) continue;
      if (test_output == 2 * input_buffer[i] + 3 * input_buffer[j])
	return 1.0;
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math2in_AV() const //(XY^2)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i++) {
    for (int j = 0; j < input_size; j++) {
      if (i == j) continue;
      if (test_output == input_buffer[i] * input_buffer[j] * input_buffer[j])
	return 1.0;
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math3in_AA() const //(X^2+Y^2+Z^2)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    for (int j = 0; j < input_size; j ++) {
      for (int k = 0; k < input_size; k ++) {
	if (i == j || j == k || i == k) continue;
	if (test_output == input_buffer[i] * input_buffer[i] + 
	    input_buffer[j] * input_buffer[j] + 
	    input_buffer[k] * input_buffer[k]) return 1.0;
      }
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math3in_AB() const //(sqrt(X)+sqrt(Y)+sqrt(Z))
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    for (int j = 0; j < input_size; j ++) {
      for (int k = 0; k < input_size; k ++) {
	if (i == j || j == k || i == k) continue;
	if (test_output == (int) sqrt((double) abs(input_buffer[i])) +
	    (int) sqrt((double) abs(input_buffer[j])) + (int) sqrt((double) abs(input_buffer[k])))
	  return 1.0;
      }
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math3in_AC() const //(X+2Y+3Z)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    for (int j = 0; j < input_size; j ++) {
      for (int k = 0; k < input_size; k ++) {
	if (i == j || j == k || i == k) continue;
	if (test_output == input_buffer[i] + 2 * input_buffer[j] +
	    3 * input_buffer[k]) return 1.0;
      }
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math3in_AD() const //(XY^2+Z^3)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    for (int j = 0; j < input_size; j ++) {
      for (int k = 0; k < input_size; k ++) {
	if (i == j || j == k || i == k) continue;
	if (test_output == input_buffer[i] * input_buffer[j] * input_buffer[j] + input_buffer[k] * input_buffer[k] * input_buffer[k])
	  return 1.0;
      }
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math3in_AE() const //((X%Y)*Z)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    for (int j = 0; j < input_size; j ++) {
      for (int k = 0; k < input_size; k ++) {
	if (i == j || j == k || i == k) continue;
	if (input_buffer[j] == 0) continue; // mod by zero
	if (test_output == input_buffer[i] % input_buffer[j] * input_buffer[k])
	  return 1.0;
      }
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math3in_AF() const //((X+Y)^2+sqrt(Y+Z))
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    for (int j = 0; j < input_size; j ++) {
      for (int k = 0; k < input_size; k ++) {
	if (i == j || j == k || i == k) continue;
	if (test_output == (input_buffer[i] + input_buffer[j]) *
	    (input_buffer[i] + input_buffer[j]) +
	    (int) sqrt((double) abs(input_buffer[j] + input_buffer[k])))
	  return 1.0;
      }
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math3in_AG() const //((XY)%(YZ))
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    for (int j = 0; j < input_size; j ++) {
      for (int k = 0; k < input_size; k ++) {
	if (i == j || j == k || i == k) continue;
	int mod_base = input_buffer[j] * input_buffer[k];
	if (mod_base == 0) continue;
	if (test_output == (input_buffer[i] * input_buffer[j]) %
	    mod_base) return 1.0;
      }
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math3in_AH() const //(X+Y+Z)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    for (int j = 0; j < input_size; j ++) {
      for (int k = 0; k < input_size; k ++) {
	if (i == j || j == k || i == k) continue;
	if (test_output == input_buffer[i] + input_buffer[j] + input_buffer[k])
	  return 1.0;
      }
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math3in_AI() const //(-X-Y-Z)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    for (int j = 0; j < input_size; j ++) {
      for (int k = 0; k < input_size; k ++) {
	if (i == j || j == k || i == k) continue;
	if (test_output == 0 - input_buffer[i] - input_buffer[j] - input_buffer[k])
	  return 1.0;
      }
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math3in_AJ() const //((X-Y)^2+(Y-Z)^2+(Z-X)^2)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    for (int j = 0; j < input_size; j ++) {
      for (int k = 0; k < input_size; k ++) {
	if (i == j || j == k || i == k) continue;
	if (test_output == (input_buffer[i] - input_buffer[j]) * (input_buffer[i] - input_buffer[j]) + (input_buffer[j] - input_buffer[k]) * (input_buffer[j] - input_buffer[k]) + (input_buffer[k] - input_buffer[i]) * (input_buffer[k] - input_buffer[i]))
	  return 1.0;
      }
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math3in_AK() const //((X+Y)^2+(Y+Z)^2+(Z+X)^2)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    for (int j = 0; j < input_size; j ++) {
      for (int k = 0; k < input_size; k ++) {
	if (i == j || j == k || i == k) continue;
	if (test_output == (input_buffer[i] + input_buffer[j]) * (input_buffer[i] + input_buffer[j]) + (input_buffer[j] + input_buffer[k]) * (input_buffer[j] + input_buffer[k]) + (input_buffer[k] + input_buffer[i]) * (input_buffer[k] + input_buffer[i])) 
	  return 1.0;
      }
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math3in_AL() const //((X-Y)^2+(X-Z)^2)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    for (int j = 0; j < input_size; j ++) {
      for (int k = 0; k < input_size; k ++) {
	if (i == j || j == k || i == k) continue;  
	if (test_output == (input_buffer[i] - input_buffer[j]) * (input_buffer[i] - input_buffer[j]) + (input_buffer[i] - input_buffer[k]) * (input_buffer[i] - input_buffer[k]))
	  return 1.0;
      }
    }
  }
  return 0.0;
}

double cTaskLib::Task_Math3in_AM() const //((X+Y)^2+(Y+Z)^2)
{
  const int test_output = output_buffer[0];
  const int input_size = input_buffer.GetNumStored();
  for (int i = 0; i < input_size; i ++) {
    for (int j = 0; j < input_size; j ++) {
      for (int k = 0; k < input_size; k ++) {
	if (i == j || j == k || i == k) continue;  
	if (test_output == (input_buffer[i] + input_buffer[j]) * (input_buffer[i] + input_buffer[j]) + (input_buffer[i] + input_buffer[k]) * (input_buffer[i] + input_buffer[k]))
	  return 1.0;
      }
    }
  }
  return 0.0;
}

Index: avida/current/source/main/task_lib.hh
+++ avida/current/source/main/task_lib.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef TASK_LIB_HH
#define TASK_LIB_HH

#ifndef TARRAY_HH
#include "tArray.hh"
#endif
#ifndef TBUFFER_HH
#include "tBuffer.hh"
#endif

class cTaskLib;
typedef double (cTaskLib::*tTaskTest)() const;

class cString;
class cTaskEntry;
class cTaskLib {
private:
  tArray<cTaskEntry *> task_array;

  // Active task information...
  mutable tBuffer<int> input_buffer;
  mutable tBuffer<int> output_buffer;
  mutable int logic_id;
public:
  cTaskLib();
  ~cTaskLib();

  int GetSize() const { return task_array.GetSize(); }

  cTaskEntry * AddTask(const cString & name);
  const cTaskEntry & GetTask(int id) const;
  
  void SetupTests(const tBuffer<int> & inputs,
		  const tBuffer<int> & outputs) const;
  double TestOutput(const cTaskEntry & task) const;



private:  // Direct task related methods
  void NewTask(const cString & name, const cString & desc, tTaskTest task_fun);
  void SetupLogicTests(const tBuffer<int> & inputs,
		       const tBuffer<int> & outputs) const;

  double Task_Echo() const;
  double Task_Add()  const;
  double Task_Sub()  const;

  double Task_Not()    const;
  double Task_Nand()   const;
  double Task_And()    const;
  double Task_OrNot()  const;
  double Task_Or()     const;
  double Task_AndNot() const;
  double Task_Nor()    const;
  double Task_Xor()    const;
  double Task_Equ()    const;

  double Task_Logic3in_AA() const;
  double Task_Logic3in_AB() const;
  double Task_Logic3in_AC() const;
  double Task_Logic3in_AD() const;
  double Task_Logic3in_AE() const;
  double Task_Logic3in_AF() const;
  double Task_Logic3in_AG() const;
  double Task_Logic3in_AH() const;
  double Task_Logic3in_AI() const;
  double Task_Logic3in_AJ() const;
  double Task_Logic3in_AK() const;
  double Task_Logic3in_AL() const;
  double Task_Logic3in_AM() const;
  double Task_Logic3in_AN() const;
  double Task_Logic3in_AO() const;
  double Task_Logic3in_AP() const;
  double Task_Logic3in_AQ() const;
  double Task_Logic3in_AR() const;
  double Task_Logic3in_AS() const;
  double Task_Logic3in_AT() const;
  double Task_Logic3in_AU() const;
  double Task_Logic3in_AV() const;
  double Task_Logic3in_AW() const;
  double Task_Logic3in_AX() const;
  double Task_Logic3in_AY() const;
  double Task_Logic3in_AZ() const;
  double Task_Logic3in_BA() const;
  double Task_Logic3in_BB() const;
  double Task_Logic3in_BC() const;
  double Task_Logic3in_BD() const;
  double Task_Logic3in_BE() const;
  double Task_Logic3in_BF() const;
  double Task_Logic3in_BG() const;
  double Task_Logic3in_BH() const;
  double Task_Logic3in_BI() const;
  double Task_Logic3in_BJ() const;
  double Task_Logic3in_BK() const;
  double Task_Logic3in_BL() const;
  double Task_Logic3in_BM() const;
  double Task_Logic3in_BN() const;
  double Task_Logic3in_BO() const;
  double Task_Logic3in_BP() const;
  double Task_Logic3in_BQ() const;
  double Task_Logic3in_BR() const;
  double Task_Logic3in_BS() const;
  double Task_Logic3in_BT() const;
  double Task_Logic3in_BU() const;
  double Task_Logic3in_BV() const;
  double Task_Logic3in_BW() const;
  double Task_Logic3in_BX() const;
  double Task_Logic3in_BY() const;
  double Task_Logic3in_BZ() const;
  double Task_Logic3in_CA() const;
  double Task_Logic3in_CB() const;
  double Task_Logic3in_CC() const;
  double Task_Logic3in_CD() const;
  double Task_Logic3in_CE() const;
  double Task_Logic3in_CF() const;
  double Task_Logic3in_CG() const;
  double Task_Logic3in_CH() const;
  double Task_Logic3in_CI() const;
  double Task_Logic3in_CJ() const;
  double Task_Logic3in_CK() const;
  double Task_Logic3in_CL() const;
  double Task_Logic3in_CM() const;
  double Task_Logic3in_CN() const;
  double Task_Logic3in_CO() const;
  double Task_Logic3in_CP() const;

  double Task_Math1in_AA() const;
  double Task_Math1in_AB() const;
  double Task_Math1in_AC() const;
  double Task_Math1in_AD() const;
  double Task_Math1in_AE() const;
  double Task_Math1in_AF() const;
  double Task_Math1in_AG() const;
  double Task_Math1in_AH() const;
  double Task_Math1in_AI() const;
  double Task_Math1in_AJ() const;
  double Task_Math1in_AK() const;
  double Task_Math1in_AL() const;
  double Task_Math1in_AM() const;
  double Task_Math1in_AN() const;
  double Task_Math1in_AO() const;
  double Task_Math1in_AP() const;

  double Task_Math2in_AA() const;
  double Task_Math2in_AB() const;
  double Task_Math2in_AC() const;
  double Task_Math2in_AD() const;
  double Task_Math2in_AE() const;
  double Task_Math2in_AF() const;
  double Task_Math2in_AG() const;
  double Task_Math2in_AH() const;
  double Task_Math2in_AI() const;
  double Task_Math2in_AJ() const;
  double Task_Math2in_AK() const;
  double Task_Math2in_AL() const;
  double Task_Math2in_AM() const;
  double Task_Math2in_AN() const;
  double Task_Math2in_AO() const;
  double Task_Math2in_AP() const;
  double Task_Math2in_AQ() const;
  double Task_Math2in_AR() const;
  double Task_Math2in_AS() const;
  double Task_Math2in_AT() const;
  double Task_Math2in_AU() const;
  double Task_Math2in_AV() const;

  double Task_Math3in_AA() const;
  double Task_Math3in_AB() const;
  double Task_Math3in_AC() const;
  double Task_Math3in_AD() const;
  double Task_Math3in_AE() const;
  double Task_Math3in_AF() const;
  double Task_Math3in_AG() const;
  double Task_Math3in_AH() const;
  double Task_Math3in_AI() const;
  double Task_Math3in_AJ() const;
  double Task_Math3in_AK() const;
  double Task_Math3in_AL() const;
  double Task_Math3in_AM() const;
  
};

#endif

Index: avida/current/source/testsuites/Makefile.am
+++ avida/current/source/testsuites/Makefile.am

if CODE_TESTS
SUBDIRS = unit_testsuites functional_testsuites
endif

Index: avida/current/source/testsuites/functional_testsuites/Makefile.am
+++ avida/current/source/testsuites/functional_testsuites/Makefile.am
EXTRA_DIST =
TESTSUITES =

EXTRA_DIST += default.tail
if DEFAULT_TESTS
TESTSUITES += default.tail/tail.sh
endif

if TEDIOUS_TESTS
endif

TESTS = $(TESTSUITES)
TESTS_ENVIRONMENT=$(SHELL)

Index: avida/current/source/testsuites/functional_testsuites/config/unix.exp
+++ avida/current/source/testsuites/functional_testsuites/config/unix.exp
# a hairy pattern to recognize text
set text "\[- A-Za-z0-9\.\;\"\_\:\'\`\(\)\!\#\=\+\?\&\*]"

# Execute the executable file, and analyse the output for the 
# test state keywords.
#    Returns:
#       A "" (empty) string if everything worked, or an error message
#       if there was a problem.
proc executable_test {tool args} {
    global text

    set timeoutmsg "Timed out: Never got started, "
    set timeout 100
    set file all
    set timetol 0
    set arguments ""
    
    expect_before buffer_full { perror "Buffer full" }
    
    if { [llength $args] == 0} {
        set executable $args
    } else {
        set executable [string trimleft [lindex [split $args " "] 0] "\{"]
        set the_command [string trimleft $args "\{"]
        set the_command [string trimright $the_command "\}"]
    }

    verbose "The executable is $executable" 2
    if ![file exists ${executable}] {
        perror "The executable \"$executable\" is missing" 0
        return "No source file found"
    }

    # spawn the executable and look for the DejaGnu output messages from the
    # test case.
    # spawn -noecho -open [open "|./${executable}" "r"]
    eval "spawn -noecho $the_command"
    expect {
        -re "\[0-9\]\[0-9\]:..:..:${text}\r\n" {
            regsub "\[\n\r\t\]*NOTE: $text\r\n" $expect_out(0,string) "" output
            verbose "$output" 3
            set timetol 0
            exp_continue
        }
        -re "NOTE:${text}*" {
            regsub "\[\n\r\t\]*NOTE: $text\r\n" $expect_out(0,string) "" output
            set output [string range $output 6 end]
            verbose "$output" 2
            set timetol 0
            exp_continue
        }
        -re "PASSED:${text}*" {
            regsub "\[\n\r\t\]*PASSED: $text\r\n" $expect_out(0,string) "" output
            set output [string range $output 8 end]
            pass "$output"
            set timetol 0
            exp_continue
        }
        -re "FAILED:${text}*" {
            regsub "\[\n\r\t\]*FAILED: $text\r\n" $expect_out(0,string) "" output
            set output [string range $output 8 end]
            fail "$output (See $tool.log for details.)"
            set timetol 0
            exp_continue
        }
        -re "UNTESTED:${text}*" {
            regsub "\[\n\r\t\]*UNTESTED: $text\r\n" $expect_out(0,string) "" output
            set output [string range $output 10 end]
            untested "$output"
            set timetol 0
            exp_continue
        }
        -re "UNRESOLVED:${text}*" {
            regsub "\[\n\r\t\]*UNRESOLVED: $text\r\n" $expect_out(0,string) "" output
            set output [string range $output 12 end]
            unresolved "$output"
            set timetol 0
            exp_continue
        }
        -re "Totals" {
            verbose "All done" 2
        }
        eof {
#           unresolved "${executable} died prematurely"
#           catch close
#           return "${executable} died prematurely"
        }
        timeout {
            warning "Timed out executing test case"
            if { $timetol <= 2 } {
                incr timetol
                exp_continue
            } else {
-               catch close
                return "Timed out executing test case"
            }
        }
    }

    # force a close of the executable to be safe.
    catch close
    return ""
}

# Execute the executable file, and analyse the output for the 
# expected last line.  
#    Returns:
#       A "" (empty) string if everything worked, or an error message
#       if there was a problem.
proc scripted_test {tool test args expected_output} {
    global text

    set timeoutmsg "Timed out: Never got started, "
    set timeout 100
    set file all
    set timetol 0
    set arguments ""
     
    expect_before buffer_full { perror "Buffer full" }

    if { [llength $args] == 0} {
        set executable $args
    } else {
        set executable [string trimleft [lindex [split $args " "] 0] "\{"]
        set the_command [string trimleft $args "\{"]
        set the_command [string trimright $the_command "\}"]
    }

    verbose "The executable is $executable" 2
    if ![file exists ${executable}] {
        perror "The executable \"$executable\" is missing" 0
        return "No source file found"
    }

    # spawn the executable and look for the DejaGnu output messages from the
    # test case.
    # spawn -noecho -open [open "|./${executable}" "r"]
    eval "spawn -noecho $the_command"
    expect {
        -re $expected_output {
            # Tells dejagnu that the test has passed.
            pass "$test"
        }
        default {
            # Displays the output from the shell script.
            puts "*** last lines of test output:"
            puts $expect_out(buffer)
            # Display expected output.
            puts "*** expected $expected_output"
            # Displays 'failed' message to user, and tells dejagnu that the
            # test has failed.
            fail "See $tool.log for details.";
        }
        timeout {
            warning "Timed out executing test case"
            if { $timetol <= 2 } {
                incr timetol
                exp_continue
            } else {
-               catch close
                return "Timed out executing test case"
            }
        }
    }

    # force a close of the executable to be safe.
    catch close
    return ""
}


Index: avida/current/source/testsuites/functional_testsuites/default.md5sum/analyze.cfg
+++ avida/current/source/testsuites/functional_testsuites/default.md5sum/analyze.cfg
#############################################################################
# This file is used to setup avida when it is in analysis-only mode (by
# running "avida -a".  It allows variety of methods to load organisms
# (specifying the type of each) and analyze them once loaded.
#
# See the documentation in doc/analyze_mode.html for usage, or the file
# doc/analyze_samples.html for guidelines on writing programs.
#
#############################################################################

Index: avida/current/source/testsuites/functional_testsuites/default.md5sum/environment.cfg
+++ avida/current/source/testsuites/functional_testsuites/default.md5sum/environment.cfg
##############################################################################
#
# This is the setup file for the task/resource system.  From here, you can
# setup the available resources (including their inflow and outflow rates) as
# well as the reactions that the organisms can trigger by performing tasks.
#
# This file is currently setup to reward 9 tasks, all of which use the
# "infinite" resource, which is undepletable.
#
# For information on how to use this file, see:  doc/environment.html
# For other sample environments, see:  source/support/config/ 
#
##############################################################################

REACTION  NOT  not   process:value=1.0:type=pow  requisite:max_count=1
REACTION  NAND nand  process:value=1.0:type=pow  requisite:max_count=1
REACTION  AND  and   process:value=2.0:type=pow  requisite:max_count=1
REACTION  ORN  orn   process:value=2.0:type=pow  requisite:max_count=1
REACTION  OR   or    process:value=3.0:type=pow  requisite:max_count=1
REACTION  ANDN andn  process:value=3.0:type=pow  requisite:max_count=1
REACTION  NOR  nor   process:value=4.0:type=pow  requisite:max_count=1
REACTION  XOR  xor   process:value=4.0:type=pow  requisite:max_count=1
REACTION  EQU  equ   process:value=5.0:type=pow  requisite:max_count=1

Index: avida/current/source/testsuites/functional_testsuites/default.md5sum/events.cfg
+++ avida/current/source/testsuites/functional_testsuites/default.md5sum/events.cfg
##############################################################################
#
# This is the setup file for the events system.  From here, you can
# configure any actions that you want to have happen during the course of
# an experiment, including setting the times for data collection.
#
# basic syntax:  [trigger]  [start:interval:stop]  [event] [arguments...]
#
# This file is currently setup to start off a population full of the 
# starting organism specified in genesis, and then record key information
# every 100 updates.
#
# For information on how to use this file, see:  doc/events.html
# For other sample event configurations, see:  source/support/config/
#
##############################################################################

# Print all of the standard data files...
u 0:100 print_dom                 # Save the most abundant genotypes
u 0:100:end print_average_data    # Save info about they average genotypes
u 0:100:end print_dominant_data   # Save info about most abundant genotypes
u 0:100:end print_stats_data      # Collect satistics about entire pop.
u 0:100:end print_count_data      # Count organisms, genotypes, species, etc.
u 0:100:end print_tasks_data      # Save organisms counts for each task.
u 0:100:end print_time_data       # Track time conversion (generations, etc.)
u 0:100:end print_resource_data   # Track resource abundance.

# A few data files not printed by default
# u 100:100:end print_error_data      # Std. Error on averages.
# u 100:100:end print_variance_data   # Variance on averages.
# u 100:100:end print_totals_data     # Total counts over entire run.
# u 100:100:end print_tasks_exe_data  # Num. times tasks have been executed.

# Setup the exit time and full population data collection.
u 100:100 detail_pop           # Save current state of population.
u 100:100 dump_historic_pop    # Save ancestors of current population.
u 100 exit                      # exit


Index: avida/current/source/testsuites/functional_testsuites/default.md5sum/genesis
+++ avida/current/source/testsuites/functional_testsuites/default.md5sum/genesis
#############################################################################
# This file includes all the basic run-time defines for avida.
# For more information, see doc/genesis.html
#############################################################################

VERSION_ID 2.0b7		# Do not change this value!

### Architecture Variables ###
MAX_UPDATES  -1         # Maximum updates to run simulation (-1 = no limit)
MAX_GENERATIONS -1      # Maximum generations to run simulation (-1 = no limit)
END_CONDITION_MODE 0	# End run when ...
			# 0 = MAX_UPDATES _OR_ MAX_GENERATIONS is reached
			# 1 = MAX_UPDATES _AND_ MAX_GENERATIONS is reached
WORLD-X 20		# Width of the world in Avida mode.
WORLD-Y 20		# Height of the world in Avida mode.
WORLD_GEOMETRY 2        # 1 = Bounded Grid
                        # 2 = Torus (Default)
RANDOM_SEED 1		# Random number seed. (0 for based on time)
HARDWARE_TYPE 0		# 0 = Original CPUs
			# 1 = New, Stack-based CPUs
MAX_CPU_THREADS 1	# Number of Threads CPUs can spawn

### Configuration Files ###
DEFAULT_DIR ../work/              # Directory in which config files are found
INST_SET inst_set.default         # File containing instruction set
EVENT_FILE events.cfg             # File containing list of events during run
ANALYZE_FILE analyze.cfg          # File used for analysis mode
ENVIRONMENT_FILE environment.cfg  # File that describes the environment
START_CREATURE organism.default   # Organism to seed the soup

### Reproduction ###
BIRTH_METHOD 4    # 0 = Replace random organism in neighborhood
		  # 1 = Replace oldest organism in neighborhood
		  # 2 = Replace largest Age/Merit in neighborhood
		  # 3 = Place only in empty cells in neighborhood
		  # 4 = Replace random from entire population (Mass Action)
		  # 5 = Replace oldest in entire population (like Tierra)
DEATH_METHOD 0    # 0 = Never die of old age.
		  # 1 = Die when inst executed = AGE_LIMIT (with deviation)
		  # 2 = Die when inst executed = length * AGE_LIMIT (+ dev.)
AGE_LIMIT 5000    # Modifies DEATH_METHOD
AGE_DEVIATION 0   # Modified DEATH_METHOD
ALLOC_METHOD 0    # 0 = Allocated space is set to default instruction.
                  # 1 = Set to section of dead genome (Necrophilia)
                  # 2 = Allocated space is set to random instruction.
DIVIDE_METHOD 1   # 0 = Divide leaves state of mother untouched.
                  # 1 = Divide resets state of mother
                  #     (after the divide, we have 2 children)

GENERATION_INC_METHOD 1 # 0 = Only the generation of the child is
                        #     increased on divide.
			# 1 = Both the generation of the mother and child are
			#     increased on divide (good with DIVIDE_METHOD 1).

### Divide Restrictions ####
CHILD_SIZE_RANGE 2.0	# Maximal differential between child and parent sizes.
MIN_COPIED_LINES 0.5    # Code fraction which must be copied before divide.
MIN_EXE_LINES    0.5    # Code fraction which must be executed before divide.
REQUIRE_ALLOCATE   1    # Is a an allocate required before a divide? (0/1)
REQUIRED_TASK -1  # Number of task required for successful divide.

### Mutations ###

# mutations that occur during execution..
POINT_MUT_PROB  0.0     # Mutation rate (per-location per update)
COPY_MUT_PROB   0.0075  # Mutation rate (per copy).

# mutations that occur on divide...
INS_MUT_PROB    0.0     # Insertion rate (per site, applied on divide).
DEL_MUT_PROB    0.0     # Deletion rate (per site, applied on divide).
DIV_MUT_PROB    0.0     # Mutation rate (per site, applied on divide).
DIVIDE_MUT_PROB 0.0     # Mutation rate (per divide).
DIVIDE_INS_PROB 0.05    # Insertion rate (per divide).
DIVIDE_DEL_PROB 0.05    # Deletion rate (per divide).
PARENT_MUT_PROB 0.0     # Per-site, in parent, on divide

# heads based mutations
# READ_SHIFT_PROB   0.0
# READ INS_PROB     0.0
# READ_DEL_PROB     0.0
# WRITE_SHIFT_PROB  0.0
# WRITE_INS_PROB    0.0
# WRITE_DEL_PROB    0.0


### Mutation reversions ###
# these slow down avida a lot, and should be set to 0 normally.
REVERT_FATAL       0.0  # Should any mutations be reverted on birth?
REVERT_DETRIMENTAL 0.0  #   0.0 to 1.0; Probability of reversion.
REVERT_NEUTRAL     0.0
REVERT_BENEFICIAL  0.0

STERILIZE_FATAL       0.0  # Should any mutations clear (kill) the organism?
STERILIZE_DETRIMENTAL 0.0  #   0.0 to 1.0; Probability of reset.
STERILIZE_NEUTRAL     0.0
STERILIZE_BENEFICIAL  0.0

FAIL_IMPLICIT     0	# Should copies that failed *not* due to mutations
			# be eliminated?

### Time Slicing ###
AVE_TIME_SLICE 30
SLICING_METHOD 2	# 0 = CONSTANT: all organisms get default...
			# 1 = PROBABILISTIC: Run _prob_ proportional to merit.
			# 2 = INTEGRATED: Perfectly integrated deterministic.
SIZE_MERIT_METHOD 4	# 0 = off (merit is independent of size)
			# 1 = Merit proportional to copied size
			# 2 = Merit prop. to executed size
			# 3 = Merit prop. to full size
			# 4 = Merit prop. to min of executed or copied size
			# 5 = Merit prop. to sqrt of the minimum size
TASK_MERIT_METHOD 1	# 0 = No task bonuses
			# 1 = Bonus just equals the task bonus
THREAD_SLICING_METHOD 0 # 0 = One thread executed per time slice.
			# 1 = All threads executed each time slice.

MAX_LABEL_EXE_SIZE 1	# Max nops marked as executed when labels are used
MERIT_TIME 1            # 0 = Merit Calculated when task completed
		        # 1 = Merit Calculated on Divide
MAX_NUM_TASKS_REWARDED -1  # -1 = Unlimited

### Genotype Info ###
THRESHOLD 3		# Number of organisms in a genotype needed for it
			#   to be considered viable.
GENOTYPE_PRINT 0	# 0/1 (off/on) Print out all threshold genotypes?
GENOTYPE_PRINT_DOM 0	# Print out a genotype if it stays dominant for
                        #   this many updates. (0 = off)
SPECIES_THRESHOLD 2     # max failure count for organisms to be same species
SPECIES_RECORDING 0	# 1 = full, 2 = limited search (parent only)
SPECIES_PRINT 0		# 0/1 (off/on) Print out all species?
TEST_CPU_TIME_MOD 20    # Time allocated in test CPUs (multiple of length)
TRACK_MAIN_LINEAGE 1    # Track primary lineage leading to final population?

### Log Files ###
LOG_CREATURES 0		# 0/1 (off/on) toggle to print file.
LOG_GENOTYPES 0		# 0 = off, 1 = print ALL, 2 = print threshold ONLY.
LOG_THRESHOLD 0		# 0/1 (off/on) toggle to print file.
LOG_SPECIES 0		# 0/1 (off/on) toggle to print file.
LOG_LANDSCAPE 0		# 0/1 (off/on) toggle to print file.

LOG_LINEAGES 0          # 0/1 (off/on) to log advantageous mutations
# This one can slow down avida a lot. It is used to get an idea of how
# often an advantageous mutation arises, and where it goes afterwards.
# See also LINEAGE_CREATION_METHOD.

LINEAGE_CREATION_METHOD 0
# Lineage creation options are.  Works only when LOG_LINEAGES is set to 1.
#   0 = manual creation (on inject, use successive integers as lineage labels).
#   1 = when a child's (potential) fitness is higher than that of its parent.
#   2 = when a child's (potential) fitness is higher than max in population.
#   3 = when a child's (potential) fitness is higher than max in dom. lineage
#	*and* the child is in the dominant lineage, or (2)
#   4 = when a child's (potential) fitness is higher than max in dom. lineage
#	(and that of its own lineage)
#   5 = same as child's (potential) fitness is higher than that of the
#       currently dominant organism, and also than that of any organism
#       currently in the same lineage.
#   6 = when a child's (potential) fitness is higher than any organism
#       currently in the same lineage.
#   7 = when a child's (potential) fitness is higher than that of any
#       organism in its line of descent

### END ###



Index: avida/current/source/testsuites/functional_testsuites/default.md5sum/inst_set.default
+++ avida/current/source/testsuites/functional_testsuites/default.md5sum/inst_set.default
nop-A      1   # a
nop-B      1   # b
nop-C      1   # c
if-n-equ   1   # d
if-less    1   # e
pop        1   # f
push       1   # g
swap-stk   1   # h
swap       1   # i 
shift-r    1   # j
shift-l    1   # k
inc        1   # l
dec        1   # m
add        1   # n
sub        1   # o
nand       1   # p
IO         1   # q   Puts current contents of register and gets new.
h-alloc    1   # r   Allocate as much memory as organism can use.
h-divide   1   # s   Cuts off everything between the read and write heads
h-copy     1   # t   Combine h-read and h-write
h-search   1   # u   Search for matching template, set flow head & return info
               #   #   if no template, move flow-head here, set size&offset=0.
mov-head   1   # v   Move ?IP? head to flow control.
jmp-head   1   # w   Move ?IP? head by fixed amount in CX.  Set old pos in CX.
get-head   1   # x   Get position of specified head in CX.
if-label   1   # y
set-flow   1   # z   Move flow-head to address in ?CX? 

#adv-head   1
#jump-f     1
#jump-b     1
#call       1
#return     1
#if-bit-1   1
#get        1
#put        1
#h-read     1
#h-write    1
#set-head   1
#search-f   1
#search-b   1


# Works on multiple nops:  pop  push  inc  dec  IO  adv-head 

# What if we add a new head.  Search will return the location of something,
# and put the new head there.  Then set-head will move another head to that
# point.  In the case of the copy loop, it only needs to be set once and
# this will speed up the code quite a bit!

# Search with no template returns current position (abs line number) in
# genome.
Index: avida/current/source/testsuites/functional_testsuites/default.md5sum/md5sum.exp
+++ avida/current/source/testsuites/functional_testsuites/default.md5sum/md5sum.exp
# Note: the variables 'srcdir', 'subdir', and 'tool' (among others) are
# preinitialized by dejagnu.

# The default timeout period is 10 seconds but may be set as follows:
  set timeout 30

# Give this test a name.
  set test "md5sum demo"

# Set the commandline that performs this test.
  set SHELLSCRIPT "$srcdir/$subdir/md5sum.sh $srcdir $subdir $AVIDA_BLDDIR/primitive"

# Expected output (regular expression to match the last line of
# detail_pop.100):
  set expected_output "46519f71f37290204b73c7fb9584c6b2"

# Launch the test.  Complain if there was a problem launching.
if { [scripted_test "$tool" "$test" "$SHELLSCRIPT" "$expected_output"] != "" } {
  perror "failed to spawn \"$SHELLSCRIPT\"." 0
}

Index: avida/current/source/testsuites/functional_testsuites/default.md5sum/md5sum.sh
+++ avida/current/source/testsuites/functional_testsuites/default.md5sum/md5sum.sh
# /bin/sh

# read command-line arguments:
TESTSUITE_DIR=$1       # path to top directory for test scripts.
SUBDIR=$2              # subdir of TESTSUITE_DIR containing this script.
AVIDA_PATH=$3          # path to avida executable.

# specify paths to config files.
CFG_DIR=$TESTSUITE_DIR/$SUBDIR
GENESIS_FILE=$CFG_DIR/genesis
INST_SET=$CFG_DIR/inst_set.default
EVENT_FILE=$CFG_DIR/events.cfg
ANALYZE_FILE=$CFG_DIR/analyze.cfg
ENVIRONMENT_FILE=$CFG_DIR/environment.cfg
START_CREATURE=$CFG_DIR/organism.default

# make subdirectory for storing avida's output files.
[ -d $SUBDIR ] || mkdir -p $SUBDIR
cd $SUBDIR

# run avida, and save all output to avida_run.log.
$AVIDA_PATH \
  -genesis $GENESIS_FILE \
  -set INST_SET $INST_SET \
  -set EVENT_FILE $EVENT_FILE \
  -set ANALYZE_FILE $ANALYZE_FILE \
  -set ENVIRONMENT_FILE $ENVIRONMENT_FILE \
  -set START_CREATURE $START_CREATURE \
  2>&1 > avida_run.log

# send the md5sum of detail_pop.100 back to the testdriver for
# verification.
echo "md5sum of output file detail_pop.100:"
md5sum detail_pop.100

# sleeping for one second gives dejagnu/expect time to react.
sleep 1;

Index: avida/current/source/testsuites/functional_testsuites/default.md5sum/organism.default
+++ avida/current/source/testsuites/functional_testsuites/default.md5sum/organism.default
h-alloc    # Allocate space for child
h-search   # Locate the end of the organism
nop-C      #
nop-A      #
mov-head   # Place write-head at beginning of offspring.
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
h-search   # Mark the beginning of the copy loop
h-copy     # Do the copy
if-label   # If we're done copying....
nop-C      #
nop-A      #
h-divide   #    ...divide!
mov-head   # Otherwise, loop back to the beginning of the copy loop.
nop-A      # End label.
nop-B      #

Index: avida/current/source/testsuites/functional_testsuites/default.tail/analyze.cfg
+++ avida/current/source/testsuites/functional_testsuites/default.tail/analyze.cfg
#############################################################################
# This file is used to setup avida when it is in analysis-only mode (by
# running "avida -a".  It allows variety of methods to load organisms
# (specifying the type of each) and analyze them once loaded.
#
# See the documentation in doc/analyze_mode.html for usage, or the file
# doc/analyze_samples.html for guidelines on writing programs.
#
#############################################################################

Index: avida/current/source/testsuites/functional_testsuites/default.tail/detail_pop.100.last_line.expected
+++ avida/current/source/testsuites/functional_testsuites/default.tail/detail_pop.100.last_line.expected
54 48 24 1 1 100 0 0 0 100 -1 2 cccccccccccccccccccccccccccccccccccccccccutyctsvabrucavccccccccccccccccccccccccccccccccccccccccccccc 

Index: avida/current/source/testsuites/functional_testsuites/default.tail/environment.cfg
+++ avida/current/source/testsuites/functional_testsuites/default.tail/environment.cfg
##############################################################################
#
# This is the setup file for the task/resource system.  From here, you can
# setup the available resources (including their inflow and outflow rates) as
# well as the reactions that the organisms can trigger by performing tasks.
#
# This file is currently setup to reward 9 tasks, all of which use the
# "infinite" resource, which is undepletable.
#
# For information on how to use this file, see:  doc/environment.html
# For other sample environments, see:  source/support/config/ 
#
##############################################################################

REACTION  NOT  not   process:value=1.0:type=pow  requisite:max_count=1
REACTION  NAND nand  process:value=1.0:type=pow  requisite:max_count=1
REACTION  AND  and   process:value=2.0:type=pow  requisite:max_count=1
REACTION  ORN  orn   process:value=2.0:type=pow  requisite:max_count=1
REACTION  OR   or    process:value=3.0:type=pow  requisite:max_count=1
REACTION  ANDN andn  process:value=3.0:type=pow  requisite:max_count=1
REACTION  NOR  nor   process:value=4.0:type=pow  requisite:max_count=1
REACTION  XOR  xor   process:value=4.0:type=pow  requisite:max_count=1
REACTION  EQU  equ   process:value=5.0:type=pow  requisite:max_count=1

Index: avida/current/source/testsuites/functional_testsuites/default.tail/events.cfg
+++ avida/current/source/testsuites/functional_testsuites/default.tail/events.cfg
##############################################################################
#
# This is the setup file for the events system.  From here, you can
# configure any actions that you want to have happen during the course of
# an experiment, including setting the times for data collection.
#
# basic syntax:  [trigger]  [start:interval:stop]  [event] [arguments...]
#
# This file is currently setup to start off a population full of the 
# starting organism specified in genesis, and then record key information
# every 100 updates.
#
# For information on how to use this file, see:  doc/events.html
# For other sample event configurations, see:  source/support/config/
#
##############################################################################

# Print all of the standard data files...
u 0:100 print_dom                 # Save the most abundant genotypes
u 0:100:end print_average_data    # Save info about they average genotypes
u 0:100:end print_dominant_data   # Save info about most abundant genotypes
u 0:100:end print_stats_data      # Collect satistics about entire pop.
u 0:100:end print_count_data      # Count organisms, genotypes, species, etc.
u 0:100:end print_tasks_data      # Save organisms counts for each task.
u 0:100:end print_time_data       # Track time conversion (generations, etc.)
u 0:100:end print_resource_data   # Track resource abundance.

# A few data files not printed by default
# u 100:100:end print_error_data      # Std. Error on averages.
# u 100:100:end print_variance_data   # Variance on averages.
# u 100:100:end print_totals_data     # Total counts over entire run.
# u 100:100:end print_tasks_exe_data  # Num. times tasks have been executed.

# Setup the exit time and full population data collection.
u 0:10 detail_pop           # Save current state of population.
u 0:10 dump_historic_pop    # Save ancestors of current population.
u 100 exit                      # exit


Index: avida/current/source/testsuites/functional_testsuites/default.tail/genesis
+++ avida/current/source/testsuites/functional_testsuites/default.tail/genesis
#############################################################################
# This file includes all the basic run-time defines for avida.
# For more information, see doc/genesis.html
#############################################################################

VERSION_ID 2.0b7		# Do not change this value!

### Architecture Variables ###
MAX_UPDATES  -1         # Maximum updates to run simulation (-1 = no limit)
MAX_GENERATIONS -1      # Maximum generations to run simulation (-1 = no limit)
END_CONDITION_MODE 0	# End run when ...
			# 0 = MAX_UPDATES _OR_ MAX_GENERATIONS is reached
			# 1 = MAX_UPDATES _AND_ MAX_GENERATIONS is reached
WORLD-X 20		# Width of the world in Avida mode.
WORLD-Y 20		# Height of the world in Avida mode.
WORLD_GEOMETRY 2        # 1 = Bounded Grid
                        # 2 = Torus (Default)
RANDOM_SEED 1		# Random number seed. (0 for based on time)
HARDWARE_TYPE 0		# 0 = Original CPUs
			# 1 = New, Stack-based CPUs
MAX_CPU_THREADS 1	# Number of Threads CPUs can spawn

### Configuration Files ###
DEFAULT_DIR ../work/              # Directory in which config files are found
INST_SET inst_set.default         # File containing instruction set
EVENT_FILE events.cfg             # File containing list of events during run
ANALYZE_FILE analyze.cfg          # File used for analysis mode
ENVIRONMENT_FILE environment.cfg  # File that describes the environment
START_CREATURE organism.default   # Organism to seed the soup

### Reproduction ###
BIRTH_METHOD 4    # 0 = Replace random organism in neighborhood
		  # 1 = Replace oldest organism in neighborhood
		  # 2 = Replace largest Age/Merit in neighborhood
		  # 3 = Place only in empty cells in neighborhood
		  # 4 = Replace random from entire population (Mass Action)
		  # 5 = Replace oldest in entire population (like Tierra)
DEATH_METHOD 0    # 0 = Never die of old age.
		  # 1 = Die when inst executed = AGE_LIMIT (with deviation)
		  # 2 = Die when inst executed = length * AGE_LIMIT (+ dev.)
AGE_LIMIT 5000    # Modifies DEATH_METHOD
AGE_DEVIATION 0   # Modified DEATH_METHOD
ALLOC_METHOD 0    # 0 = Allocated space is set to default instruction.
                  # 1 = Set to section of dead genome (Necrophilia)
                  # 2 = Allocated space is set to random instruction.
DIVIDE_METHOD 1   # 0 = Divide leaves state of mother untouched.
                  # 1 = Divide resets state of mother
                  #     (after the divide, we have 2 children)

GENERATION_INC_METHOD 1 # 0 = Only the generation of the child is
                        #     increased on divide.
			# 1 = Both the generation of the mother and child are
			#     increased on divide (good with DIVIDE_METHOD 1).

### Divide Restrictions ####
CHILD_SIZE_RANGE 2.0	# Maximal differential between child and parent sizes.
MIN_COPIED_LINES 0.5    # Code fraction which must be copied before divide.
MIN_EXE_LINES    0.5    # Code fraction which must be executed before divide.
REQUIRE_ALLOCATE   1    # Is a an allocate required before a divide? (0/1)
REQUIRED_TASK -1  # Number of task required for successful divide.

### Mutations ###

# mutations that occur during execution..
POINT_MUT_PROB  0.0     # Mutation rate (per-location per update)
COPY_MUT_PROB   0.0075  # Mutation rate (per copy).

# mutations that occur on divide...
INS_MUT_PROB    0.0     # Insertion rate (per site, applied on divide).
DEL_MUT_PROB    0.0     # Deletion rate (per site, applied on divide).
DIV_MUT_PROB    0.0     # Mutation rate (per site, applied on divide).
DIVIDE_MUT_PROB 0.0     # Mutation rate (per divide).
DIVIDE_INS_PROB 0.05    # Insertion rate (per divide).
DIVIDE_DEL_PROB 0.05    # Deletion rate (per divide).
PARENT_MUT_PROB 0.0     # Per-site, in parent, on divide

# heads based mutations
# READ_SHIFT_PROB   0.0
# READ INS_PROB     0.0
# READ_DEL_PROB     0.0
# WRITE_SHIFT_PROB  0.0
# WRITE_INS_PROB    0.0
# WRITE_DEL_PROB    0.0


### Mutation reversions ###
# these slow down avida a lot, and should be set to 0 normally.
REVERT_FATAL       0.0  # Should any mutations be reverted on birth?
REVERT_DETRIMENTAL 0.0  #   0.0 to 1.0; Probability of reversion.
REVERT_NEUTRAL     0.0
REVERT_BENEFICIAL  0.0

STERILIZE_FATAL       0.0  # Should any mutations clear (kill) the organism?
STERILIZE_DETRIMENTAL 0.0  #   0.0 to 1.0; Probability of reset.
STERILIZE_NEUTRAL     0.0
STERILIZE_BENEFICIAL  0.0

FAIL_IMPLICIT     0	# Should copies that failed *not* due to mutations
			# be eliminated?

### Time Slicing ###
AVE_TIME_SLICE 30
SLICING_METHOD 2	# 0 = CONSTANT: all organisms get default...
			# 1 = PROBABILISTIC: Run _prob_ proportional to merit.
			# 2 = INTEGRATED: Perfectly integrated deterministic.
SIZE_MERIT_METHOD 4	# 0 = off (merit is independent of size)
			# 1 = Merit proportional to copied size
			# 2 = Merit prop. to executed size
			# 3 = Merit prop. to full size
			# 4 = Merit prop. to min of executed or copied size
			# 5 = Merit prop. to sqrt of the minimum size
TASK_MERIT_METHOD 1	# 0 = No task bonuses
			# 1 = Bonus just equals the task bonus
THREAD_SLICING_METHOD 0 # 0 = One thread executed per time slice.
			# 1 = All threads executed each time slice.

MAX_LABEL_EXE_SIZE 1	# Max nops marked as executed when labels are used
MERIT_TIME 1            # 0 = Merit Calculated when task completed
		        # 1 = Merit Calculated on Divide
MAX_NUM_TASKS_REWARDED -1  # -1 = Unlimited

### Genotype Info ###
THRESHOLD 3		# Number of organisms in a genotype needed for it
			#   to be considered viable.
GENOTYPE_PRINT 0	# 0/1 (off/on) Print out all threshold genotypes?
GENOTYPE_PRINT_DOM 0	# Print out a genotype if it stays dominant for
                        #   this many updates. (0 = off)
SPECIES_THRESHOLD 2     # max failure count for organisms to be same species
SPECIES_RECORDING 0	# 1 = full, 2 = limited search (parent only)
SPECIES_PRINT 0		# 0/1 (off/on) Print out all species?
TEST_CPU_TIME_MOD 20    # Time allocated in test CPUs (multiple of length)
TRACK_MAIN_LINEAGE 1    # Track primary lineage leading to final population?

### Log Files ###
LOG_CREATURES 0		# 0/1 (off/on) toggle to print file.
LOG_GENOTYPES 0		# 0 = off, 1 = print ALL, 2 = print threshold ONLY.
LOG_THRESHOLD 0		# 0/1 (off/on) toggle to print file.
LOG_SPECIES 0		# 0/1 (off/on) toggle to print file.
LOG_LANDSCAPE 0		# 0/1 (off/on) toggle to print file.

LOG_LINEAGES 0          # 0/1 (off/on) to log advantageous mutations
# This one can slow down avida a lot. It is used to get an idea of how
# often an advantageous mutation arises, and where it goes afterwards.
# See also LINEAGE_CREATION_METHOD.

LINEAGE_CREATION_METHOD 0
# Lineage creation options are.  Works only when LOG_LINEAGES is set to 1.
#   0 = manual creation (on inject, use successive integers as lineage labels).
#   1 = when a child's (potential) fitness is higher than that of its parent.
#   2 = when a child's (potential) fitness is higher than max in population.
#   3 = when a child's (potential) fitness is higher than max in dom. lineage
#	*and* the child is in the dominant lineage, or (2)
#   4 = when a child's (potential) fitness is higher than max in dom. lineage
#	(and that of its own lineage)
#   5 = same as child's (potential) fitness is higher than that of the
#       currently dominant organism, and also than that of any organism
#       currently in the same lineage.
#   6 = when a child's (potential) fitness is higher than any organism
#       currently in the same lineage.
#   7 = when a child's (potential) fitness is higher than that of any
#       organism in its line of descent

### END ###



Index: avida/current/source/testsuites/functional_testsuites/default.tail/inst_set.default
+++ avida/current/source/testsuites/functional_testsuites/default.tail/inst_set.default
nop-A      1   # a
nop-B      1   # b
nop-C      1   # c
if-n-equ   1   # d
if-less    1   # e
pop        1   # f
push       1   # g
swap-stk   1   # h
swap       1   # i 
shift-r    1   # j
shift-l    1   # k
inc        1   # l
dec        1   # m
add        1   # n
sub        1   # o
nand       1   # p
IO         1   # q   Puts current contents of register and gets new.
h-alloc    1   # r   Allocate as much memory as organism can use.
h-divide   1   # s   Cuts off everything between the read and write heads
h-copy     1   # t   Combine h-read and h-write
h-search   1   # u   Search for matching template, set flow head & return info
               #   #   if no template, move flow-head here, set size&offset=0.
mov-head   1   # v   Move ?IP? head to flow control.
jmp-head   1   # w   Move ?IP? head by fixed amount in CX.  Set old pos in CX.
get-head   1   # x   Get position of specified head in CX.
if-label   1   # y
set-flow   1   # z   Move flow-head to address in ?CX? 

#adv-head   1
#jump-f     1
#jump-b     1
#call       1
#return     1
#if-bit-1   1
#get        1
#put        1
#h-read     1
#h-write    1
#set-head   1
#search-f   1
#search-b   1


# Works on multiple nops:  pop  push  inc  dec  IO  adv-head 

# What if we add a new head.  Search will return the location of something,
# and put the new head there.  Then set-head will move another head to that
# point.  In the case of the copy loop, it only needs to be set once and
# this will speed up the code quite a bit!

# Search with no template returns current position (abs line number) in
# genome.
Index: avida/current/source/testsuites/functional_testsuites/default.tail/organism.default
+++ avida/current/source/testsuites/functional_testsuites/default.tail/organism.default
h-alloc    # Allocate space for child
h-search   # Locate the end of the organism
nop-C      #
nop-A      #
mov-head   # Place write-head at beginning of offspring.
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
h-search   # Mark the beginning of the copy loop
h-copy     # Do the copy
if-label   # If we're done copying....
nop-C      #
nop-A      #
h-divide   #    ...divide!
mov-head   # Otherwise, loop back to the beginning of the copy loop.
nop-A      # End label.
nop-B      #

Index: avida/current/source/testsuites/functional_testsuites/default.tail/tail.exp
+++ avida/current/source/testsuites/functional_testsuites/default.tail/tail.exp
# Note: the variables 'srcdir', 'subdir', and 'tool' (among others) are
# preinitialized by dejagnu.

# The default timeout period is 10 seconds but may be set as follows:
  set timeout 30

# Give this test a name.
  set test "tail demo"

# Set the commandline that performs this test.
  set SHELLSCRIPT "$srcdir/$subdir/tail.sh $srcdir $subdir $AVIDA_BLDDIR/primitive"

# Expected output (regular expression to match the last line of
# detail_pop.100):
  set expected_output "55 49 24 1 1 99 0 0 0 100 -1 2 cccccccccccccccccccccccccccccccccccccccccutycusvabrucavcccccccccccccccccccccccccccccccccccccccccccc"

# Launch the test.  Complain if there was a problem launching.
if { [scripted_test "$tool" "$test" "$SHELLSCRIPT" "$expected_output"] != "" } {
  perror "failed to spawn \"$SHELLSCRIPT\"." 0
}

Index: avida/current/source/testsuites/functional_testsuites/default.tail/tail.sh
+++ avida/current/source/testsuites/functional_testsuites/default.tail/tail.sh
# /bin/sh

# set TESTSUITE_DIR to top directory for test scripts.
pushd $srcdir; TESTSUITE_DIR=$PWD; popd
SUBDIR=default.tail           # subdir of TESTSUITE_DIR containing this script.
AVIDA_PATH=$PWD/../../main/primitive  # path to avida executable.

# specify paths to config files.
CFG_DIR=$TESTSUITE_DIR/$SUBDIR
GENESIS_FILE=$CFG_DIR/genesis
INST_SET=$CFG_DIR/inst_set.default
EVENT_FILE=$CFG_DIR/events.cfg
ANALYZE_FILE=$CFG_DIR/analyze.cfg
ENVIRONMENT_FILE=$CFG_DIR/environment.cfg
START_CREATURE=$CFG_DIR/organism.default

# make subdirectory for storing avida's output files.
[ -d $SUBDIR ] || mkdir -p $SUBDIR
cd $SUBDIR || exit  # exit with error status if can't cd into subdir for
                    # storing avida's output files.

# run avida, and save all output to avida_run.log.
$AVIDA_PATH \
  -genesis $GENESIS_FILE \
  -set INST_SET $INST_SET \
  -set EVENT_FILE $EVENT_FILE \
  -set ANALYZE_FILE $ANALYZE_FILE \
  -set ENVIRONMENT_FILE $ENVIRONMENT_FILE \
  -set START_CREATURE $START_CREATURE \
  2>&1 > avida_run.log \
  || exit  # if avida run fails, exit with avida's error status.

# verify last line of detail_pop.100 matches contents of file
# detail_pop.100.last_line.expected.
tail -n 1 detail_pop.100 > detail_pop.100.last_line
cmp detail_pop.100.last_line $CFG_DIR/detail_pop.100.last_line.expected \
  && echo "Last line of detail_pop.100 is as expected." \
  || exit  # if last line doesn't match, exit with error status.



  # Uncomment section below for demo of test failure.

### run avida, and save all output to avida_run.log.
##$AVIDA_PATH \
##  -genesis $GENESIS_FILE \
##  -seed 0 \
##  -set INST_SET $INST_SET \
##  -set EVENT_FILE $EVENT_FILE \
##  -set ANALYZE_FILE $ANALYZE_FILE \
##  -set ENVIRONMENT_FILE $ENVIRONMENT_FILE \
##  -set START_CREATURE $START_CREATURE \
##  2>&1 > avida_run.log \
##  || exit  # if avida run fails, exit with avida's error status.
##
### verify last line of detail_pop.100 matches contents of file
### detail_pop.100.last_line.expected.
##tail -n 1 detail_pop.100 > detail_pop.100.last_line
##cmp detail_pop.100.last_line $CFG_DIR/detail_pop.100.last_line.expected \
##  && echo "Last line of detail_pop.100 is as expected." \
##  || exit  # if last line doesn't match, exit with error status.

Index: avida/current/source/testsuites/functional_testsuites/default.tail.disabled/analyze.cfg
+++ avida/current/source/testsuites/functional_testsuites/default.tail.disabled/analyze.cfg
#############################################################################
# This file is used to setup avida when it is in analysis-only mode (by
# running "avida -a".  It allows variety of methods to load organisms
# (specifying the type of each) and analyze them once loaded.
#
# See the documentation in doc/analyze_mode.html for usage, or the file
# doc/analyze_samples.html for guidelines on writing programs.
#
#############################################################################

Index: avida/current/source/testsuites/functional_testsuites/default.tail.disabled/environment.cfg
+++ avida/current/source/testsuites/functional_testsuites/default.tail.disabled/environment.cfg
##############################################################################
#
# This is the setup file for the task/resource system.  From here, you can
# setup the available resources (including their inflow and outflow rates) as
# well as the reactions that the organisms can trigger by performing tasks.
#
# This file is currently setup to reward 9 tasks, all of which use the
# "infinite" resource, which is undepletable.
#
# For information on how to use this file, see:  doc/environment.html
# For other sample environments, see:  source/support/config/ 
#
##############################################################################

REACTION  NOT  not   process:value=1.0:type=pow  requisite:max_count=1
REACTION  NAND nand  process:value=1.0:type=pow  requisite:max_count=1
REACTION  AND  and   process:value=2.0:type=pow  requisite:max_count=1
REACTION  ORN  orn   process:value=2.0:type=pow  requisite:max_count=1
REACTION  OR   or    process:value=3.0:type=pow  requisite:max_count=1
REACTION  ANDN andn  process:value=3.0:type=pow  requisite:max_count=1
REACTION  NOR  nor   process:value=4.0:type=pow  requisite:max_count=1
REACTION  XOR  xor   process:value=4.0:type=pow  requisite:max_count=1
REACTION  EQU  equ   process:value=5.0:type=pow  requisite:max_count=1

Index: avida/current/source/testsuites/functional_testsuites/default.tail.disabled/events.cfg
+++ avida/current/source/testsuites/functional_testsuites/default.tail.disabled/events.cfg
##############################################################################
#
# This is the setup file for the events system.  From here, you can
# configure any actions that you want to have happen during the course of
# an experiment, including setting the times for data collection.
#
# basic syntax:  [trigger]  [start:interval:stop]  [event] [arguments...]
#
# This file is currently setup to start off a population full of the 
# starting organism specified in genesis, and then record key information
# every 100 updates.
#
# For information on how to use this file, see:  doc/events.html
# For other sample event configurations, see:  source/support/config/
#
##############################################################################

# Print all of the standard data files...
u 0:100 print_dom                 # Save the most abundant genotypes
u 0:100:end print_average_data    # Save info about they average genotypes
u 0:100:end print_dominant_data   # Save info about most abundant genotypes
u 0:100:end print_stats_data      # Collect satistics about entire pop.
u 0:100:end print_count_data      # Count organisms, genotypes, species, etc.
u 0:100:end print_tasks_data      # Save organisms counts for each task.
u 0:100:end print_time_data       # Track time conversion (generations, etc.)
u 0:100:end print_resource_data   # Track resource abundance.

# A few data files not printed by default
# u 100:100:end print_error_data      # Std. Error on averages.
# u 100:100:end print_variance_data   # Variance on averages.
# u 100:100:end print_totals_data     # Total counts over entire run.
# u 100:100:end print_tasks_exe_data  # Num. times tasks have been executed.

# Setup the exit time and full population data collection.
u 100:100 detail_pop           # Save current state of population.
u 100:100 dump_historic_pop    # Save ancestors of current population.
u 100 exit                      # exit


Index: avida/current/source/testsuites/functional_testsuites/default.tail.disabled/genesis
+++ avida/current/source/testsuites/functional_testsuites/default.tail.disabled/genesis
#############################################################################
# This file includes all the basic run-time defines for avida.
# For more information, see doc/genesis.html
#############################################################################

VERSION_ID 2.0b7		# Do not change this value!

### Architecture Variables ###
MAX_UPDATES  -1         # Maximum updates to run simulation (-1 = no limit)
MAX_GENERATIONS -1      # Maximum generations to run simulation (-1 = no limit)
END_CONDITION_MODE 0	# End run when ...
			# 0 = MAX_UPDATES _OR_ MAX_GENERATIONS is reached
			# 1 = MAX_UPDATES _AND_ MAX_GENERATIONS is reached
WORLD-X 20		# Width of the world in Avida mode.
WORLD-Y 20		# Height of the world in Avida mode.
WORLD_GEOMETRY 2        # 1 = Bounded Grid
                        # 2 = Torus (Default)
RANDOM_SEED 1		# Random number seed. (0 for based on time)
HARDWARE_TYPE 0		# 0 = Original CPUs
			# 1 = New, Stack-based CPUs
MAX_CPU_THREADS 1	# Number of Threads CPUs can spawn

### Configuration Files ###
DEFAULT_DIR ../work/              # Directory in which config files are found
INST_SET inst_set.default         # File containing instruction set
EVENT_FILE events.cfg             # File containing list of events during run
ANALYZE_FILE analyze.cfg          # File used for analysis mode
ENVIRONMENT_FILE environment.cfg  # File that describes the environment
START_CREATURE organism.default   # Organism to seed the soup

### Reproduction ###
BIRTH_METHOD 4    # 0 = Replace random organism in neighborhood
		  # 1 = Replace oldest organism in neighborhood
		  # 2 = Replace largest Age/Merit in neighborhood
		  # 3 = Place only in empty cells in neighborhood
		  # 4 = Replace random from entire population (Mass Action)
		  # 5 = Replace oldest in entire population (like Tierra)
DEATH_METHOD 0    # 0 = Never die of old age.
		  # 1 = Die when inst executed = AGE_LIMIT (with deviation)
		  # 2 = Die when inst executed = length * AGE_LIMIT (+ dev.)
AGE_LIMIT 5000    # Modifies DEATH_METHOD
AGE_DEVIATION 0   # Modified DEATH_METHOD
ALLOC_METHOD 0    # 0 = Allocated space is set to default instruction.
                  # 1 = Set to section of dead genome (Necrophilia)
                  # 2 = Allocated space is set to random instruction.
DIVIDE_METHOD 1   # 0 = Divide leaves state of mother untouched.
                  # 1 = Divide resets state of mother
                  #     (after the divide, we have 2 children)

GENERATION_INC_METHOD 1 # 0 = Only the generation of the child is
                        #     increased on divide.
			# 1 = Both the generation of the mother and child are
			#     increased on divide (good with DIVIDE_METHOD 1).

### Divide Restrictions ####
CHILD_SIZE_RANGE 2.0	# Maximal differential between child and parent sizes.
MIN_COPIED_LINES 0.5    # Code fraction which must be copied before divide.
MIN_EXE_LINES    0.5    # Code fraction which must be executed before divide.
REQUIRE_ALLOCATE   1    # Is a an allocate required before a divide? (0/1)
REQUIRED_TASK -1  # Number of task required for successful divide.

### Mutations ###

# mutations that occur during execution..
POINT_MUT_PROB  0.0     # Mutation rate (per-location per update)
COPY_MUT_PROB   0.0075  # Mutation rate (per copy).

# mutations that occur on divide...
INS_MUT_PROB    0.0     # Insertion rate (per site, applied on divide).
DEL_MUT_PROB    0.0     # Deletion rate (per site, applied on divide).
DIV_MUT_PROB    0.0     # Mutation rate (per site, applied on divide).
DIVIDE_MUT_PROB 0.0     # Mutation rate (per divide).
DIVIDE_INS_PROB 0.05    # Insertion rate (per divide).
DIVIDE_DEL_PROB 0.05    # Deletion rate (per divide).
PARENT_MUT_PROB 0.0     # Per-site, in parent, on divide

# heads based mutations
# READ_SHIFT_PROB   0.0
# READ INS_PROB     0.0
# READ_DEL_PROB     0.0
# WRITE_SHIFT_PROB  0.0
# WRITE_INS_PROB    0.0
# WRITE_DEL_PROB    0.0


### Mutation reversions ###
# these slow down avida a lot, and should be set to 0 normally.
REVERT_FATAL       0.0  # Should any mutations be reverted on birth?
REVERT_DETRIMENTAL 0.0  #   0.0 to 1.0; Probability of reversion.
REVERT_NEUTRAL     0.0
REVERT_BENEFICIAL  0.0

STERILIZE_FATAL       0.0  # Should any mutations clear (kill) the organism?
STERILIZE_DETRIMENTAL 0.0  #   0.0 to 1.0; Probability of reset.
STERILIZE_NEUTRAL     0.0
STERILIZE_BENEFICIAL  0.0

FAIL_IMPLICIT     0	# Should copies that failed *not* due to mutations
			# be eliminated?

### Time Slicing ###
AVE_TIME_SLICE 30
SLICING_METHOD 2	# 0 = CONSTANT: all organisms get default...
			# 1 = PROBABILISTIC: Run _prob_ proportional to merit.
			# 2 = INTEGRATED: Perfectly integrated deterministic.
SIZE_MERIT_METHOD 4	# 0 = off (merit is independent of size)
			# 1 = Merit proportional to copied size
			# 2 = Merit prop. to executed size
			# 3 = Merit prop. to full size
			# 4 = Merit prop. to min of executed or copied size
			# 5 = Merit prop. to sqrt of the minimum size
TASK_MERIT_METHOD 1	# 0 = No task bonuses
			# 1 = Bonus just equals the task bonus
THREAD_SLICING_METHOD 0 # 0 = One thread executed per time slice.
			# 1 = All threads executed each time slice.

MAX_LABEL_EXE_SIZE 1	# Max nops marked as executed when labels are used
MERIT_TIME 1            # 0 = Merit Calculated when task completed
		        # 1 = Merit Calculated on Divide
MAX_NUM_TASKS_REWARDED -1  # -1 = Unlimited

### Genotype Info ###
THRESHOLD 3		# Number of organisms in a genotype needed for it
			#   to be considered viable.
GENOTYPE_PRINT 0	# 0/1 (off/on) Print out all threshold genotypes?
GENOTYPE_PRINT_DOM 0	# Print out a genotype if it stays dominant for
                        #   this many updates. (0 = off)
SPECIES_THRESHOLD 2     # max failure count for organisms to be same species
SPECIES_RECORDING 0	# 1 = full, 2 = limited search (parent only)
SPECIES_PRINT 0		# 0/1 (off/on) Print out all species?
TEST_CPU_TIME_MOD 20    # Time allocated in test CPUs (multiple of length)
TRACK_MAIN_LINEAGE 1    # Track primary lineage leading to final population?

### Log Files ###
LOG_CREATURES 0		# 0/1 (off/on) toggle to print file.
LOG_GENOTYPES 0		# 0 = off, 1 = print ALL, 2 = print threshold ONLY.
LOG_THRESHOLD 0		# 0/1 (off/on) toggle to print file.
LOG_SPECIES 0		# 0/1 (off/on) toggle to print file.
LOG_LANDSCAPE 0		# 0/1 (off/on) toggle to print file.

LOG_LINEAGES 0          # 0/1 (off/on) to log advantageous mutations
# This one can slow down avida a lot. It is used to get an idea of how
# often an advantageous mutation arises, and where it goes afterwards.
# See also LINEAGE_CREATION_METHOD.

LINEAGE_CREATION_METHOD 0
# Lineage creation options are.  Works only when LOG_LINEAGES is set to 1.
#   0 = manual creation (on inject, use successive integers as lineage labels).
#   1 = when a child's (potential) fitness is higher than that of its parent.
#   2 = when a child's (potential) fitness is higher than max in population.
#   3 = when a child's (potential) fitness is higher than max in dom. lineage
#	*and* the child is in the dominant lineage, or (2)
#   4 = when a child's (potential) fitness is higher than max in dom. lineage
#	(and that of its own lineage)
#   5 = same as child's (potential) fitness is higher than that of the
#       currently dominant organism, and also than that of any organism
#       currently in the same lineage.
#   6 = when a child's (potential) fitness is higher than any organism
#       currently in the same lineage.
#   7 = when a child's (potential) fitness is higher than that of any
#       organism in its line of descent

### END ###



Index: avida/current/source/testsuites/functional_testsuites/default.tail.disabled/inst_set.default
+++ avida/current/source/testsuites/functional_testsuites/default.tail.disabled/inst_set.default
nop-A      1   # a
nop-B      1   # b
nop-C      1   # c
if-n-equ   1   # d
if-less    1   # e
pop        1   # f
push       1   # g
swap-stk   1   # h
swap       1   # i 
shift-r    1   # j
shift-l    1   # k
inc        1   # l
dec        1   # m
add        1   # n
sub        1   # o
nand       1   # p
IO         1   # q   Puts current contents of register and gets new.
h-alloc    1   # r   Allocate as much memory as organism can use.
h-divide   1   # s   Cuts off everything between the read and write heads
h-copy     1   # t   Combine h-read and h-write
h-search   1   # u   Search for matching template, set flow head & return info
               #   #   if no template, move flow-head here, set size&offset=0.
mov-head   1   # v   Move ?IP? head to flow control.
jmp-head   1   # w   Move ?IP? head by fixed amount in CX.  Set old pos in CX.
get-head   1   # x   Get position of specified head in CX.
if-label   1   # y
set-flow   1   # z   Move flow-head to address in ?CX? 

#adv-head   1
#jump-f     1
#jump-b     1
#call       1
#return     1
#if-bit-1   1
#get        1
#put        1
#h-read     1
#h-write    1
#set-head   1
#search-f   1
#search-b   1


# Works on multiple nops:  pop  push  inc  dec  IO  adv-head 

# What if we add a new head.  Search will return the location of something,
# and put the new head there.  Then set-head will move another head to that
# point.  In the case of the copy loop, it only needs to be set once and
# this will speed up the code quite a bit!

# Search with no template returns current position (abs line number) in
# genome.
Index: avida/current/source/testsuites/functional_testsuites/default.tail.disabled/organism.default
+++ avida/current/source/testsuites/functional_testsuites/default.tail.disabled/organism.default
h-alloc    # Allocate space for child
h-search   # Locate the end of the organism
nop-C      #
nop-A      #
mov-head   # Place write-head at beginning of offspring.
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
h-search   # Mark the beginning of the copy loop
h-copy     # Do the copy
if-label   # If we're done copying....
nop-C      #
nop-A      #
h-divide   #    ...divide!
mov-head   # Otherwise, loop back to the beginning of the copy loop.
nop-A      # End label.
nop-B      #

Index: avida/current/source/testsuites/functional_testsuites/default.tail.disabled/tail.exp
+++ avida/current/source/testsuites/functional_testsuites/default.tail.disabled/tail.exp
# Note: the variables 'srcdir', 'subdir', and 'tool' (among others) are
# preinitialized by dejagnu.

# The default timeout period is 10 seconds but may be set as follows:
  set timeout 30

# Give this test a name.
  set test "tail demo"

# Set the commandline that performs this test.
  set SHELLSCRIPT "$srcdir/$subdir/tail.sh $srcdir $subdir $AVIDA_BLDDIR/primitive"

# Expected output (regular expression to match the last line of
# detail_pop.100):
  set expected_output "55 49 24 1 1 99 0 0 0 100 -1 2 cccccccccccccccccccccccccccccccccccccccccutycusvabrucavcccccccccccccccccccccccccccccccccccccccccccc"

# Launch the test.  Complain if there was a problem launching.
if { [scripted_test "$tool" "$test" "$SHELLSCRIPT" "$expected_output"] != "" } {
  perror "failed to spawn \"$SHELLSCRIPT\"." 0
}

Index: avida/current/source/testsuites/functional_testsuites/default.tail.disabled/tail.sh
+++ avida/current/source/testsuites/functional_testsuites/default.tail.disabled/tail.sh
# /bin/sh

# read command-line arguments:
TESTSUITE_DIR=$1       # path to top directory for test scripts.
SUBDIR=$2              # subdir of TESTSUITE_DIR containing this script.
AVIDA_PATH=$3          # path to avida executable.

# specify paths to config files.
CFG_DIR=$TESTSUITE_DIR/$SUBDIR
GENESIS_FILE=$CFG_DIR/genesis
INST_SET=$CFG_DIR/inst_set.default
EVENT_FILE=$CFG_DIR/events.cfg
ANALYZE_FILE=$CFG_DIR/analyze.cfg
ENVIRONMENT_FILE=$CFG_DIR/environment.cfg
START_CREATURE=$CFG_DIR/organism.default

# make subdirectory for storing avida's output files.
[ -d $SUBDIR ] || mkdir -p $SUBDIR
cd $SUBDIR

# run avida, and save all output to avida_run.log.
$AVIDA_PATH \
  -genesis $GENESIS_FILE \
  -set INST_SET $INST_SET \
  -set EVENT_FILE $EVENT_FILE \
  -set ANALYZE_FILE $ANALYZE_FILE \
  -set ENVIRONMENT_FILE $ENVIRONMENT_FILE \
  -set START_CREATURE $START_CREATURE \
  2>&1 > avida_run.log

# send the last line of detail_pop.100 back to the testdriver for
# verification.
echo "last line of output file detail_pop.100:"
tail -n 1 detail_pop.100

# sleeping for one second gives dejagnu/expect time to react.
sleep 1;

Index: avida/current/source/testsuites/functional_testsuites/tedious.tail.disabled/analyze.cfg
+++ avida/current/source/testsuites/functional_testsuites/tedious.tail.disabled/analyze.cfg
#############################################################################
# This file is used to setup avida when it is in analysis-only mode (by
# running "avida -a".  It allows variety of methods to load organisms
# (specifying the type of each) and analyze them once loaded.
#
# See the documentation in doc/analyze_mode.html for usage, or the file
# doc/analyze_samples.html for guidelines on writing programs.
#
#############################################################################

Index: avida/current/source/testsuites/functional_testsuites/tedious.tail.disabled/environment.cfg
+++ avida/current/source/testsuites/functional_testsuites/tedious.tail.disabled/environment.cfg
##############################################################################
#
# This is the setup file for the task/resource system.  From here, you can
# setup the available resources (including their inflow and outflow rates) as
# well as the reactions that the organisms can trigger by performing tasks.
#
# This file is currently setup to reward 9 tasks, all of which use the
# "infinite" resource, which is undepletable.
#
# For information on how to use this file, see:  doc/environment.html
# For other sample environments, see:  source/support/config/ 
#
##############################################################################

REACTION  NOT  not   process:value=1.0:type=pow  requisite:max_count=1
REACTION  NAND nand  process:value=1.0:type=pow  requisite:max_count=1
REACTION  AND  and   process:value=2.0:type=pow  requisite:max_count=1
REACTION  ORN  orn   process:value=2.0:type=pow  requisite:max_count=1
REACTION  OR   or    process:value=3.0:type=pow  requisite:max_count=1
REACTION  ANDN andn  process:value=3.0:type=pow  requisite:max_count=1
REACTION  NOR  nor   process:value=4.0:type=pow  requisite:max_count=1
REACTION  XOR  xor   process:value=4.0:type=pow  requisite:max_count=1
REACTION  EQU  equ   process:value=5.0:type=pow  requisite:max_count=1

Index: avida/current/source/testsuites/functional_testsuites/tedious.tail.disabled/events.cfg
+++ avida/current/source/testsuites/functional_testsuites/tedious.tail.disabled/events.cfg
##############################################################################
#
# This is the setup file for the events system.  From here, you can
# configure any actions that you want to have happen during the course of
# an experiment, including setting the times for data collection.
#
# basic syntax:  [trigger]  [start:interval:stop]  [event] [arguments...]
#
# This file is currently setup to start off a population full of the 
# starting organism specified in genesis, and then record key information
# every 100 updates.
#
# For information on how to use this file, see:  doc/events.html
# For other sample event configurations, see:  source/support/config/
#
##############################################################################

# Print all of the standard data files...
u 0:100 print_dom                 # Save the most abundant genotypes
u 0:100:end print_average_data    # Save info about they average genotypes
u 0:100:end print_dominant_data   # Save info about most abundant genotypes
u 0:100:end print_stats_data      # Collect satistics about entire pop.
u 0:100:end print_count_data      # Count organisms, genotypes, species, etc.
u 0:100:end print_tasks_data      # Save organisms counts for each task.
u 0:100:end print_time_data       # Track time conversion (generations, etc.)
u 0:100:end print_resource_data   # Track resource abundance.

# A few data files not printed by default
# u 100:100:end print_error_data      # Std. Error on averages.
# u 100:100:end print_variance_data   # Variance on averages.
# u 100:100:end print_totals_data     # Total counts over entire run.
# u 100:100:end print_tasks_exe_data  # Num. times tasks have been executed.

# Setup the exit time and full population data collection.
u 100:100 detail_pop           # Save current state of population.
u 100:100 dump_historic_pop    # Save ancestors of current population.
u 100 exit                      # exit


Index: avida/current/source/testsuites/functional_testsuites/tedious.tail.disabled/genesis
+++ avida/current/source/testsuites/functional_testsuites/tedious.tail.disabled/genesis
#############################################################################
# This file includes all the basic run-time defines for avida.
# For more information, see doc/genesis.html
#############################################################################

VERSION_ID 2.0b7		# Do not change this value!

### Architecture Variables ###
MAX_UPDATES  -1         # Maximum updates to run simulation (-1 = no limit)
MAX_GENERATIONS -1      # Maximum generations to run simulation (-1 = no limit)
END_CONDITION_MODE 0	# End run when ...
			# 0 = MAX_UPDATES _OR_ MAX_GENERATIONS is reached
			# 1 = MAX_UPDATES _AND_ MAX_GENERATIONS is reached
WORLD-X 20		# Width of the world in Avida mode.
WORLD-Y 20		# Height of the world in Avida mode.
WORLD_GEOMETRY 2        # 1 = Bounded Grid
                        # 2 = Torus (Default)
RANDOM_SEED 1		# Random number seed. (0 for based on time)
HARDWARE_TYPE 0		# 0 = Original CPUs
			# 1 = New, Stack-based CPUs
MAX_CPU_THREADS 1	# Number of Threads CPUs can spawn

### Configuration Files ###
DEFAULT_DIR ../work/              # Directory in which config files are found
INST_SET inst_set.default         # File containing instruction set
EVENT_FILE events.cfg             # File containing list of events during run
ANALYZE_FILE analyze.cfg          # File used for analysis mode
ENVIRONMENT_FILE environment.cfg  # File that describes the environment
START_CREATURE organism.default   # Organism to seed the soup

### Reproduction ###
BIRTH_METHOD 4    # 0 = Replace random organism in neighborhood
		  # 1 = Replace oldest organism in neighborhood
		  # 2 = Replace largest Age/Merit in neighborhood
		  # 3 = Place only in empty cells in neighborhood
		  # 4 = Replace random from entire population (Mass Action)
		  # 5 = Replace oldest in entire population (like Tierra)
DEATH_METHOD 0    # 0 = Never die of old age.
		  # 1 = Die when inst executed = AGE_LIMIT (with deviation)
		  # 2 = Die when inst executed = length * AGE_LIMIT (+ dev.)
AGE_LIMIT 5000    # Modifies DEATH_METHOD
AGE_DEVIATION 0   # Modified DEATH_METHOD
ALLOC_METHOD 0    # 0 = Allocated space is set to default instruction.
                  # 1 = Set to section of dead genome (Necrophilia)
                  # 2 = Allocated space is set to random instruction.
DIVIDE_METHOD 1   # 0 = Divide leaves state of mother untouched.
                  # 1 = Divide resets state of mother
                  #     (after the divide, we have 2 children)

GENERATION_INC_METHOD 1 # 0 = Only the generation of the child is
                        #     increased on divide.
			# 1 = Both the generation of the mother and child are
			#     increased on divide (good with DIVIDE_METHOD 1).

### Divide Restrictions ####
CHILD_SIZE_RANGE 2.0	# Maximal differential between child and parent sizes.
MIN_COPIED_LINES 0.5    # Code fraction which must be copied before divide.
MIN_EXE_LINES    0.5    # Code fraction which must be executed before divide.
REQUIRE_ALLOCATE   1    # Is a an allocate required before a divide? (0/1)
REQUIRED_TASK -1  # Number of task required for successful divide.

### Mutations ###

# mutations that occur during execution..
POINT_MUT_PROB  0.0     # Mutation rate (per-location per update)
COPY_MUT_PROB   0.0075  # Mutation rate (per copy).

# mutations that occur on divide...
INS_MUT_PROB    0.0     # Insertion rate (per site, applied on divide).
DEL_MUT_PROB    0.0     # Deletion rate (per site, applied on divide).
DIV_MUT_PROB    0.0     # Mutation rate (per site, applied on divide).
DIVIDE_MUT_PROB 0.0     # Mutation rate (per divide).
DIVIDE_INS_PROB 0.05    # Insertion rate (per divide).
DIVIDE_DEL_PROB 0.05    # Deletion rate (per divide).
PARENT_MUT_PROB 0.0     # Per-site, in parent, on divide

# heads based mutations
# READ_SHIFT_PROB   0.0
# READ INS_PROB     0.0
# READ_DEL_PROB     0.0
# WRITE_SHIFT_PROB  0.0
# WRITE_INS_PROB    0.0
# WRITE_DEL_PROB    0.0


### Mutation reversions ###
# these slow down avida a lot, and should be set to 0 normally.
REVERT_FATAL       0.0  # Should any mutations be reverted on birth?
REVERT_DETRIMENTAL 0.0  #   0.0 to 1.0; Probability of reversion.
REVERT_NEUTRAL     0.0
REVERT_BENEFICIAL  0.0

STERILIZE_FATAL       0.0  # Should any mutations clear (kill) the organism?
STERILIZE_DETRIMENTAL 0.0  #   0.0 to 1.0; Probability of reset.
STERILIZE_NEUTRAL     0.0
STERILIZE_BENEFICIAL  0.0

FAIL_IMPLICIT     0	# Should copies that failed *not* due to mutations
			# be eliminated?

### Time Slicing ###
AVE_TIME_SLICE 30
SLICING_METHOD 2	# 0 = CONSTANT: all organisms get default...
			# 1 = PROBABILISTIC: Run _prob_ proportional to merit.
			# 2 = INTEGRATED: Perfectly integrated deterministic.
SIZE_MERIT_METHOD 4	# 0 = off (merit is independent of size)
			# 1 = Merit proportional to copied size
			# 2 = Merit prop. to executed size
			# 3 = Merit prop. to full size
			# 4 = Merit prop. to min of executed or copied size
			# 5 = Merit prop. to sqrt of the minimum size
TASK_MERIT_METHOD 1	# 0 = No task bonuses
			# 1 = Bonus just equals the task bonus
THREAD_SLICING_METHOD 0 # 0 = One thread executed per time slice.
			# 1 = All threads executed each time slice.

MAX_LABEL_EXE_SIZE 1	# Max nops marked as executed when labels are used
MERIT_TIME 1            # 0 = Merit Calculated when task completed
		        # 1 = Merit Calculated on Divide
MAX_NUM_TASKS_REWARDED -1  # -1 = Unlimited

### Genotype Info ###
THRESHOLD 3		# Number of organisms in a genotype needed for it
			#   to be considered viable.
GENOTYPE_PRINT 0	# 0/1 (off/on) Print out all threshold genotypes?
GENOTYPE_PRINT_DOM 0	# Print out a genotype if it stays dominant for
                        #   this many updates. (0 = off)
SPECIES_THRESHOLD 2     # max failure count for organisms to be same species
SPECIES_RECORDING 0	# 1 = full, 2 = limited search (parent only)
SPECIES_PRINT 0		# 0/1 (off/on) Print out all species?
TEST_CPU_TIME_MOD 20    # Time allocated in test CPUs (multiple of length)
TRACK_MAIN_LINEAGE 1    # Track primary lineage leading to final population?

### Log Files ###
LOG_CREATURES 0		# 0/1 (off/on) toggle to print file.
LOG_GENOTYPES 0		# 0 = off, 1 = print ALL, 2 = print threshold ONLY.
LOG_THRESHOLD 0		# 0/1 (off/on) toggle to print file.
LOG_SPECIES 0		# 0/1 (off/on) toggle to print file.
LOG_LANDSCAPE 0		# 0/1 (off/on) toggle to print file.

LOG_LINEAGES 0          # 0/1 (off/on) to log advantageous mutations
# This one can slow down avida a lot. It is used to get an idea of how
# often an advantageous mutation arises, and where it goes afterwards.
# See also LINEAGE_CREATION_METHOD.

LINEAGE_CREATION_METHOD 0
# Lineage creation options are.  Works only when LOG_LINEAGES is set to 1.
#   0 = manual creation (on inject, use successive integers as lineage labels).
#   1 = when a child's (potential) fitness is higher than that of its parent.
#   2 = when a child's (potential) fitness is higher than max in population.
#   3 = when a child's (potential) fitness is higher than max in dom. lineage
#	*and* the child is in the dominant lineage, or (2)
#   4 = when a child's (potential) fitness is higher than max in dom. lineage
#	(and that of its own lineage)
#   5 = same as child's (potential) fitness is higher than that of the
#       currently dominant organism, and also than that of any organism
#       currently in the same lineage.
#   6 = when a child's (potential) fitness is higher than any organism
#       currently in the same lineage.
#   7 = when a child's (potential) fitness is higher than that of any
#       organism in its line of descent

### END ###



Index: avida/current/source/testsuites/functional_testsuites/tedious.tail.disabled/inst_set.default
+++ avida/current/source/testsuites/functional_testsuites/tedious.tail.disabled/inst_set.default
nop-A      1   # a
nop-B      1   # b
nop-C      1   # c
if-n-equ   1   # d
if-less    1   # e
pop        1   # f
push       1   # g
swap-stk   1   # h
swap       1   # i 
shift-r    1   # j
shift-l    1   # k
inc        1   # l
dec        1   # m
add        1   # n
sub        1   # o
nand       1   # p
IO         1   # q   Puts current contents of register and gets new.
h-alloc    1   # r   Allocate as much memory as organism can use.
h-divide   1   # s   Cuts off everything between the read and write heads
h-copy     1   # t   Combine h-read and h-write
h-search   1   # u   Search for matching template, set flow head & return info
               #   #   if no template, move flow-head here, set size&offset=0.
mov-head   1   # v   Move ?IP? head to flow control.
jmp-head   1   # w   Move ?IP? head by fixed amount in CX.  Set old pos in CX.
get-head   1   # x   Get position of specified head in CX.
if-label   1   # y
set-flow   1   # z   Move flow-head to address in ?CX? 

#adv-head   1
#jump-f     1
#jump-b     1
#call       1
#return     1
#if-bit-1   1
#get        1
#put        1
#h-read     1
#h-write    1
#set-head   1
#search-f   1
#search-b   1


# Works on multiple nops:  pop  push  inc  dec  IO  adv-head 

# What if we add a new head.  Search will return the location of something,
# and put the new head there.  Then set-head will move another head to that
# point.  In the case of the copy loop, it only needs to be set once and
# this will speed up the code quite a bit!

# Search with no template returns current position (abs line number) in
# genome.
Index: avida/current/source/testsuites/functional_testsuites/tedious.tail.disabled/organism.default
+++ avida/current/source/testsuites/functional_testsuites/tedious.tail.disabled/organism.default
h-alloc    # Allocate space for child
h-search   # Locate the end of the organism
nop-C      #
nop-A      #
mov-head   # Place write-head at beginning of offspring.
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
nop-C      #
h-search   # Mark the beginning of the copy loop
h-copy     # Do the copy
if-label   # If we're done copying....
nop-C      #
nop-A      #
h-divide   #    ...divide!
mov-head   # Otherwise, loop back to the beginning of the copy loop.
nop-A      # End label.
nop-B      #

Index: avida/current/source/testsuites/functional_testsuites/tedious.tail.disabled/tail.exp
+++ avida/current/source/testsuites/functional_testsuites/tedious.tail.disabled/tail.exp
# Note: the variables 'srcdir', 'subdir', and 'tool' (among others) are
# preinitialized by dejagnu.

# The default timeout period is 10 seconds but may be set as follows:
  set timeout 30

# Give this test a name.
  set test "tedious tail demo"

# Set the commandline that performs this test.
  set SHELLSCRIPT "$srcdir/$subdir/tail.sh $srcdir $subdir $AVIDA_BLDDIR/primitive"

# Expected output (regular expression to match the last line of
# detail_pop.100):
  set expected_output "55 49 24 1 1 99 0 0 0 100 -1 2 cccccccccccccccccccccccccccccccccccccccccutycusvabrucavcccccccccccccccccccccccccccccccccccccccccccc"

# Launch the test.  Complain if there was a problem launching.
if { [scripted_test "$tool" "$test" "$SHELLSCRIPT" "$expected_output"] != "" } {
  perror "failed to spawn \"$SHELLSCRIPT\"." 0
}

Index: avida/current/source/testsuites/functional_testsuites/tedious.tail.disabled/tail.sh
+++ avida/current/source/testsuites/functional_testsuites/tedious.tail.disabled/tail.sh
# /bin/sh

# read command-line arguments:
TESTSUITE_DIR=$1       # path to top directory for test scripts.
SUBDIR=$2              # subdir of TESTSUITE_DIR containing this script.
AVIDA_PATH=$3          # path to avida executable.

# specify paths to config files.
CFG_DIR=$TESTSUITE_DIR/$SUBDIR
GENESIS_FILE=$CFG_DIR/genesis
INST_SET=$CFG_DIR/inst_set.default
EVENT_FILE=$CFG_DIR/events.cfg
ANALYZE_FILE=$CFG_DIR/analyze.cfg
ENVIRONMENT_FILE=$CFG_DIR/environment.cfg
START_CREATURE=$CFG_DIR/organism.default

# make subdirectory for storing avida's output files.
[ -d $SUBDIR ] || mkdir -p $SUBDIR
cd $SUBDIR

# run avida, and save all output to avida_run.log.
$AVIDA_PATH \
  -genesis $GENESIS_FILE \
  -set INST_SET $INST_SET \
  -set EVENT_FILE $EVENT_FILE \
  -set ANALYZE_FILE $ANALYZE_FILE \
  -set ENVIRONMENT_FILE $ENVIRONMENT_FILE \
  -set START_CREATURE $START_CREATURE \
  2>&1 > avida_run.log

# send the last line of detail_pop.100 back to the testdriver for
# verification.
echo "last line of output file detail_pop.100:"
tail -n 1 detail_pop.100

# sleeping for one second gives dejagnu/expect time to react.
sleep 1;

Index: avida/current/source/testsuites/unit_testsuites/4stack_head.t.cc
+++ avida/current/source/testsuites/unit_testsuites/4stack_head.t.cc
#include <iostream>

#ifndef FOURSTACK_HEAD_HH
#include "4stack_head.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/Makefile.am
+++ avida/current/source/testsuites/unit_testsuites/Makefile.am

SUBDIRS = level_0 level_1

SOURCE_DIR = $(srcdir)/../..
INCLUDES = \
	-I$(SOURCE_DIR) \
	-I$(SOURCE_DIR)/event \
	-I$(SOURCE_DIR)/cpu \
	-I$(SOURCE_DIR)/tools \
	-I$(SOURCE_DIR)/main \
	-I$(SOURCE_DIR)/third-party

BLD_DIR = ../..
UNITTEST_LIBS = \
	$(BLD_DIR)/event/libevent.a \
	$(BLD_DIR)/cpu/libcpu.a \
	$(BLD_DIR)/tools/libtools.a \
	$(BLD_DIR)/main/libmain.a \
	$(BLD_DIR)/third-party/trio/libtrio.a \
  $(BLD_DIR)/third-party/yaktest/libyaktest.a \
  $(BLD_DIR)/third-party/mockpp/libmockpp.a \
  $(BLD_DIR)/third-party/mockpp/compat/libcompat.a \
  $(BLD_DIR)/third-party/mockpp/util/libutil.a

LINK = $(CXXLINK)
LDADD = $(UNITTEST_LIBS)
SUFFIXES = .cc
cc.o:
	$(CXXCOMPILE) -c $<
template_t_SOURCES = template.t.cc

check_PROGRAMS = $(TESTSUITES)
TESTS = $(TESTSUITES)

TESTSUITES = \
	template.t \
	\
  4stack_head.t \
  analyze.t \
  analyze_command.t \
  analyze_command_def.t \
  analyze_command_def_base.t \
  analyze_flow_command.t \
  analyze_flow_command_def.t \
  analyze_function.t \
  analyze_genotype.t \
  analyze_util.t \
  avida.t \
  avida_driver_analyze.t \
  avida_driver_base.t \
  avida_driver_population.t \
  avida_triggers.t \
  birth_chamber.t \
  block_struct.t \
  callback_util.t \
  config.t \
  const_schedule.t \
  cpu_head.t \
  cpu_memory.t \
  cpu_stack.t \
  cpu_test_info.t \
  data_entry.t \
  data_file.t \
  data_file_manager.t \
  data_manager_base.t \
  default_message_display.t \
  environment.t \
  event.t \
  event_factory.t \
  event_factory_manager.t \
  event_list.t \
  event_list_entry.t \
  event_list_iterator.t \
  file.t \
  fitness_matrix.t \
  fixed_coords.t \
  functions.t \
  genebank.t \
  genesis.t \
  genome.t \
  genome_util.t \
  genotype.t \
  genotype_batch.t \
  genotype_birth_data.t \
  genotype_control.t \
  hardware_4stack.t \
  hardware_4stack_thread.t \
  hardware_base.t \
  hardware_cpu.t \
  hardware_cpu_thread.t \
  hardware_factory.t \
  hardware_util.t \
  help_alias.t \
  help_entry.t \
  help_full_entry.t \
  help_manager.t \
  help_type.t \
  histogram.t \
  indexed_block_struct.t \
  init_file.t \
  inject_genebank.t \
  inject_genotype.t \
  inject_genotype_birth_data.t \
  inject_genotype_control.t \
  inject_genotype_element.t \
  inject_genotype_queue.t \
  inst_lib_base.t \
  inst_set.t \
  inst_util.t \
  integrated_schedule.t \
  integrated_schedule_node.t \
  landscape.t \
  lineage.t \
  lineage_control.t \
  local_mutations.t \
  message_class.t \
  message_closure.t \
  message_display.t \
  message_type.t \
  mutation.t \
  mutation_lib.t \
  mutation_rates.t \
  mx_code_array.t \
  my_code_array_less_than.t \
  org_message.t \
  organism.t \
  phenotype.t \
  population.t \
  population_cell.t \
  population_event.t \
  population_event_factory.t \
  population_interface.t \
  prob_schedule.t \
  random.t \
  reaction.t \
  reaction_lib.t \
  reaction_process.t \
  reaction_result.t \
  ref_block.t \
  resource.t \
  resource_count.t \
  resource_lib.t \
  running_average.t \
  scaled_block.t \
  schedule.t \
  spatial_count_elem.t \
  spatial_res_count.t \
  species.t \
  species_control.t \
  species_queue.t \
  stats.t \
  string.t \
  string_iterator.t \
  string_list.t \
  string_util.t \
  tArgDataEntry.t \
  tArray.t \
  tBuffer.t \
  tDataEntry.t \
  tDataEntryBase.t \
  tDataEntryCommand.t \
  tDataManager.t \
  tDictionary.t \
  tList.t \
  tMatrix.t \
  tVector.t \
  task_entry.t \
  task_lib.t \
  test_cpu.t \
  test_util.t \
  tools.t \
  uint.t \
  weighted_index.t


Index: avida/current/source/testsuites/unit_testsuites/analyze.t.cc
+++ avida/current/source/testsuites/unit_testsuites/analyze.t.cc
#include <iostream>

#ifndef ANALYZE_HH
#include "analyze.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/analyze_command.t.cc
+++ avida/current/source/testsuites/unit_testsuites/analyze_command.t.cc
#include <iostream>

#ifndef ANALYZE_COMMAND_HH
#include "analyze_command.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/analyze_command_def.t.cc
+++ avida/current/source/testsuites/unit_testsuites/analyze_command_def.t.cc
#include <iostream>

#ifndef ANALYZE_COMMAND_DEF_HH
#include "analyze_command_def.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/analyze_command_def_base.t.cc
+++ avida/current/source/testsuites/unit_testsuites/analyze_command_def_base.t.cc
#include <iostream>

#ifndef ANALYZE_COMMAND_DEF_BASE_HH
#include "analyze_command_def_base.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/analyze_flow_command.t.cc
+++ avida/current/source/testsuites/unit_testsuites/analyze_flow_command.t.cc
#include <iostream>

#ifndef ANALYZE_FLOW_COMMAND_HH
#include "analyze_flow_command.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/analyze_flow_command_def.t.cc
+++ avida/current/source/testsuites/unit_testsuites/analyze_flow_command_def.t.cc
#include <iostream>

#ifndef ANALYZE_FLOW_COMMAND_DEF_HH
#include "analyze_flow_command_def.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/analyze_function.t.cc
+++ avida/current/source/testsuites/unit_testsuites/analyze_function.t.cc
#include <iostream>

#ifndef ANALYZE_FUNCTION_HH
#include "analyze_function.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/analyze_genotype.t.cc
+++ avida/current/source/testsuites/unit_testsuites/analyze_genotype.t.cc
#include <iostream>

#ifndef ANALYZE_GENOTYPE_HH
#include "analyze_genotype.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/analyze_util.t.cc
+++ avida/current/source/testsuites/unit_testsuites/analyze_util.t.cc
#include <iostream>

#ifndef ANALYZE_UTIL_HH
#include "analyze_util.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/avida.t.cc
+++ avida/current/source/testsuites/unit_testsuites/avida.t.cc
#ifndef AVIDA_HH
#include "avida.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/avida_driver_analyze.t.cc
+++ avida/current/source/testsuites/unit_testsuites/avida_driver_analyze.t.cc
#include <iostream>

#ifndef AVIDA_DRIVER_ANALYZE_HH
#include "avida_driver_analyze.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/avida_driver_base.t.cc
+++ avida/current/source/testsuites/unit_testsuites/avida_driver_base.t.cc
#include <iostream>

#ifndef AVIDA_DRIVER_BASE_HH
#include "avida_driver_base.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/avida_driver_population.t.cc
+++ avida/current/source/testsuites/unit_testsuites/avida_driver_population.t.cc
#include <iostream>

#ifndef AVIDA_DRIVER_POPULATION_HH
#include "avida_driver_population.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/avida_triggers.t.cc
+++ avida/current/source/testsuites/unit_testsuites/avida_triggers.t.cc
#ifndef AVIDA_TRIGGERS_HH
#include "avida_triggers.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/birth_chamber.t.cc
+++ avida/current/source/testsuites/unit_testsuites/birth_chamber.t.cc
#include <iostream>

#ifndef BIRTH_CHAMBER_HH
#include "birth_chamber.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/block_struct.t.cc
+++ avida/current/source/testsuites/unit_testsuites/block_struct.t.cc
#include <iostream>

#ifndef BLOCK_STRUCT_HH
#include "block_struct.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/callback_util.t.cc
+++ avida/current/source/testsuites/unit_testsuites/callback_util.t.cc
#include <iostream>

#ifndef CALLBACK_UTIL_HH
#include "callback_util.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/config.t.cc
+++ avida/current/source/testsuites/unit_testsuites/config.t.cc
#include <iostream>

#ifndef CONFIG_HH
#include "config.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/const_schedule.t.cc
+++ avida/current/source/testsuites/unit_testsuites/const_schedule.t.cc
#include <iostream>

#ifndef CONST_SCHEDULE_HH
#include "const_schedule.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/cpu_head.t.cc
+++ avida/current/source/testsuites/unit_testsuites/cpu_head.t.cc
#include <iostream>

#ifndef CPU_HEAD_HH
#include "cpu_head.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/cpu_memory.t.cc
+++ avida/current/source/testsuites/unit_testsuites/cpu_memory.t.cc
#include <iostream>

#ifndef CPU_MEMORY_HH
#include "cpu_memory.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/cpu_stack.t.cc
+++ avida/current/source/testsuites/unit_testsuites/cpu_stack.t.cc
#include <iostream>

#ifndef CPU_STACK_HH
#include "cpu_stack.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/cpu_test_info.t.cc
+++ avida/current/source/testsuites/unit_testsuites/cpu_test_info.t.cc
#include <iostream>

#ifndef CPU_TEST_INFO_HH
#include "cpu_test_info.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/data_entry.t.cc
+++ avida/current/source/testsuites/unit_testsuites/data_entry.t.cc
#include <iostream>

#ifndef DATA_ENTRY_HH
#include "data_entry.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/data_file.t.cc
+++ avida/current/source/testsuites/unit_testsuites/data_file.t.cc
#include <iostream>

#ifndef DATA_FILE_HH
#include "data_file.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/data_file_manager.t.cc
+++ avida/current/source/testsuites/unit_testsuites/data_file_manager.t.cc
#include <iostream>

#ifndef DATA_FILE_MANAGER_HH
#include "data_file_manager.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/data_manager_base.t.cc
+++ avida/current/source/testsuites/unit_testsuites/data_manager_base.t.cc
#include <iostream>

#ifndef DATA_MANAGER_BASE_HH
#include "data_manager_base.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/default_message_display.t.cc
+++ avida/current/source/testsuites/unit_testsuites/default_message_display.t.cc
#include <iostream>

#ifndef DEFAULT_MESSAGE_DISPLAY_HH
#include "default_message_display.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/environment.t.cc
+++ avida/current/source/testsuites/unit_testsuites/environment.t.cc
#include <iostream>

#ifndef ENVIRONMENT_HH
#include "environment.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/event.t.cc
+++ avida/current/source/testsuites/unit_testsuites/event.t.cc
#include <iostream>

#ifndef EVENT_HH
#include "event.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/event_factory.t.cc
+++ avida/current/source/testsuites/unit_testsuites/event_factory.t.cc
#include <iostream>

#ifndef EVENT_FACTORY_HH
#include "event_factory.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/event_factory_manager.t.cc
+++ avida/current/source/testsuites/unit_testsuites/event_factory_manager.t.cc
#include <iostream>

#ifndef EVENT_FACTORY_MANAGER_HH
#include "event_factory_manager.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/event_list.t.cc
+++ avida/current/source/testsuites/unit_testsuites/event_list.t.cc
#include <iostream>

#ifndef EVENT_LIST_HH
#include "event_list.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/event_list_entry.t.cc
+++ avida/current/source/testsuites/unit_testsuites/event_list_entry.t.cc
#include <iostream>

#ifndef EVENT_LIST_ENTRY_HH
#include "event_list_entry.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/event_list_iterator.t.cc
+++ avida/current/source/testsuites/unit_testsuites/event_list_iterator.t.cc
#include <iostream>

#ifndef EVENT_LIST_ITERATOR_HH
#include "event_list_iterator.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/file.t.cc
+++ avida/current/source/testsuites/unit_testsuites/file.t.cc
#include <iostream>

#ifndef FILE_HH
#include "file.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/fitness_matrix.t.cc
+++ avida/current/source/testsuites/unit_testsuites/fitness_matrix.t.cc
#include <iostream>

#ifndef FITNESS_MATRIX_HH
#include "fitness_matrix.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/fixed_coords.t.cc
+++ avida/current/source/testsuites/unit_testsuites/fixed_coords.t.cc
#include <iostream>

#ifndef FIXED_COORDS_HH
#include "fixed_coords.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/functions.t.cc
+++ avida/current/source/testsuites/unit_testsuites/functions.t.cc
#include <iostream>

#ifndef FUNCTIONS_HH
#include "functions.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/genebank.t.cc
+++ avida/current/source/testsuites/unit_testsuites/genebank.t.cc
#include <iostream>

#ifndef GENEBANK_HH
#include "genebank.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/genesis.t.cc
+++ avida/current/source/testsuites/unit_testsuites/genesis.t.cc
#include <iostream>

#ifndef GENESIS_HH
#include "genesis.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/genome.t.cc
+++ avida/current/source/testsuites/unit_testsuites/genome.t.cc
#ifndef GENOME_HH
#include "genome.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/genome_util.t.cc
+++ avida/current/source/testsuites/unit_testsuites/genome_util.t.cc
#ifndef GENOME_UTIL_HH
#include "genome_util.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/genotype.t.cc
+++ avida/current/source/testsuites/unit_testsuites/genotype.t.cc
#ifndef GENOTYPE_HH
#include "genotype.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/genotype_batch.t.cc
+++ avida/current/source/testsuites/unit_testsuites/genotype_batch.t.cc
#include <iostream>

#ifndef GENOTYPE_BATCH_HH
#include "genotype_batch.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/genotype_birth_data.t.cc
+++ avida/current/source/testsuites/unit_testsuites/genotype_birth_data.t.cc
#ifndef GENOTYPE_BIRTH_DATA_HH
#include "genotype_birth_data.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/genotype_control.t.cc
+++ avida/current/source/testsuites/unit_testsuites/genotype_control.t.cc
#include <iostream>

#ifndef GENOTYPE_CONTROL_HH
#include "genotype_control.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/hardware_4stack.t.cc
+++ avida/current/source/testsuites/unit_testsuites/hardware_4stack.t.cc
#include <iostream>

#ifndef HARDWARE_4STACK_HH
#include "hardware_4stack.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/hardware_4stack_thread.t.cc
+++ avida/current/source/testsuites/unit_testsuites/hardware_4stack_thread.t.cc
#include <iostream>

#ifndef HARDWARE_4STACK_THREAD_HH
#include "hardware_4stack_thread.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/hardware_base.t.cc
+++ avida/current/source/testsuites/unit_testsuites/hardware_base.t.cc
#include <iostream>

#ifndef HARDWARE_BASE_HH
#include "hardware_base.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/hardware_cpu.t.cc
+++ avida/current/source/testsuites/unit_testsuites/hardware_cpu.t.cc
#include <iostream>

#ifndef HARDWARE_CPU_HH
#include "hardware_cpu.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/hardware_cpu_thread.t.cc
+++ avida/current/source/testsuites/unit_testsuites/hardware_cpu_thread.t.cc
#include <iostream>

#ifndef HARDWARE_CPU_THREAD_HH
#include "hardware_cpu_thread.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/hardware_factory.t.cc
+++ avida/current/source/testsuites/unit_testsuites/hardware_factory.t.cc
#include <iostream>

#ifndef HARDWARE_FACTORY_HH
#include "hardware_factory.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/hardware_util.t.cc
+++ avida/current/source/testsuites/unit_testsuites/hardware_util.t.cc
#include <iostream>

#ifndef HARDWARE_UTIL_HH
#include "hardware_util.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/help_alias.t.cc
+++ avida/current/source/testsuites/unit_testsuites/help_alias.t.cc
#include <iostream>

#ifndef HELP_ALIAS_HH
#include "tools/help_alias.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/help_entry.t.cc
+++ avida/current/source/testsuites/unit_testsuites/help_entry.t.cc
#include <iostream>

#ifndef HELP_ENTRY_HH
#include "tools/help_entry.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/help_full_entry.t.cc
+++ avida/current/source/testsuites/unit_testsuites/help_full_entry.t.cc
#include <iostream>

#ifndef HELP_FULL_ENTRY_HH
#include "tools/help_full_entry.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/help_manager.t.cc
+++ avida/current/source/testsuites/unit_testsuites/help_manager.t.cc
#include <iostream>

#ifndef HELP_MANAGER_HH
#include "tools/help_manager.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/help_type.t.cc
+++ avida/current/source/testsuites/unit_testsuites/help_type.t.cc
#include <iostream>

#ifndef HELP_TYPE_HH
#include "tools/help_type.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/histogram.t.cc
+++ avida/current/source/testsuites/unit_testsuites/histogram.t.cc
#include <iostream>

#ifndef HISTOGRAM_HH
#include "histogram.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/indexed_block_struct.t.cc
+++ avida/current/source/testsuites/unit_testsuites/indexed_block_struct.t.cc
#include <iostream>

#ifndef INDEXED_BLOCK_STRUCT_HH
#include "indexed_block_struct.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/init_file.t.cc
+++ avida/current/source/testsuites/unit_testsuites/init_file.t.cc
#include <iostream>

#ifndef INIT_FILE_HH
#include "init_file.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/inject_genebank.t.cc
+++ avida/current/source/testsuites/unit_testsuites/inject_genebank.t.cc
#ifndef INJECT_GENEBANK_HH
#include "inject_genebank.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/inject_genotype.t.cc
+++ avida/current/source/testsuites/unit_testsuites/inject_genotype.t.cc
#ifndef INJECT_GENOTYPE_HH
#include "inject_genotype.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/inject_genotype_birth_data.t.cc
+++ avida/current/source/testsuites/unit_testsuites/inject_genotype_birth_data.t.cc
#ifndef INJECT_GENOTYPE_BIRTH_DATA_HH
#include "inject_genotype_birth_data.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/inject_genotype_control.t.cc
+++ avida/current/source/testsuites/unit_testsuites/inject_genotype_control.t.cc
#ifndef INJECT_GENOTYPE_CONTROL_HH
#include "inject_genotype_control.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/inject_genotype_element.t.cc
+++ avida/current/source/testsuites/unit_testsuites/inject_genotype_element.t.cc
#ifndef INJECT_GENOTYPE_ELEMENT_HH
#include "inject_genotype_element.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/inject_genotype_queue.t.cc
+++ avida/current/source/testsuites/unit_testsuites/inject_genotype_queue.t.cc
#ifndef INJECT_GENOTYPE_QUEUE_HH
#include "inject_genotype_queue.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/inst_lib_base.t.cc
+++ avida/current/source/testsuites/unit_testsuites/inst_lib_base.t.cc
#ifndef INST_LIB_BASE_HH
#include "inst_lib_base.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/inst_set.t.cc
+++ avida/current/source/testsuites/unit_testsuites/inst_set.t.cc
#ifndef INST_SET_HH
#include "inst_set.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/inst_util.t.cc
+++ avida/current/source/testsuites/unit_testsuites/inst_util.t.cc
#ifndef INST_UTIL_HH
#include "inst_util.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/integrated_schedule.t.cc
+++ avida/current/source/testsuites/unit_testsuites/integrated_schedule.t.cc
#include <iostream>

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/integrated_schedule_node.t.cc
+++ avida/current/source/testsuites/unit_testsuites/integrated_schedule_node.t.cc
#include <iostream>

#ifndef INTEGRATED_SCHEDULE_NODE_HH
#include "integrated_schedule_node.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/landscape.t.cc
+++ avida/current/source/testsuites/unit_testsuites/landscape.t.cc
#ifndef LANDSCAPE_HH
#include "landscape.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/lineage.t.cc
+++ avida/current/source/testsuites/unit_testsuites/lineage.t.cc
#ifndef LINEAGE_HH
#include "lineage.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/lineage_control.t.cc
+++ avida/current/source/testsuites/unit_testsuites/lineage_control.t.cc
#ifndef LINEAGE_CONTROL_HH
#include "lineage_control.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/local_mutations.t.cc
+++ avida/current/source/testsuites/unit_testsuites/local_mutations.t.cc
#ifndef LOCAL_MUTATIONS_HH
#include "local_mutations.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/message_class.t.cc
+++ avida/current/source/testsuites/unit_testsuites/message_class.t.cc
#include <iostream>

#ifndef MESSAGE_CLASS_HH
#include "message_class.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/message_closure.t.cc
+++ avida/current/source/testsuites/unit_testsuites/message_closure.t.cc
#include <iostream>

#ifndef MESSAGE_CLOSURE_HH
#include "message_closure.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/message_display.t.cc
+++ avida/current/source/testsuites/unit_testsuites/message_display.t.cc
#include <iostream>

#ifndef MESSAGE_DISPLAY_HH
#include "message_display.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/message_type.t.cc
+++ avida/current/source/testsuites/unit_testsuites/message_type.t.cc
#include <iostream>

#ifndef MESSAGE_CLASS_HH
#include "message_type.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/mutation.t.cc
+++ avida/current/source/testsuites/unit_testsuites/mutation.t.cc
#ifndef MUTATION_HH
#include "mutation.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/mutation_lib.t.cc
+++ avida/current/source/testsuites/unit_testsuites/mutation_lib.t.cc
#ifndef MUTATION_LIB_HH
#include "mutation_lib.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/mutation_rates.t.cc
+++ avida/current/source/testsuites/unit_testsuites/mutation_rates.t.cc
#ifndef MUTATION_RATES_HH
#include "mutation_rates.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/mx_code_array.t.cc
+++ avida/current/source/testsuites/unit_testsuites/mx_code_array.t.cc
#include <iostream>

#ifndef MX_CODE_ARRAY_HH
#include "mx_code_array.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/my_code_array_less_than.t.cc
+++ avida/current/source/testsuites/unit_testsuites/my_code_array_less_than.t.cc
#include <iostream>

#ifndef MY_CODE_ARRAY_LESS_THAN_HH
#include "my_code_array_less_than.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/org_message.t.cc
+++ avida/current/source/testsuites/unit_testsuites/org_message.t.cc
#ifndef ORG_MESSAGE_HH
#include "org_message.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/organism.t.cc
+++ avida/current/source/testsuites/unit_testsuites/organism.t.cc
#ifndef ORGANISM_HH
#include "organism.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/phenotype.t.cc
+++ avida/current/source/testsuites/unit_testsuites/phenotype.t.cc
#ifndef PHENOTYPE_HH
#include "phenotype.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/population.t.cc
+++ avida/current/source/testsuites/unit_testsuites/population.t.cc
#ifndef POPULATION_HH
#include "population.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/population_cell.t.cc
+++ avida/current/source/testsuites/unit_testsuites/population_cell.t.cc
#ifndef POPULATION_CELL_HH
#include "population_cell.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/population_event.t.cc
+++ avida/current/source/testsuites/unit_testsuites/population_event.t.cc
#include <iostream>

#ifndef POPULATION_EVENT_HH
#include "population_event.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/population_event_factory.t.cc
+++ avida/current/source/testsuites/unit_testsuites/population_event_factory.t.cc

#include <iostream>

#ifndef POPULATION_EVENT_FACTORY_HH
#include "population_event_factory.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/population_interface.t.cc
+++ avida/current/source/testsuites/unit_testsuites/population_interface.t.cc
#ifndef POPULATION_INTERFACE_HH
#include "population_interface.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/prob_schedule.t.cc
+++ avida/current/source/testsuites/unit_testsuites/prob_schedule.t.cc
#include <iostream>

#ifndef PROB_SCHEDULE_HH
#include "prob_schedule.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/random.t.cc
+++ avida/current/source/testsuites/unit_testsuites/random.t.cc
#include <iostream>

#ifndef RANDOM_HH
#include "random.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/reaction.t.cc
+++ avida/current/source/testsuites/unit_testsuites/reaction.t.cc
#ifndef REACTION_HH
#include "reaction.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/reaction_lib.t.cc
+++ avida/current/source/testsuites/unit_testsuites/reaction_lib.t.cc
#ifndef REACTION_LIB_HH
#include "reaction_lib.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/reaction_process.t.cc
+++ avida/current/source/testsuites/unit_testsuites/reaction_process.t.cc
#ifndef REACTION_PROCESS_HH
#include "reaction_process.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/reaction_result.t.cc
+++ avida/current/source/testsuites/unit_testsuites/reaction_result.t.cc
#ifndef REACTION_RESULT_HH
#include "reaction_result.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/ref_block.t.cc
+++ avida/current/source/testsuites/unit_testsuites/ref_block.t.cc
#include <iostream>

#ifndef REF_BLOCK_HH
#include "ref_block.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/resource.t.cc
+++ avida/current/source/testsuites/unit_testsuites/resource.t.cc
#ifdef RESOURCE_HH
#include "resource.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/resource_count.t.cc
+++ avida/current/source/testsuites/unit_testsuites/resource_count.t.cc
#ifndef RESOURCE_COUNT_HH
#include "resource_count.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/resource_lib.t.cc
+++ avida/current/source/testsuites/unit_testsuites/resource_lib.t.cc
#ifndef RESOURCE_LIB_HH
#include "resource_lib.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/running_average.t.cc
+++ avida/current/source/testsuites/unit_testsuites/running_average.t.cc
#include <iostream>

#ifndef RUNNING_AVERAGE_HH
#include "running_average.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/scaled_block.t.cc
+++ avida/current/source/testsuites/unit_testsuites/scaled_block.t.cc
#include <iostream>

#ifndef SCALED_BLOCK_HH
#include "scaled_block.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/schedule.t.cc
+++ avida/current/source/testsuites/unit_testsuites/schedule.t.cc
#include <iostream>

#ifndef SCHEDULE_HH
#include "schedule.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/spatial_count_elem.t.cc
+++ avida/current/source/testsuites/unit_testsuites/spatial_count_elem.t.cc
#ifndef SPATIAL_COUNT_ELEM_HH
#include "spatial_count_elem.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/spatial_res_count.t.cc
+++ avida/current/source/testsuites/unit_testsuites/spatial_res_count.t.cc
#ifndef SPATIAL_RES_COUNT_HH
#include "spatial_res_count.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/species.t.cc
+++ avida/current/source/testsuites/unit_testsuites/species.t.cc
#ifndef SPECIES_HH
#include "species.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/species_control.t.cc
+++ avida/current/source/testsuites/unit_testsuites/species_control.t.cc
#include <iostream>

#ifndef SPECIES_CONTROL_HH
#include "species_control.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/species_queue.t.cc
+++ avida/current/source/testsuites/unit_testsuites/species_queue.t.cc
#include <iostream>

#ifndef SPECIES_QUEUE_HH
#include "species_queue.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/stats.t.cc
+++ avida/current/source/testsuites/unit_testsuites/stats.t.cc
#ifndef STATS_HH
#include "stats.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/string.t.cc
+++ avida/current/source/testsuites/unit_testsuites/string.t.cc
#include <iostream>

#ifndef STRING_HH
#include "string.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/string_iterator.t.cc
+++ avida/current/source/testsuites/unit_testsuites/string_iterator.t.cc
#include <iostream>

#ifndef STRING_ITERATOR_HH
#include "string_iterator.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/string_list.t.cc
+++ avida/current/source/testsuites/unit_testsuites/string_list.t.cc
#include <iostream>

#ifndef STRING_LIST_HH
#include "string_list.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/string_util.t.cc
+++ avida/current/source/testsuites/unit_testsuites/string_util.t.cc
#include <iostream>

#ifndef STRING_UTIL_HH
#include "string_util.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/tArgDataEntry.t.cc
+++ avida/current/source/testsuites/unit_testsuites/tArgDataEntry.t.cc
#include <iostream>

#ifndef TARGDATAENTRY_HH
#include "tArgDataEntry.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/tArray.t.cc
+++ avida/current/source/testsuites/unit_testsuites/tArray.t.cc
#include <iostream>

#ifndef TARRAY_HH
#include "tArray.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/tBuffer.t.cc
+++ avida/current/source/testsuites/unit_testsuites/tBuffer.t.cc
#include <iostream>

#ifndef TBUFFER_HH
#include "tBuffer.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/tDataEntry.t.cc
+++ avida/current/source/testsuites/unit_testsuites/tDataEntry.t.cc
#include <iostream>

#ifndef TDATAENTRY_HH
#include "tDataEntry.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/tDataEntryBase.t.cc
+++ avida/current/source/testsuites/unit_testsuites/tDataEntryBase.t.cc
#include <iostream>

#ifndef TDATAENTRYBASE_HH
#include "tDataEntryBase.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/tDataEntryCommand.t.cc
+++ avida/current/source/testsuites/unit_testsuites/tDataEntryCommand.t.cc
#include <iostream>

#ifndef TDATAENTRYCOMMAND_HH
#include "tDataEntryCommand.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/tDataManager.t.cc
+++ avida/current/source/testsuites/unit_testsuites/tDataManager.t.cc
#include <iostream>

#ifndef TDATAMANAGER_HH
#include "tDataManager.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/tDictionary.t.cc
+++ avida/current/source/testsuites/unit_testsuites/tDictionary.t.cc
#include <iostream>

#ifndef TDICTIONARY_HH
#include "tDictionary.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/tList.t.cc
+++ avida/current/source/testsuites/unit_testsuites/tList.t.cc
#include <iostream>

#ifndef TLIST_HH
#include "tList.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/tMatrix.t.cc
+++ avida/current/source/testsuites/unit_testsuites/tMatrix.t.cc
#include <iostream>

#ifndef TMATRIX_HH
#include "tMatrix.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/tVector.t.cc
+++ avida/current/source/testsuites/unit_testsuites/tVector.t.cc
#include <iostream>

#ifndef TVECTOR_HH
#include "tVector.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/task_entry.t.cc
+++ avida/current/source/testsuites/unit_testsuites/task_entry.t.cc
#ifndef TASK_ENTRY_HH
#include "task_entry.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/task_lib.t.cc
+++ avida/current/source/testsuites/unit_testsuites/task_lib.t.cc
#ifndef TASK_LIB_HH
#include "task_lib.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/template.t.cc
+++ avida/current/source/testsuites/unit_testsuites/template.t.cc
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;

class cTemplateTest : public test_case {
public: virtual void test() {
  test_is_true(true);
} };

class cTestSuite : public test_case {
public: cTestSuite() : test_case() {
  adopt_test_case(new cTemplateTest); 
} };

int main(int argc, char *argv[]){
  cout << endl 
  << "----------------------------------------" << endl
  << "Testing Template." << endl;
  cTestSuite t;
  t.run_test();
  cout << text_test_interpreter().interpretation(t.last_result());
  return(t.last_result().success_count() != t.last_result().total_test_count());
}

Index: avida/current/source/testsuites/unit_testsuites/test_cpu.t.cc
+++ avida/current/source/testsuites/unit_testsuites/test_cpu.t.cc
#include <iostream>

#ifndef TEST_CPU_HH
#include "test_cpu.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/test_util.t.cc
+++ avida/current/source/testsuites/unit_testsuites/test_util.t.cc
#include <iostream>

#ifndef TEST_UTIL_HH
#include "test_util.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/tools.t.cc
+++ avida/current/source/testsuites/unit_testsuites/tools.t.cc
#include <iostream>

#ifndef TOOLS_HH
#include "tools.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/uint.t.cc
+++ avida/current/source/testsuites/unit_testsuites/uint.t.cc
#include <iostream>

#ifndef UINT_HH
#include "uint.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/weighted_index.t.cc
+++ avida/current/source/testsuites/unit_testsuites/weighted_index.t.cc
#include <iostream>

#ifndef WEIGHTED_INDEX_HH
#include "weighted_index.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nTemplateTest {
  class cTemplateTest : public test_case {
  public: virtual void test() {
      test_is_true(true);
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTemplateTest); 
  } };
}

using namespace nTemplateTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing Template." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/level_0/Makefile.am
+++ avida/current/source/testsuites/unit_testsuites/level_0/Makefile.am

SOURCE_DIR = $(srcdir)/../../..
INCLUDES = \
	-I$(SOURCE_DIR) \
	-I$(SOURCE_DIR)/event \
	-I$(SOURCE_DIR)/cpu \
	-I$(SOURCE_DIR)/tools \
	-I$(SOURCE_DIR)/main \
	-I$(SOURCE_DIR)/third-party

BLD_DIR = ../../..
UNITTEST_LIBS = \
	$(BLD_DIR)/event/libevent.a \
	$(BLD_DIR)/cpu/libcpu.a \
	$(BLD_DIR)/tools/libtools.a \
	$(BLD_DIR)/main/libmain.a \
	$(BLD_DIR)/third-party/trio/libtrio.a \
  $(BLD_DIR)/third-party/yaktest/libyaktest.a \
  $(BLD_DIR)/third-party/mockpp/libmockpp.a \
  $(BLD_DIR)/third-party/mockpp/compat/libcompat.a \
  $(BLD_DIR)/third-party/mockpp/util/libutil.a

LINK = $(CXXLINK)
LDADD = $(UNITTEST_LIBS)
SUFFIXES = .cc
cc.o:
	$(CXXCOMPILE) -c $<
template_t_SOURCES = template.t.cc

check_PROGRAMS = $(TESTSUITES)
TESTS = $(TESTSUITES)

TESTSUITES = \
  count_tracker.t \
  cpu_stats.t \
  double_sum.t \
  event_triggers.t \
  fixed_block.t \
  genotype_test_data.t \
  int_sum.t \
  memory_flags.t \
  merit.t \
	\
	template.t

Index: avida/current/source/testsuites/unit_testsuites/level_0/count_tracker.t.cc
+++ avida/current/source/testsuites/unit_testsuites/level_0/count_tracker.t.cc
#ifndef COUNT_TRACKER_HH
#include "count_tracker.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;

class cTestCounting : public test_case {
public: virtual void test() {
  int i;
  cCountTracker ct;

  for(i=0;i<5;i++) ct.Inc();
  test_is_true(ct.GetCur() == 5);
  test_is_true(ct.GetLast() == 0);
  test_is_true(ct.GetTotal() == 5);

  for(i=0;i<4;i++) ct.Dec();
  test_is_true(ct.GetCur() == 1);
  test_is_true(ct.GetLast() == 0);
  test_is_true(ct.GetTotal() == 5);

  ct.Next();
  test_is_true(ct.GetCur() == 0);
  test_is_true(ct.GetLast() == 1);
  test_is_true(ct.GetTotal() == 5);

  for(i=0;i<5;i++) ct.Inc();
  test_is_true(ct.GetCur() == 5);
  test_is_true(ct.GetLast() == 1);
  test_is_true(ct.GetTotal() == 10);

  ct.Clear();
  test_is_true(ct.GetCur() == 0);
  test_is_true(ct.GetLast() == 0);
  test_is_true(ct.GetTotal() == 0);
} };

class cTestDefaultConstructor : public test_case {
public: virtual void test() {
  cCountTracker ct;
  test_is_true(ct.GetCur() == 0);
  test_is_true(ct.GetLast() == 0);
  test_is_true(ct.GetTotal() == 0);
} };


class cTestSuite : public test_case {
public: cTestSuite() : test_case() {
  adopt_test_case(new cTestCounting); 
  adopt_test_case(new cTestDefaultConstructor); 
} };

int main(int argc, char *argv[]){
  cout << endl 
  << "----------------------------------------" << endl
  << "Testing cCountTracker." << endl;
  cTestSuite t;
  t.run_test();
  cout << text_test_interpreter().interpretation(t.last_result());
  return(t.last_result().success_count() != t.last_result().total_test_count());
}

Index: avida/current/source/testsuites/unit_testsuites/level_0/cpu_stats.t.cc
+++ avida/current/source/testsuites/unit_testsuites/level_0/cpu_stats.t.cc
#ifndef CPU_STATS_HH
#include "cpu_stats.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;

class cTestSetup : public test_case {
public:
  virtual void test() {
    sCPUStats s;
    s.Setup(0);
    test_is_true(s.mut_stats.point_mut_count == 0);
    test_is_true(s.mut_stats.copy_mut_count == 0);
    test_is_true(s.mut_stats.insert_mut_count == 0);
    test_is_true(s.mut_stats.delete_mut_count == 0);
    test_is_true(s.mut_stats.div_mut_count == 0);
    test_is_true(s.mut_stats.point_mut_line_count == 0);
    test_is_true(s.mut_stats.parent_mut_line_count == 0);
    test_is_true(s.mut_stats.copy_mut_line_count == 0);
    test_is_true(s.mut_stats.divide_mut_count == 0);
    test_is_true(s.mut_stats.divide_insert_mut_count == 0);
    test_is_true(s.mut_stats.divide_delete_mut_count == 0);
    test_is_true(s.mut_stats.copies_exec == 0);
  }
};

class cTestClear : public test_case {
public:
  virtual void test() {
    sCPUStats s;
    s.mut_stats.point_mut_count = 1;
    s.mut_stats.copy_mut_count = 2;
    s.mut_stats.insert_mut_count = 3;
    s.mut_stats.delete_mut_count = 4;
    s.mut_stats.div_mut_count = 5;
    s.mut_stats.point_mut_line_count = 6;
    s.mut_stats.parent_mut_line_count = 7;
    s.mut_stats.copy_mut_line_count = 8;
    s.mut_stats.divide_mut_count = 9;
    s.mut_stats.divide_insert_mut_count = 10;
    s.mut_stats.divide_delete_mut_count = 11;
    s.mut_stats.copies_exec = 12;

    s.Clear();
    test_is_true(s.mut_stats.point_mut_count == 0);
    test_is_true(s.mut_stats.copy_mut_count == 0);
    test_is_true(s.mut_stats.insert_mut_count == 0);
    test_is_true(s.mut_stats.delete_mut_count == 0);
    test_is_true(s.mut_stats.div_mut_count == 0);
    test_is_true(s.mut_stats.point_mut_line_count == 0);
    test_is_true(s.mut_stats.parent_mut_line_count == 0);
    test_is_true(s.mut_stats.copy_mut_line_count == 0);
    test_is_true(s.mut_stats.divide_mut_count == 0);
    test_is_true(s.mut_stats.divide_insert_mut_count == 0);
    test_is_true(s.mut_stats.divide_delete_mut_count == 0);
    test_is_true(s.mut_stats.copies_exec == 0);
  }
};

class cTestSuite : public test_case {
public: cTestSuite() : test_case() {
  adopt_test_case(new cTestSetup); 
  adopt_test_case(new cTestClear); 
} };

int main(int argc, char *argv[]){
  cout << endl 
  << "----------------------------------------" << endl
  << "Testing sCPUStats." << endl;
  cTestSuite t;
  t.run_test();
  cout << text_test_interpreter().interpretation(t.last_result());
  return(t.last_result().success_count() != t.last_result().total_test_count());
}

Index: avida/current/source/testsuites/unit_testsuites/level_0/double_sum.t.cc
+++ avida/current/source/testsuites/unit_testsuites/level_0/double_sum.t.cc
#ifndef DOUBLE_SUM_HH
#include "double_sum.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;

class cDoubleSumTest : public test_case {
public: virtual void test() {
  cDoubleSum ds;
  // test of default constructor, which should Clear()
  test_double_is_equal(ds.Count(), 0.);
  test_double_is_equal(ds.N(), 0.);
  test_double_is_equal(ds.Sum(), 0.);
  test_double_is_equal(ds.S1(), 0.);
  test_double_is_equal(ds.SumOfSquares(), 0.);
  test_double_is_equal(ds.S2(), 0.);
  test_double_is_equal(ds.SumOfCubes(), 0.);
  test_double_is_equal(ds.S3(), 0.);
  test_double_is_equal(ds.S4(), 0.);
  test_double_is_equal(ds.Average(), 0.);
  test_double_is_equal(ds.Variance(), cDoubleSum::INF_ERR);
  test_double_is_equal(ds.StdDeviation(), cDoubleSum::INF_ERR);
  test_double_is_equal(ds.StdError(), cDoubleSum::INF_ERR);
  test_double_is_equal(ds.Skewness(), cDoubleSum::INF_ERR);
  test_double_is_equal(ds.Kurtosis(), cDoubleSum::INF_ERR);
  test_double_is_equal(ds.Ave(), cDoubleSum::INF_ERR);
  test_double_is_equal(ds.Var(), cDoubleSum::INF_ERR);
  test_double_is_equal(ds.Kur(), cDoubleSum::INF_ERR);
  test_double_is_equal(ds.Skw(), cDoubleSum::INF_ERR);

  ds.Add(1.);
  ds.Add(2., 2.);
  ds.Add(3., 3.);
  ds.Add(4., 4.);
  double ave(ds.Average());
  double var(ds.Variance());
  double sdv(ds.StdDeviation());
  double sde(ds.StdError());
  double skw(ds.Skewness());
  double krt(ds.Kurtosis());
  ds.Add(5., 5.);
  double_is_within_tolerance(ds.Average(), 3.6666, 0.0001);
  double_is_within_tolerance(ds.Variance(), 55.524, 0.001);
  double_is_within_tolerance(ds.StdDeviation(), 7.4514, 0.0001);
  double_is_within_tolerance(ds.StdError(), 1.9239, 0.0001);
  double_is_within_tolerance(ds.Skewness(), 9.2512e+02, 1.e-02);
  double_is_within_tolerance(ds.Kurtosis(), 2.5596e+04, 1.);

  //cout
  //<< " ave: " << ave
  //<< " var: " << var
  //<< " sdv: " << sdv
  //<< " sde: " << sde
  //<< " skw: " << skw
  //<< " krt: " << krt
  //<< endl;
  ds.Subtract(5., 5.);
  double_is_within_tolerance(ds.Average(), ave, 0.0001);
  double_is_within_tolerance(ds.Variance(), var, 1.e-03);
  double_is_within_tolerance(ds.StdDeviation(), sdv, 0.0001);
  double_is_within_tolerance(ds.StdError(), sde, 0.0001);
  double_is_within_tolerance(ds.Skewness(), skw, 1.e-02);
  double_is_within_tolerance(ds.Kurtosis(), krt, 1.e-01);

  ds.Clear();
  test_double_is_equal(ds.Count(), 0.);
  test_double_is_equal(ds.N(), 0.);
  test_double_is_equal(ds.Sum(), 0.);
  test_double_is_equal(ds.S1(), 0.);
  test_double_is_equal(ds.SumOfSquares(), 0.);
  test_double_is_equal(ds.S2(), 0.);
  test_double_is_equal(ds.SumOfCubes(), 0.);
  test_double_is_equal(ds.S3(), 0.);
  test_double_is_equal(ds.S4(), 0.);
  test_double_is_equal(ds.Average(), 0.);
  test_double_is_equal(ds.Variance(), cDoubleSum::INF_ERR);
  test_double_is_equal(ds.StdDeviation(), cDoubleSum::INF_ERR);
  test_double_is_equal(ds.StdError(), cDoubleSum::INF_ERR);
  test_double_is_equal(ds.Skewness(), cDoubleSum::INF_ERR);
  test_double_is_equal(ds.Kurtosis(), cDoubleSum::INF_ERR);
  test_double_is_equal(ds.Ave(), cDoubleSum::INF_ERR);
  test_double_is_equal(ds.Var(), cDoubleSum::INF_ERR);
  test_double_is_equal(ds.Kur(), cDoubleSum::INF_ERR);
  test_double_is_equal(ds.Skw(), cDoubleSum::INF_ERR);

  // FIXME
  cout
  << "***" << endl
  << "FIXME:" << endl
  << "We should test for precision and range." << endl
  << "Discuss with Charles.  -- kgn" << endl
  << "***" << endl;
} };

class cTestSuite : public test_case {
public: cTestSuite() : test_case() {
  adopt_test_case(new cDoubleSumTest); 
} };

int main(int argc, char *argv[]){
  cout << endl 
  << "----------------------------------------" << endl
  << "Testing cDoubleSum." << endl;
  cTestSuite t;
  t.run_test();
  cout << text_test_interpreter().interpretation(t.last_result());
  return(t.last_result().success_count() != t.last_result().total_test_count());
}

Index: avida/current/source/testsuites/unit_testsuites/level_0/event_triggers.t.cc
+++ avida/current/source/testsuites/unit_testsuites/level_0/event_triggers.t.cc
#ifndef EVENT_TRIGGERS_HH
#include "event_triggers.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;

class cTemplateTest : public test_case {
public: virtual void test() {
  // FIXME
  cout
  << "***" << endl
  << "FIXME:" << endl
  << "cEventTriggers can't be instantiated" << endl
  << "because it is a pure virtual base class;" << endl
  << "but it can be Mock-subclassed..." << endl
  << "try this out.  -- kgn" << endl
  << "***" << endl
  << "PS: cAvidaTriggers is an instantiable subclass." << endl
  << "***" << endl;
} };

class cTestSuite : public test_case {
public: cTestSuite() : test_case() {
  adopt_test_case(new cTemplateTest); 
} };

int main(int argc, char *argv[]){
  cout << endl 
  << "----------------------------------------" << endl
  << "Testing cEventTriggers." << endl;
  cTestSuite t;
  t.run_test();
  cout << text_test_interpreter().interpretation(t.last_result());
  return(t.last_result().success_count() != t.last_result().total_test_count());
}

Index: avida/current/source/testsuites/unit_testsuites/level_0/fixed_block.t.cc
+++ avida/current/source/testsuites/unit_testsuites/level_0/fixed_block.t.cc
#ifndef FIXED_BLOCK_HH
#include "fixed_block.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;

class cFixedBlockTest : public test_case {
public: virtual void test() {
  cFixedBlock fb;
  test_is_true(fb.GetStart() == 0);
  fb.SetStart(5);
  test_is_true(fb.GetStart() == 5);
} };

class cTestSuite : public test_case {
public: cTestSuite() : test_case() {
  adopt_test_case(new cFixedBlockTest); 
} };

int main(int argc, char *argv[]){
  cout << endl 
  << "----------------------------------------" << endl
  << "Testing cFixedBlock." << endl;
  cTestSuite t;
  t.run_test();
  cout << text_test_interpreter().interpretation(t.last_result());
  return(t.last_result().success_count() != t.last_result().total_test_count());
}

Index: avida/current/source/testsuites/unit_testsuites/level_0/genotype_test_data.t.cc
+++ avida/current/source/testsuites/unit_testsuites/level_0/genotype_test_data.t.cc
#ifndef GENOTYPE_TEST_DATA_HH
#include "genotype_test_data.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;

class cGenotype_TestDataTest : public test_case {
public: virtual void test() {
  cGenotype_TestData gtd;
  //test_is_true(!gtd.is_viable);
  test_double_is_equal(gtd.fitness, -1.);
  //test_double_is_equal(gtd.merit, 0.);
  //test_int_is_equal(gtd.gestation_time, 0);
  //test_int_is_equal(gtd.executed_size, 0);
  //test_int_is_equal(gtd.copied_size, 0);
  //test_double_is_equal(gtd.colony_fitness, 0.);
  //test_int_is_equal(gtd.generations, 0);

  // FIXME
  cout
  << "***" << endl
  << "FIXME:" << endl
  << "why is cGenotype_TestData::fitness" << endl
  << "initially -1.0?" << endl
  << "verify that other members" << endl
  << "need not be initialized. -- kgn" << endl
  << "***" << endl;
} };

class cTestSuite : public test_case {
public: cTestSuite() : test_case() {
  adopt_test_case(new cGenotype_TestDataTest); 
} };

int main(int argc, char *argv[]){
  cout << endl 
  << "----------------------------------------" << endl
  << "Testing cGenotype_TestData." << endl;
  cTestSuite t;
  t.run_test();
  cout << text_test_interpreter().interpretation(t.last_result());
  return(t.last_result().success_count() != t.last_result().total_test_count());
}

Index: avida/current/source/testsuites/unit_testsuites/level_0/int_sum.t.cc
+++ avida/current/source/testsuites/unit_testsuites/level_0/int_sum.t.cc
#ifndef INT_SUM_HH
#include "int_sum.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;

class cIntSumTest : public test_case {
public: virtual void test() {
  cIntSum is;
  // test of default constructor, which should Clear()
  test_int_is_equal(is.Count(), 0);
  test_int_is_equal(is.N(), 0);
  test_int_is_equal(is.Sum(), 0);
  test_int_is_equal(is.S1(), 0);
  test_int_is_equal(is.SumOfSquares(), 0);
  test_int_is_equal(is.S2(), 0);
  test_int_is_equal(is.SumOfCubes(), 0);
  test_int_is_equal(is.S3(), 0);
  test_int_is_equal(is.S4(), 0);
  test_double_is_equal(is.Average(), 0.);
  test_double_is_equal(is.Variance(), cIntSum::INF_ERR);
  test_double_is_equal(is.StdDeviation(), cIntSum::INF_ERR);
  test_double_is_equal(is.StdError(), cIntSum::INF_ERR);
  test_double_is_equal(is.Skewness(), cIntSum::INF_ERR);
  test_double_is_equal(is.Kurtosis(), cIntSum::INF_ERR);
  test_double_is_equal(is.Ave(), cIntSum::INF_ERR);
  test_double_is_equal(is.Var(), cIntSum::INF_ERR);
  test_double_is_equal(is.Kur(), cIntSum::INF_ERR);
  test_double_is_equal(is.Skw(), cIntSum::INF_ERR);

  is.Add(1);
  is.Add(2, 2);
  is.Add(3, 3);
  is.Add(4, 4);
  double ave(is.Average());
  double var(is.Variance());
  double sdv(is.StdDeviation());
  double sde(is.StdError());
  double skw(is.Skewness());
  double krt(is.Kurtosis());
  is.Add(5, 5);
  double_is_within_tolerance(is.Average(), 3.6666, 0.0001);
  double_is_within_tolerance(is.Variance(), 55.524, 0.001);
  double_is_within_tolerance(is.StdDeviation(), 7.4514, 0.0001);
  //double_is_within_tolerance(is.StdError(), 1.9239, 0.0001);
  double_is_within_tolerance(is.Skewness(), 9.2512e+02, 1.e-02);
  double_is_within_tolerance(is.Kurtosis(), 2.5596e+04, 1.);

  //cout
  //<< " ave: " << ave
  //<< " var: " << var
  //<< " sdv: " << sdv
  //<< " sde: " << sde
  //<< " skw: " << skw
  //<< " krt: " << krt
  //<< endl;
  is.Subtract(5, 5);
  double_is_within_tolerance(is.Average(), ave, 0.0001);
  double_is_within_tolerance(is.Variance(), var, 1.e-03);
  double_is_within_tolerance(is.StdDeviation(), sdv, 0.0001);
  double_is_within_tolerance(is.StdError(), sde, 0.0001);
  double_is_within_tolerance(is.Skewness(), skw, 1.e-02);
  double_is_within_tolerance(is.Kurtosis(), krt, 1.e-01);

  is.Clear();
  test_int_is_equal(is.Count(), 0);
  test_int_is_equal(is.N(), 0);
  test_int_is_equal(is.Sum(), 0);
  test_int_is_equal(is.S1(), 0);
  test_int_is_equal(is.SumOfSquares(), 0);
  test_int_is_equal(is.S2(), 0);
  test_int_is_equal(is.SumOfCubes(), 0);
  test_int_is_equal(is.S3(), 0);
  test_int_is_equal(is.S4(), 0);
  test_double_is_equal(is.Average(), 0.);
  test_double_is_equal(is.Variance(), cIntSum::INF_ERR);
  test_double_is_equal(is.StdDeviation(), cIntSum::INF_ERR);
  test_double_is_equal(is.StdError(), cIntSum::INF_ERR);
  test_double_is_equal(is.Skewness(), cIntSum::INF_ERR);
  test_double_is_equal(is.Kurtosis(), cIntSum::INF_ERR);
  test_double_is_equal(is.Ave(), cIntSum::INF_ERR);
  test_double_is_equal(is.Var(), cIntSum::INF_ERR);
  test_double_is_equal(is.Kur(), cIntSum::INF_ERR);
  test_double_is_equal(is.Skw(), cIntSum::INF_ERR);

  // FIXME
  cout
  << "***" << endl
  << "FIXME:" << endl
  << "We should test for precision and range." << endl
  << "Discuss with Charles.  -- kgn" << endl
  << "In particular, is.StdError() overflows" << endl
  << "perhaps too easily." << endl
  << endl
  << "Should find out expected range and number" << endl
  << "of inputs and weights.  -- kgn" << endl
  << "***" << endl;
} };

class cTestSuite : public test_case {
public: cTestSuite() : test_case() {
  adopt_test_case(new cIntSumTest); 
} };

int main(int argc, char *argv[]){
  cout << endl 
  << "----------------------------------------" << endl
  << "Testing cIntSum." << endl;
  cTestSuite t;
  t.run_test();
  cout << text_test_interpreter().interpretation(t.last_result());
  return(t.last_result().success_count() != t.last_result().total_test_count());
}

Index: avida/current/source/testsuites/unit_testsuites/level_0/memory_flags.t.cc
+++ avida/current/source/testsuites/unit_testsuites/level_0/memory_flags.t.cc
#ifndef MEMORY_FLAGS_HH
#include "memory_flags.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;

class cMemoryFlagsOverride : public cMemoryFlags {
public:
  bool getCopied(){ return copied; }
  bool getMutated(){ return mutated; }
  bool getExecuted(){ return executed; }
  bool getBreakpoint(){ return breakpoint; }
  bool getPoint_mut(){ return point_mut; }
  bool getCopy_mut(){ return copy_mut; }
  bool getInjected(){ return injected; }

  void setCopied(bool _copied){ copied = _copied; }
  void setMutated(bool _mutated){ mutated = _mutated; }
  void setExecuted(bool _executed){ executed = _executed; }
  void setBreakpoint(bool _breakpoint){ breakpoint = _breakpoint; }
  void setPoint_mut(bool _point_mut){ point_mut = _point_mut; }
  void setCopy_mut(bool _copy_mut){ copy_mut = _copy_mut; }
  void setInjected(bool _injected){ injected = _injected; }
};

class cMemoryFlagsTest : public test_case {
public: virtual void test() {
  // all values should be false after construction.
  cMemoryFlagsOverride mfo;
  test_is_true(!mfo.getCopied());
  test_is_true(!mfo.getMutated());
  test_is_true(!mfo.getExecuted());
  test_is_true(!mfo.getBreakpoint());
  test_is_true(!mfo.getPoint_mut());
  test_is_true(!mfo.getCopy_mut());
  test_is_true(!mfo.getInjected());

  // set all values to true, and double check result.
  mfo.setCopied(true);
  mfo.setMutated(true);
  mfo.setExecuted(true);
  mfo.setBreakpoint(true);
  mfo.setPoint_mut(true);
  mfo.setCopy_mut(true);
  mfo.setInjected(true);
  test_is_true(mfo.getCopied());
  test_is_true(mfo.getMutated());
  test_is_true(mfo.getExecuted());
  test_is_true(mfo.getBreakpoint());
  test_is_true(mfo.getPoint_mut());
  test_is_true(mfo.getCopy_mut());
  test_is_true(mfo.getInjected());

  // all values should be false after Clear().
  mfo.Clear();
  test_is_true(!mfo.getCopied());
  test_is_true(!mfo.getMutated());
  test_is_true(!mfo.getExecuted());
  test_is_true(!mfo.getBreakpoint());
  test_is_true(!mfo.getPoint_mut());
  test_is_true(!mfo.getCopy_mut());
  test_is_true(!mfo.getInjected());
} };

class cTestSuite : public test_case {
public: cTestSuite() : test_case() {
  adopt_test_case(new cMemoryFlagsTest); 
} };

int main(int argc, char *argv[]){
  cout << endl 
  << "----------------------------------------" << endl
  << "Testing cMemoryFlags." << endl;
  cTestSuite t;
  t.run_test();
  cout << text_test_interpreter().interpretation(t.last_result());
  return(t.last_result().success_count() != t.last_result().total_test_count());
}

Index: avida/current/source/testsuites/unit_testsuites/level_0/merit.t.cc
+++ avida/current/source/testsuites/unit_testsuites/level_0/merit.t.cc
#ifndef MERIT_HH
#include "merit.hh"
#endif

#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;

class cMeritOverride : public cMerit {
public:
  void operator=(const cMerit &merit){*static_cast<cMerit *>(this)=merit;}
  int getBits(){ return bits; }
  UINT getBase(){ return base; }
  UINT getOffset(){ return offset; }
  double getValue(){ return value; }
};

class cGetBitTest : public test_case {
public: virtual void test() {
  cout << "\tTesting GetDouble() UNIMPLEMENTED." << endl;

  //double mult[];
  //cMerit m;
  //cMeritOverride mo;
  //mo.Clear();
  //for(double d = 0.; d < 64.; d+=0.3){
  //  double value = pow(2.,d);
  //  m = value; mo = m;

  //}
} };

class cGetDoubleTest : public test_case {
public: virtual void test() {
  cout << "\tTesting GetDouble()." << endl;
  cMerit m;
  m.Clear();
  for(double d = 0.; d < 64.; d+=0.3){
    double value = pow(2.,d);
    m = value;
    test_double_is_equal(value, m.GetDouble());
  }
} };

class cGetNumBitsTest : public test_case {
public: virtual void test() {
  cout << "\tTesting GetNumBits()." << endl;
  cMerit m;
  m.Clear();
  for(double d = 0.; d < 64.; d+=0.3){
    double value = pow(2.,d);
    m = value;
    test_int_is_equal((int)d+1, m.GetNumBits());
  }
} };

class cInternalStateTest : public test_case {
public: virtual void test() {
  cout << "\tTesting internal state." << endl;
  cMerit m;
  cMeritOverride mo;
  mo.Clear();
  for(double d = 0.; d < 64.; d += 0.3){
    double value = pow(2., d);
    m = value; mo = m;
    // test bits
    test_int_is_equal((int)d+1, mo.getBits());
    // test value
    test_is_true(
      mo.getValue() <= value * (1 + 1/UINT_MAX) ||
      mo.getValue() >= value / (1 + 1/UINT_MAX));
    // test base and offset
    double reconstructed_value = ((double)(mo.getBase()) * pow(2., (int)mo.getOffset()));
    test_is_true(
      reconstructed_value <= value * (1 + 1/UINT_MAX) ||
      reconstructed_value >= value / (1 + 1/UINT_MAX));
  }
} };

class cTestSuite : public test_case {
public: cTestSuite() : test_case() {
  adopt_test_case(new cInternalStateTest); 
  adopt_test_case(new cGetDoubleTest); 
  adopt_test_case(new cGetNumBitsTest); 
} };

int main(int argc, char *argv[]){
  cout << endl 
  << "----------------------------------------" << endl
  << "Testing cMerit." << endl;
  cTestSuite t;
  t.run_test();
  cout << text_test_interpreter().interpretation(t.last_result());
  return(t.last_result().success_count() != t.last_result().total_test_count());
}

Index: avida/current/source/testsuites/unit_testsuites/level_0/template.t.cc
+++ avida/current/source/testsuites/unit_testsuites/level_0/template.t.cc
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

#include <iostream>

using namespace std;

class cTemplateTest : public test_case {
public: virtual void test() {
    test_is_true(true);
} };

class cTestSuite : public test_case {
public: cTestSuite() : test_case() {
  adopt_test_case(new cTemplateTest); 
} };

int main(int argc, char *argv[]){
  cout << endl 
  << "----------------------------------------" << endl
  << "Testing Template." << endl;
  cTestSuite t;
  t.run_test();
  cout << text_test_interpreter().interpretation(t.last_result());
  return(t.last_result().success_count() != t.last_result().total_test_count());
}

Index: avida/current/source/testsuites/unit_testsuites/level_1/Makefile.am
+++ avida/current/source/testsuites/unit_testsuites/level_1/Makefile.am
EXTRA_DIST =
TESTSUITES =
check_PROGRAMS =
check_LIBRARIES =

SOURCE_DIR = $(srcdir)/../../..
SOURCE_INC = -I$(SOURCE_DIR)
EVENT_DIR = $(SOURCE_DIR)/event
EVENT_INC = -I$(EVENT_DIR)
CPU_DIR = $(SOURCE_DIR)/cpu
CPU_INC = -I$(CPU_DIR)
TOOLS_DIR = $(SOURCE_DIR)/tools
TOOLS_INC = -I$(TOOLS_DIR)
MAIN_DIR = $(SOURCE_DIR)/main
MAIN_INC = -I$(MAIN_DIR)
MOCKPP_DIR = $(SOURCE_DIR)/third-party
MOCKPP_INC = -I$(MOCKPP_DIR)

INCLUDES = $(EVENT_INC) $(CPU_INC) $(TOOLS_INC) $(MAIN_INC) $(MOCKPP_INC) $(SOURCE_INC) 

BLD_DIR = ../../..

UNITTEST_LIBS = \
  $(BLD_DIR)/third-party/yaktest/libyaktest.a \
  $(BLD_DIR)/third-party/mockpp/libmockpp.a \
  $(BLD_DIR)/third-party/mockpp/compat/libcompat.a \
  $(BLD_DIR)/third-party/mockpp/util/libutil.a

# cInstruction test
#if DEFAULT_TESTS
TESTSUITES += instruction.t
#endif
check_PROGRAMS += instruction.t
instruction_t_SOURCES = instruction.t.cc
instruction_t_LDADD = $(BLD_DIR)/main/libmain.a $(UNITTEST_LIBS)

# cCodeLabel test
#if DEFAULT_TESTS
TESTSUITES += code_label.t
#endif
check_PROGRAMS += code_label.t
code_label_t_SOURCES = code_label.t.cc
code_label_t_LDADD = \
  $(BLD_DIR)/cpu/libcpu.a \
  $(BLD_DIR)/main/libmain.a \
  $(UNITTEST_LIBS)

TESTS = $(TESTSUITES)

Index: avida/current/source/testsuites/unit_testsuites/level_1/code_label.t.cc
+++ avida/current/source/testsuites/unit_testsuites/level_1/code_label.t.cc
#include <iostream>

#ifndef CODE_LABEL_HH
#include "cpu/code_label.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nCodeLabelTest {
  class cTestConstructor : public test_case {
  public: virtual void test() {
    cCodeLabel label;
    test_is_true(label.GetSize() == 0);
  } };
  class cTestCopyConstructor : public test_case {
  public: virtual void test() {
    cout << __PRETTY_FUNCTION__ << " is not implemented." << endl; 
  } };
  
  class cTestOK : public test_case {
  public: virtual void test() {
    cout << __PRETTY_FUNCTION__ << " is not implemented." << endl; 
  } };
  class cTestEqualityOperator : public test_case {
  public: virtual void test() {
    cout << __PRETTY_FUNCTION__ << " is not implemented." << endl; 
  } };
  class cTestInequalityOperator : public test_case {
  public: virtual void test() {
    cout << __PRETTY_FUNCTION__ << " is not implemented." << endl; 
  } };
  class cTestIndexOperator : public test_case {
  public: virtual void test() {
    cout << __PRETTY_FUNCTION__ << " is not implemented." << endl; 
  } };
  class cTestFindSublabel : public test_case {
  public: virtual void test() {
    cout << __PRETTY_FUNCTION__ << " is not implemented." << endl; 
  } };
  
  class cTestClear : public test_case {
  public: virtual void test() {
    cout << __PRETTY_FUNCTION__ << " is not implemented." << endl; 
  } };
  class cTestAddNop : public test_case {
  public: virtual void test() {
    cout << __PRETTY_FUNCTION__ << " is not implemented." << endl; 
  } };
  class cTestRotate : public test_case {
  public: virtual void test() {
    cout << __PRETTY_FUNCTION__ << " is not implemented." << endl; 
  } };
  
  class cTestGetSize : public test_case {
  public: virtual void test() {
    cout << __PRETTY_FUNCTION__ << " is not implemented." << endl; 
  } };
  class cTestAsString : public test_case {
  public: virtual void test() {
    cout << __PRETTY_FUNCTION__ << " is not implemented." << endl; 
  } };
  class cTestAsInt : public test_case {
  public: virtual void test() {
    cout << __PRETTY_FUNCTION__ << " is not implemented." << endl; 
  } };
  
  class cTestSaveState : public test_case {
  public: virtual void test() {
    cout << __PRETTY_FUNCTION__ << " is not implemented," << endl <<
    "because void cCodeLabel::SaveState(ostream &) is not implemented."
    << endl;
  } };
  class cTestLoadState : public test_case {
  public: virtual void test() {
    cout << __PRETTY_FUNCTION__ << " is not implemented," << endl <<
    "because void cCodeLabel::LoadState(istream &) is not implemented."
    << endl;
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTestConstructor); 
    adopt_test_case(new cTestCopyConstructor); 

    adopt_test_case(new cTestOK); 
    adopt_test_case(new cTestEqualityOperator); 
    adopt_test_case(new cTestInequalityOperator); 
    adopt_test_case(new cTestIndexOperator); 
    adopt_test_case(new cTestFindSublabel); 

    adopt_test_case(new cTestClear); 
    adopt_test_case(new cTestAddNop); 
    adopt_test_case(new cTestRotate); 

    adopt_test_case(new cTestGetSize); 
    adopt_test_case(new cTestAsString); 
    adopt_test_case(new cTestAsInt); 

    adopt_test_case(new cTestSaveState); 
    adopt_test_case(new cTestLoadState); 
  } };
}

using namespace nCodeLabelTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing cCodeLabel." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/testsuites/unit_testsuites/level_1/instruction.t.cc
+++ avida/current/source/testsuites/unit_testsuites/level_1/instruction.t.cc
#include <iostream>

#ifndef INSTRUCTION_HH
#include "main/instruction.hh"
#endif
#ifndef TEST_CASE_H
#include "third-party/yaktest/test_case.h"
#endif
#ifndef TEXT_TEST_INTERPRETER_H
#include "third-party/yaktest/text_test_interpreter.h"
#endif
#ifndef TEST_RESULT_H
#include "third-party/yaktest/test_result.h"
#endif

using namespace std;
namespace nInstructionTest {
  class cTestGetSetOp : public test_case {
  public: virtual void test() {
      cInstruction inst;
      inst.SetOp(5); test_is_true(inst.GetOp() == 5);
  } };
  class cTestSetSymbol : public test_case {
  public: virtual void test() {
      cInstruction inst;
      // Legal symbols are a-z, A-Z, and 0-9,
      // and map to values 0-61.
      // All other symbols should map to value 254 (error).
      inst.SetSymbol('b'); test_is_true(inst.GetOp() == 1);
      inst.SetSymbol('z'); test_is_true(inst.GetOp() == 25);
      inst.SetSymbol('A'); test_is_true(inst.GetOp() == 26);
      inst.SetSymbol('Z'); test_is_true(inst.GetOp() == 51);
      inst.SetSymbol('0'); test_is_true(inst.GetOp() == 52);
      inst.SetSymbol('9'); test_is_true(inst.GetOp() == 61);
      inst.SetSymbol('9' + 1); test_is_true(inst.GetOp() == 254);
      inst.SetSymbol('.'); test_is_true(inst.GetOp() == 254);
  } };
  class cTestGetSymbol : public test_case {
  public: virtual void test() {
      cInstruction inst;
      // Values 0-61 map to symbols a-z, A-Z, and 0-9,
      // in that order.
      // All other values should map to symbol '?'.
      // XXX: why does value 255 map to symbol '_'?
      inst.SetOp(1); test_is_true(inst.GetSymbol() == 'b');
      inst.SetOp(25); test_is_true(inst.GetSymbol() == 'z');
      inst.SetOp(26); test_is_true(inst.GetSymbol() == 'A');
      inst.SetOp(51); test_is_true(inst.GetSymbol() == 'Z');
      inst.SetOp(52); test_is_true(inst.GetSymbol() == '0');
      inst.SetOp(61); test_is_true(inst.GetSymbol() == '9');
      inst.SetOp(62); test_is_true(inst.GetSymbol() == '?');
      inst.SetOp(255); test_is_true(inst.GetSymbol() == '_');
  } };
  class cTestConstructor : public test_case {
  public: virtual void test() {
      cInstruction inst;
      test_is_true(inst.GetOp() == 0);
  } };
  class cTestIntConstructor : public test_case {
  public: virtual void test() {
      cInstruction inst(5);
      test_is_true(inst.GetOp() == 5);
  } };
  class cTestCopyConstructor : public test_case {
  public: virtual void test() {
      cInstruction inst(5);
      cInstruction inst2(inst);
      test_is_true(inst2.GetOp() == 5);
      inst.SetOp(6);
      test_is_true(inst2.GetOp() == 5); // should not now == 6.
      cInstruction inst3(inst);
      test_is_true(inst3.GetOp() == 6);
  } };
  class cTestAssignmentOperator : public test_case {
  public: virtual void test() {
      cInstruction inst(5);
      cInstruction inst2 = inst;
      test_is_true(inst2.GetOp() == 5);
      inst.SetOp(6);
      test_is_true(inst2.GetOp() == 5); // should not now == 6.
      cInstruction inst3 = inst;
      test_is_true(inst3.GetOp() == 6);
  } };
  class cTestEqualityOperators : public test_case {
  public: virtual void test() {
      cInstruction inst(5);
      cInstruction inst2(6);
      cInstruction inst3(6);
      test_is_true(inst2 == inst3);
      test_is_true(inst != inst2);
      test_is_true(inst2 != inst); // commutes?
  } };
  
  class cTestSuite : public test_case {
  public: cTestSuite() : test_case() {
    adopt_test_case(new cTestGetSetOp); 
    adopt_test_case(new cTestSetSymbol); 
    adopt_test_case(new cTestGetSymbol); 
    adopt_test_case(new cTestConstructor); 
    adopt_test_case(new cTestIntConstructor); 
    adopt_test_case(new cTestCopyConstructor); 
    adopt_test_case(new cTestAssignmentOperator); 
    adopt_test_case(new cTestEqualityOperators); 
  } };
}

using namespace nInstructionTest;
int main(int argc, char *argv[]){
  cout << endl << "Testing cInstruction." << endl;
  int successes = 0, test_count = 0;
  cTestSuite inst_test;
  inst_test.run_test();
  successes += inst_test.last_result().success_count();
  test_count += inst_test.last_result().total_test_count();
  text_test_interpreter interpreter;
  cout << interpreter.interpretation(inst_test.last_result());
  return(successes != test_count);
}

Index: avida/current/source/tools/const_schedule.cc
+++ avida/current/source/tools/const_schedule.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef CONST_SCHEDULE_HH
#include "const_schedule.hh"
#endif

#ifndef MERIT_HH
#include "merit.hh"
#endif

////////////////////
//  cConstSchedule
////////////////////

cConstSchedule::cConstSchedule(int _item_count)
  : cSchedule(_item_count), is_active(_item_count)
{
  last_id = 0;
  is_active.SetAll(false);
}

cConstSchedule::~cConstSchedule()
{
}

bool cConstSchedule::OK()
{
  assert(last_id == 0 || last_id < item_count);  //  invalid last_id
  return true;
}

void cConstSchedule::Adjust(int item_id, const cMerit & merit)
{
  if (merit == 0.0) is_active[item_id] = false;
  else is_active[item_id] = true;
}


int cConstSchedule::GetNextID()
{
  // Grab the next ID...
  if (++last_id == item_count) last_id = 0;

  // Make sure we actually have an active ID...
  while (is_active[last_id] == false) {
    if (++last_id == item_count) last_id = 0;
  }
  return last_id;
}

Index: avida/current/source/tools/const_schedule.hh
+++ avida/current/source/tools/const_schedule.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef CONST_SCHEDULE_HH
#define CONST_SCHEDULE_HH

#ifndef SCHEDULE_HH
#include "schedule.hh"
#endif
#ifndef TARRAY_HH
#include "tArray.hh"
#endif

/**
 * This class rotates between all items to schedule, giving each equal time.
 **/

class cMerit;
template <class T> class tArray; // aggregate;

class cConstSchedule : public cSchedule {
private:
  int last_id;
  tArray<bool> is_active;
public:
  cConstSchedule(int _item_count);
  ~cConstSchedule();

  bool OK();
  void Adjust(int item_id, const cMerit & merit);

  int GetNextID();
};

#endif

Index: avida/current/source/tools/count_tracker.cc
+++ avida/current/source/tools/count_tracker.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef COUNT_TRACKER_HH
#include "count_tracker.hh"
#endif

// cCountTracker /////////////////////////////////////////////////////////////

void cCountTracker::Inc()
{
  cur_count++;
  total_count++;
}

void cCountTracker::Dec() 
{
  cur_count--;
}

void cCountTracker::Next()
{
  last_count = cur_count;
  cur_count = 0;
}

void cCountTracker::Clear()
{
  cur_count = 0;
  last_count = 0;
  total_count = 0;
}

Index: avida/current/source/tools/count_tracker.hh
+++ avida/current/source/tools/count_tracker.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef COUNT_TRACKER_HH
#define COUNT_TRACKER_HH

class cCountTracker {
private:
  int cur_count;
  int last_count;
  int total_count;
public:
  cCountTracker() { Clear(); }
  ~cCountTracker() { ; }

  int GetCur() const { return cur_count; }
  int GetLast() const { return last_count; }
  int GetTotal() const { return total_count; }

  void Inc();
  void Dec();
  void Next();
  void Clear();
};

#endif

Index: avida/current/source/tools/data_file.cc
+++ avida/current/source/tools/data_file.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef DATA_FILE_HH
#include "data_file.hh"
#endif

#ifndef STRING_UTIL_HH
#include "string_util.hh"
#endif

using namespace std;

void cDataFile::Init()
{
  m_descr_written = false;
  num_cols = 0;
}

cDataFile::cDataFile()
{
  Init();
}

cDataFile::cDataFile(cString name) : m_name(name)
{
  Init();
   
  if( fopen(name,"r") ){
    // cout << "File " << name() << " exists and is being overwritten" << endl;
  }
  m_fp.open(name);
  assert(m_fp.good());
  m_descr_written = false;
}


void cDataFile::Write( double x, const char * descr )
{
  if ( !m_descr_written ){
    m_data += cStringUtil::Stringf( "%f ", x );
    WriteColumnDesc(descr);
  }
  else m_fp << x << " ";
}


void cDataFile::Write( int i, const char * descr )
{
  if ( !m_descr_written ){
    m_data += cStringUtil::Stringf( "%i ", i );
    WriteColumnDesc(descr);
  }
  else m_fp << i << " ";
}


void cDataFile::Write( const char * data_str, const char * descr )
{
  if ( !m_descr_written ) {
    m_data += cStringUtil::Stringf( "%s ", data_str );
    WriteColumnDesc(descr);
  }
  else m_fp << data_str << " ";
}


void cDataFile::WriteBlockElement(double x, int element, int x_size)
{
  m_fp << x << " ";
  if (((element + 1) % x_size) == 0) {
    m_fp << "\n";
  }
}

void cDataFile::WriteBlockElement(int i, int element, int x_size)
{
  m_fp << i << " ";
  if (((element + 1) % x_size) == 0) {
    m_fp << "\n";
  }
}

void cDataFile::WriteColumnDesc( const char * descr )
{
  if ( !m_descr_written ){
    num_cols++;
    m_descr += cStringUtil::Stringf( "# %2d: %s\n", num_cols, descr );
  }
}

void cDataFile::WriteComment( const char * descr )
{
  if ( !m_descr_written ) m_descr += cStringUtil::Stringf( "# %s\n", descr );
}


void cDataFile::WriteRawComment( const char * descr )
{
  if ( !m_descr_written ) m_descr += cStringUtil::Stringf( "%s\n", descr );
}

void cDataFile::WriteRaw( const char * descr )
{
  m_fp << cStringUtil::Stringf( "%s\n", descr );
}




void cDataFile::WriteTimeStamp()
{
  if ( !m_descr_written ){
    time_t time_p = time( 0 );
    m_descr += cStringUtil::Stringf( "# %s", ctime( &time_p ) );
  }
}

void cDataFile::FlushComments()
{
  if ( !m_descr_written ){
    m_fp << m_descr;
    m_descr_written = true;
  }
}


void cDataFile::Endl()
{
  if ( !m_descr_written ){
    m_fp << m_descr << endl;
    m_fp << m_data << endl;
    m_descr_written = true;
  }
  else m_fp << endl;
}

Index: avida/current/source/tools/data_file.hh
+++ avida/current/source/tools/data_file.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

/* data_file.hh ****************************************************************
 cDataFile

 charles at krl.caltech.edu & travc at ugcs.caltech.edu
 Time-stamp: <1999-01-07 10:02:09 travc>

 cString: basic string class
******************************************************************************/

#ifndef DATA_FILE_HH
#define DATA_FILE_HH

#include <fstream>

#ifndef STRING_HH
#include "string.hh"
#endif

/**
 * This class encapsulates file handling for the class @ref cDataFileManager.
 * The files it creates are write only. Reading of files is handled by
 * @ref cFile.
 */

class cString; // aggregate

class cDataFile {

private:
  cString m_name;
  cString m_data;
  cString m_descr;
  int num_cols;
  
  bool m_descr_written;
  
  std::ofstream m_fp;

  void Init();
public:
  /**
   * The empty constructor does nothing.
   **/
  cDataFile();

  /**
   * This constructor opens a file of the given name, and makes sure
   * the file is usable.
   *
   * @param _name The name of the file to open.
   **/
  cDataFile(cString name);

  /**
   * The desctructor automatically closes the file.
   **/
  ~cDataFile(){ m_fp.close(); }

  /**
   * @return The file name used
   **/
  const cString & GetName() const { return m_name; }

  /**
   * @return A bool that indicates whether the file is actually usable.
   **/
  bool Good() const { return m_fp.good(); }

  /**
   * This function allows low-level write access to the file. Although
   * sometimes usefull, it provides the possibility to circumvent the
   * automatic documentation. Use with care.
   *
   * @return The output stream corresponding to the file.
   **/
  std::ofstream & GetOFStream() { return m_fp; }

  /**
   * Outputs a value into the data file.
   *
   * @param x The value to write (as double, int, or char *)
   *
   * @param descr A string that describes the meaning of the value. The string
   * will be written only once, before the first data line has been finished.
   **/

  void Write( double x,              const char * descr );
  void Write( int i,                 const char * descr );
  void Write( const char * data_str, const char * descr );
  void WriteBlockElement (double x, int element, int x_size );
  void WriteBlockElement (int i, int element, int x_size );

  /**
   * Writes a descriptive string into a data file. The string is only
   * written if the first data line hasn't been completed (Endl() hasn't
   * been called. This allows to output initial comments into a file.
   **/
  void WriteComment( const char * descr );

  /**
   * Same as WriteComment, but doesn't automatically include the # in the
   * front of the line.  This should only be used in special circumstances
   * where something outside of a typical comment needs to be at the top.
   **/
  void WriteRawComment( const char * descr );

  /**
   * Writes text string any where in the data file. This should only be used 
   * in special circumstances where something outside of a typical comment 
   * needs to be placed in the file.
   **/
  void WriteRaw( const char * descr );

  /**
   * Writes the description for a single column; keeps track of column numbers.
   **/
  void WriteColumnDesc(const char * descr );

  /**
   * Writes the current time into the data file. The time string is only
   * written if the first data line hasn't been completed (Endl() hasn't
   * been called.
   **/
  void WriteTimeStamp();

  /**
   * This function writes the comments that have accumulated. There should
   * normally be no reason to call this function. Endl() does the same thing
   * in a safer way.
   **/
  void FlushComments();
  
  /**
   * Write all data to disk and start a new line.
   **/
  void Endl();

  /**
   * Has the header been written to the file yet?
   **/
  bool HeaderDone() { return m_descr_written; }
  
  /**
   * This function makes sure that all cached data is written to the disk.
   **/
  void Flush(){ m_fp.flush(); }
};

#endif

Index: avida/current/source/tools/data_file_manager.cc
+++ avida/current/source/tools/data_file_manager.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef DATA_FILE_MANAGER_HH
#include "data_file_manager.hh"
#endif

#ifndef DATA_FILE_HH
#include "data_file.hh"
#endif

using namespace std;

//////////////////////
//  cDataFileManager
//////////////////////


cDataFileManager::~cDataFileManager()
{
  while (data_file_list.GetSize()) {
    delete data_file_list.Pop();
  }
}


cDataFile * cDataFileManager::InternalFind(const cString & name)
{
  tListIterator<cDataFile> list_it(data_file_list);
  while (list_it.Next() != NULL) {
    if (list_it.Get()->GetName() == name) return list_it.Get();
  }
  return NULL;
}


cDataFile & cDataFileManager::Get(const cString & name)
{
  // Find the file by this name...
  cDataFile * found_file = InternalFind(name);

  // If it hasn't been found, create it...
  if (found_file == NULL) {
    found_file = new cDataFile(name);
    data_file_list.Push(found_file);
  }

  // Make sure we got the name right...
  assert( found_file->GetName() == name );

  // and return it.
  return *found_file;
}


ofstream & cDataFileManager::GetOFStream(const cString & name)
{
  // Find the file by this name...
  cDataFile * found_file = InternalFind(name);

  // If it hasn't been found, create it...
  if (found_file == NULL) {
    found_file = new cDataFile(name);
    data_file_list.Push(found_file);
  }

  // Make sure we got the name right...
  assert( found_file->GetName() == name );

  // And return the releven stream...
  return found_file->GetOFStream();
}


void cDataFileManager::FlushAll()
{
  tListIterator<cDataFile> list_it(data_file_list);
  while (list_it.Next() != NULL) list_it.Get()->Flush();
}


bool cDataFileManager::Remove(const cString & name)
{
  cDataFile * found_file = InternalFind(name);
  if (found_file == NULL) return false;

  delete found_file;
  return true;
}

Index: avida/current/source/tools/data_file_manager.hh
+++ avida/current/source/tools/data_file_manager.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

/* data_file_manager.hh ********************************************************
 cDataFileManager

 charles at krl.caltech.edu & travc at ugcs.caltech.edu
 Time-stamp: <1999-01-07 10:02:09 travc>

 cString: basic string class
******************************************************************************/

#ifndef DATA_FILE_MANAGER_HH
#define DATA_FILE_MANAGER_HH

#include <fstream>

#ifndef TLIST_HH
#include "tList.hh"
#endif

/**
 * This class helps to manage a collection of data files. It is possible
 * to add files, to remove files, and to access existing files by name.
 **/

class cDataFile;
class cString;
template <class T> class tList; // aggregate

class cDataFileManager {
private:
  tList<cDataFile> data_file_list;

  cDataFile * InternalFind(const cString & name);

public:
  cDataFileManager() { ; }
  ~cDataFileManager();

  /**
   * Looks up the @ref cDataFile corresponding to the given name. If that
   * file hasn't been created previously, it is created now.
   *
   * @return The @ref cDataFile.
   * @param name The name of the file to look up/create.
   **/
  cDataFile & Get(const cString & name);

  /**
   * Looks up the ofstream corresponding to the file of the given name.
   * If that file hasn't been created previously, it is created now.
   *
   * Read the cautionary remarks about the function with the same name in
   * @ref cDataFile.
   *
   * @return The ofstream.
   * @param name The name of the file to look up/create.
   **/
  std::ofstream & GetOFStream(const cString & name);

  void FlushAll();

  /** Removes the given file, thereby closing it.
   *
   * @return true if file existed, otherwise false.
   **/
  bool Remove(const cString & name);
};

#endif

Index: avida/current/source/tools/data_manager_base.cc
+++ avida/current/source/tools/data_manager_base.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2001 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef DATA_MANAGER_BASE_HH
#include "data_manager_base.hh"
#endif

#include "data_file.hh"


using namespace std;


cDataManager_Base::~cDataManager_Base()
{
}


bool cDataManager_Base::PrintRow(cDataFile & data_file,
				 cString row_entries, char sep)
{
  bool result = true;

  row_entries.CompressWhitespace();

  // If we haven't output the header for this file yet, do so.
  if ( data_file.HeaderDone() == false ) {
    // Setup the format string for the top...
    cString format(row_entries);
    cString out_filetype(filetype);

    // Make sure its space seperated...
    if (sep != ' ') {
      int pos = -1;
      while ( (pos = format.Find(sep)) != -1 ) format[pos] = ' ';
    }

    // Write out the filetype and format strip
    out_filetype.Insert("#filetype ");
    format.Insert("#format ");
    data_file.WriteRawComment(out_filetype);
    data_file.WriteRawComment(format);

    // Setup the human-readable description...
    cString header_entries(row_entries);
    cString cur_desc;
    data_file.WriteComment(" ");
    data_file.WriteComment("Legend:");
    while (header_entries.GetSize() > 0) {
      cString cur_entry( header_entries.Pop(sep) );
      if ( GetDesc(cur_entry, cur_desc) == false ) {
	result = false;
	continue;
      }
      data_file.WriteColumnDesc(cur_desc);
    }
    data_file.FlushComments();
    data_file.Endl();
  }


  ofstream & fp = data_file.GetOFStream();
  while (row_entries.GetSize() > 0) {
    cString cur_entry( row_entries.Pop(sep) );
    if ( Print(cur_entry, fp) == false ) {
      cerr << "Data manager unable to find entry '"
	   << cur_entry << "'" << endl;
      result = false;
      continue;
    }
    fp << " ";
  }
  fp << endl;

  return result;
}


Index: avida/current/source/tools/data_manager_base.hh
+++ avida/current/source/tools/data_manager_base.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef DATA_MANAGER_BASE_HH
#define DATA_MANAGER_BASE_HH

#include <iostream>

#ifndef STRING_HH
#include "string.hh"
#endif

class cDataFile;
class cString; // aggregate

class cDataManager_Base {
private:
  cString filetype;
public:
  cDataManager_Base(const cString & in_filetype) : filetype(in_filetype) { ; }
  virtual ~cDataManager_Base();
  
  const cString & GetFiletype() const { return filetype; }

  virtual bool Print(const cString & name, std::ostream & fp) = 0;
  virtual bool GetDesc(const cString & name, cString & out_desc) = 0;

  bool PrintRow(cDataFile & data_file, cString row_entries, char sep=' ');
};

#endif

Index: avida/current/source/tools/default_message_display.cc
+++ avida/current/source/tools/default_message_display.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef DEFAULT_MESSAGE_DISPLAY_HH
#include "default_message_display.hh"
#endif

#ifndef STRING_HH
#include "string.hh"
#endif

using namespace std;

void cDefaultMessageDisplay::out(cString &final_msg)
{ *_out << final_msg << endl; _out->flush(); }

/*
default instantiations of cDefaultMessageDisplay...
*/
cDefaultMessageDisplay s_info_msg_cout(&cout);
cDefaultMessageDisplay s_debug_msg_cerr(&cerr);
cDefaultMessageDisplay s_error_msg_cerr(&cerr);
cDefaultMessageDisplay s_fatal_msg_cerr(&cerr);
cDefaultMessageDisplay s_noprefix_msg_cout(&cout);


Index: avida/current/source/tools/default_message_display.hh
+++ avida/current/source/tools/default_message_display.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef DEFAULT_MESSAGE_DISPLAY_HH
#define DEFAULT_MESSAGE_DISPLAY_HH

#include <iostream>

#ifndef MESSAGE_DISPLAY_HH
#include "message_display.hh"
#endif

/*
This subclass of cMessageDisplay just prints to stdout and stderr.

cMessageDisplay displays the message "final_msg" to the user/programmer.
cMessageDisplay is meant to be subclassed, where
  out(string final_msg)
is reimplemented to display "final_msg" in the desired manner. 

Instances of the subclass may then be passed to
  setStandardOutDisplay(cMessageDisplay &)
and
  setStandardErrDisplay(cMessageDisplay &)
with expected results.
*/

class cString;

class cDefaultMessageDisplay : public cMessageDisplay{
private:
  std::ostream *_out;
public:
  cDefaultMessageDisplay(std::ostream *stream):_out(stream){}
  void out(cString &final_msg);
};

extern cDefaultMessageDisplay s_info_msg_cout;
extern cDefaultMessageDisplay s_debug_msg_cerr;
extern cDefaultMessageDisplay s_error_msg_cerr;
extern cDefaultMessageDisplay s_fatal_msg_cerr;
extern cDefaultMessageDisplay s_noprefix_msg_cout;

#endif

Index: avida/current/source/tools/double_sum.cc
+++ avida/current/source/tools/double_sum.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef DOUBLE_SUM_HH
#include "double_sum.hh"
#endif

// cDoubleSum ////////////////////////////////////////////////////////////////

const double cDoubleSum::INF_ERR = 0;

Index: avida/current/source/tools/double_sum.hh
+++ avida/current/source/tools/double_sum.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef DOUBLE_SUM_HH
#define DOUBLE_SUM_HH

#include <math.h>
#include <limits.h>

class cDoubleSum {
private:
  double s1;  // Sum (x)
  double s2;  // Sum of squares (x^2)
  double s3;  // Sum of cubes (x^3)
  double s4;  // Sum of x^4
  double n;

public:
  static const double INF_ERR;  // Value Returned by StdError if Infinate

  cDoubleSum(){ Clear(); }

  void Clear(){ s1=0; s2=0; s3=0; s4=0; n=0; }

  double Count()        const { return n; }
  double N()            const { return n; }
  double Sum()          const { return s1; }
  double S1()           const { return s1; }
  double SumOfSquares() const { return s2; }
  double S2()           const { return s2; }
  double SumOfCubes()   const { return s3; }
  double S3()           const { return s3; }
  double S4()           const { return s4; }

  double Average() const { return ( n >1 ) ? (s1/n) : 0; }

  double Variance() const { return ( n > 1 ) ?
      (s2 - s1*s1/n) / (n-1) : INF_ERR; }
    //n*(s2/n - s1/n*s1/n) / (n-1) : INF_ERR; }
  double StdDeviation() const { return sqrt(Variance()); }
  double StdError()  const { return (n > 1) ?
         sqrt(Variance()/n) : INF_ERR; }

//      old formula, implemented by TCC, not sure how it relates to 
//      the real Standard Error
//       sqrt(s2 / (n * (n-1))) : INF_ERR; }

  double Skewness() const { return ( n > 2 ) ?
       (n*s3 - 3*s2*s1 + 2*s1*s1*s1/n) / ((n-1)*(n-2)) : INF_ERR; }
     //n*n*(s3/n - 3*s2/n*s1/n + 2*s1/n*s1/n*s1/n)/((n-1)*(n-2)) : INF_ERR; }

  double Kurtosis() const { return ( n > 3 ) ?
     //n*n*(n+1)*(s4/n - 4*s3/n*s1/n + 6*s2/n*s1/n*s1/n -
     //3*s1/n*s1/n*s1/n*s1/n)/((n-1)*(n-2)*(n-3)) :
       (n+1)*(n*s4 - 4*s3*s1 + 6*s2*s1*s1/n - 3*s1*s1*s1/n*s1/n) /
       ((n-1)*(n-2)*(n-3)) :
       INF_ERR; }

  // Notation Shortcuts
  double Ave() const { return Average(); }
  double Var() const { return Variance(); }
  double Kur() const { return Kurtosis(); }
  double Skw() const { return Skewness(); }


  void Add(double value, double weight=1){
    double w_val = value * weight;
    n += weight;
    s1 += w_val;
    s2 += w_val * w_val;
    s3 += w_val * w_val * w_val;
    s4 += w_val * w_val * w_val * w_val;
  }

  void Subtract(double value, double weight=1){
    double w_val = value * weight;
    n -= weight;
    s1 -= w_val;
    s2 -= w_val * w_val;
    s3 -= w_val * w_val * w_val;
    s4 -= w_val * w_val * w_val * w_val;
  }
};

#endif

Index: avida/current/source/tools/fixed_block.cc
+++ avida/current/source/tools/fixed_block.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef FIXED_BLOCK_HH
#include "fixed_block.hh"
#endif

////////////////////
//  cFixedBlock
////////////////////

cFixedBlock::cFixedBlock()
{
  start_point = 0;
}

cFixedBlock::~cFixedBlock()
{
}


Index: avida/current/source/tools/fixed_block.hh
+++ avida/current/source/tools/fixed_block.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef FIXED_BLOCK_HH
#define FIXED_BLOCK_HH

/**
 * Class used by @ref cBlockStruct.
 **/

class cFixedBlock {
private:
  int start_point;   // Starting point in the cScaledBlock array.
public:
  cFixedBlock();
  ~cFixedBlock();

  inline int GetStart() { return start_point; }
  inline void SetStart(int in_sp) { start_point = in_sp; }
};

#endif

Index: avida/current/source/tools/fixed_coords.hh
+++ avida/current/source/tools/fixed_coords.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef FIXED_COORDS_HH
#define FIXED_COORDS_HH

#ifndef UINT_HH
#include "uint.hh"
#endif

/**
 * Class used by @ref cBlockStruct.
 *
 * It handles co-ordinates in terms of block number
 * and offset.
 **/

class cUInt; // aggregate

class cFixedCoords {
private:
  int block_num;
  int offset;
public:
  inline cFixedCoords() {
    block_num = 0;
    offset = 0;
  }
  inline cFixedCoords(int in_block, int in_offset) {
    block_num = in_block;
    offset = in_offset;
  }

  inline int GetBlockNum() const { return block_num; }
  inline int GetOffset() const { return offset; }

  inline cUInt AsCUInt(int in_fixed_size) const {
    cUInt temp;
    temp = block_num * in_fixed_size + offset;
    return temp;
  }

  inline void operator()(int in_block, int in_offset) {
    block_num = in_block;
    offset = in_offset;
  }
  inline void operator=(const cFixedCoords & in_coords) {
    block_num = in_coords.GetBlockNum();
    offset = in_coords.GetOffset();
  }
  inline int operator<(const cFixedCoords & in_coords) const {
    return ((block_num < in_coords.block_num) ||
	    (block_num == in_coords.block_num && offset < in_coords.offset));
  }
  inline int operator<=(const cFixedCoords & in_coords) const {
    return ((block_num < in_coords.block_num) ||
	    (block_num == in_coords.block_num && offset <= in_coords.offset));
  }
  inline int operator>(const cFixedCoords & in_coords) const {
    return !operator<=(in_coords);
  }
  inline int operator>=(const cFixedCoords & in_coords) const {
    return !operator<(in_coords);
  }
  inline int operator==(const cFixedCoords & in_coords) const {
    return (block_num == in_coords.GetBlockNum() &&
            offset == in_coords.GetOffset());
  }

  inline void Add(cFixedCoords & other_coord, int fixed_size) {
    block_num += other_coord.GetBlockNum();
    offset += other_coord.GetOffset();
    block_num += offset / fixed_size;
    offset %= fixed_size;
  }
  inline void Add(int in_block, int in_offset, int fixed_size) {
    block_num += in_block;
    offset += in_offset;
    block_num += offset / fixed_size;
    offset %= fixed_size;
  }
};

#endif

Index: avida/current/source/tools/genesis.cc
+++ avida/current/source/tools/genesis.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef GENESIS_HH
#include "genesis.hh"
#endif

using namespace std;

/////////////////
//  cGenesis
/////////////////

cGenesis::cGenesis()
{
}

cGenesis::cGenesis(const cString & in_filename) : cInitFile(in_filename)
{
  if( !IsOpen() ){
    cerr<<"Failed to open '" << in_filename << "' file!!!\n" << endl;
  }

  Load();
  Compress();
  Close();
}

//int cGenesis::Open(cString _filename, int mode)
// porting to gcc 3.1 -- k
int cGenesis::Open(cString _filename, ios::openmode mode)
{
  if( IsOpen() ){
    cerr << "Trying to reopen '" << _filename << "' file!!!\n" << endl;
    return 0;
  }

  int base_ret = cFile::Open(_filename, mode);
  
  if (IsOpen() == false) return base_ret;  // Failed to open!

  Load();
  Compress();
  Close();

  return base_ret;
}

void cGenesis::AddInput(const cString & in_name, int in_value)
{
  cString in_string;
  in_string.Set("%s %d", in_name(), in_value);
  AddLine(in_string);
}

void cGenesis::AddInput(const cString & in_name, const cString & in_value)
{
  cString in_string;
  in_string.Set("%s %s", in_name(), in_value());
  AddLine(in_string);
}

int cGenesis::ReadInt(const cString & name, int base, bool warn) const
{
  if (name == "" || IsOpen() == false) return base;
  cString cur_line;

  if (!Find(cur_line, name, 0)) { 
    if (verbose == true && warn == true) {
      cout << "Warning: " << name << " not in \"" << GetFilename()
	   << "\", defaulting to: " << base <<endl;
    }
    return base;
  }

  return cur_line.GetWord(1).AsInt();
}

double cGenesis::ReadFloat(const cString & name, float base, bool warn) const
{
  if (name == "" || IsOpen() == false) return base;
  cString cur_line;

  if (!Find(cur_line, name, 0)) {
    if (verbose == true && warn == true) {
      cout << "Warning: " << name << " not in \"" << GetFilename()
	   << "\", defaulting to: " << base <<endl;
    }
    return base;
  }

  return cur_line.GetWord(1).AsDouble();
}

Index: avida/current/source/tools/genesis.hh
+++ avida/current/source/tools/genesis.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef GENESIS_HH
#define GENESIS_HH

#ifndef INIT_FILE_HH
#include "init_file.hh"
#endif
#ifndef STRING_HH
#include "string.hh"
#endif

/**
 * A specialized initialization file class that is used for setting up
 * the way Avida should run.
 */

class cString; // aggregate

class cGenesis : public cInitFile {
public:
    /** 
     * The empty constructor creates a clean object.
     **/
    cGenesis();
  
    /**
     * This constructor opens the given initialization file, reads it in,
     * removes all comments, and closes it again.
     **/
    cGenesis(const cString & filename);

    /**
     * Opens an initialization file, reads it in, removes all comments, and 
     * closes it again.
     **/
    //int Open(cString _filename, int mode=(ios::in|ios::nocreate));
    // porting to gcc 3.1
    // nocreate is no longer in the class ios -- k
    int Open(cString _filename, std::ios::openmode mode=(std::ios::in));

    /**
     * Convenience function. Adds an integer valued entry to the file in
     * memory. Uses @ref cInitFile::AddLine().
     **/
    void AddInput(const cString & in_name, int in_value);
  
    /**
     * Convenience function. Adds a string valued entry to the file in
     * memory. Uses @ref cInitFile::AddLine().
     **/
    void AddInput(const cString & in_name, const cString & in_value);
    
    /**
     * Reads an entry of type int. In case the entry does not exist,
     * the value of base is returned.
     *
     * @param name The name of the entry.
     * @param base The default value.
     * @param warn Warn user if not set?
     **/
    int ReadInt (const cString & name, int base=0, bool warn=true) const;
  
    /**
     * Reads an entry of type float. In case the entry does not exist,
     * the value of base is returned.
     *
     * @param name The name of the entry.
     * @param base The default value.
     * @param warn Warn user if not set?
     **/
     double ReadFloat (const cString & name, float base=0.0, bool warn=true) const;

  void Read(cString & _var, const cString & _name, const cString & _def="") {
    _var = ReadString(_name, _def);
  }

  void Read(int & _var, const cString & _name, const cString & _def="0") {
    _var = ReadInt(_name, _def.AsInt());
  }

  void Read(double & _var, const cString & _name, const cString & _def="0.0") {
    _var = ReadFloat(_name, _def.AsDouble());
  }

  void Read(bool & _var, const cString & _name, const cString & _def="0.0") {
    _var = ReadInt(_name, _def.AsInt()) != 0;
  }
};

#endif


Index: avida/current/source/tools/help_alias.cc
+++ avida/current/source/tools/help_alias.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef HELP_ALIAS_HH
#include "help_alias.hh"
#endif

#ifndef HELP_FULL_ENTRY_HH
#include "help_full_entry.hh"
#endif

const cString & cHelpAlias::GetKeyword() const { return full_entry->GetKeyword(); }
const cString & cHelpAlias::GetDesc() const { return full_entry->GetDesc(); }
cHelpType * cHelpAlias::GetType() const { return full_entry->GetType(); }

Index: avida/current/source/tools/help_alias.hh
+++ avida/current/source/tools/help_alias.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef HELP_ALIAS_HH
#define HELP_ALIAS_HH

#ifndef HELP_ENTRY_HH
#include "help_entry.hh"
#endif

class cHelpFullEntry;
class cHelpType;
class cString;

class cHelpAlias : public cHelpEntry {
private:
  cHelpFullEntry * full_entry;
public:
  cHelpAlias(const cString & _alias, cHelpFullEntry * _full_entry)
    : cHelpEntry(_alias), full_entry(_full_entry) { ; }
  ~cHelpAlias() { ; }

  const cString & GetKeyword() const;
  const cString & GetDesc() const;
  cHelpType * GetType() const;

  bool IsAlias() const { return true; }
};

#endif

Index: avida/current/source/tools/help_entry.hh
+++ avida/current/source/tools/help_entry.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef HELP_ENTRY_HH
#define HELP_ENTRY_HH

#ifndef STRING_HH
#include "string.hh"
#endif
#ifndef STRING_UTIL_HH
#include "string_util.hh"
#endif

class cHelpType;
class cString; // aggregate
class cStringUtil; // accessed

class cHelpEntry {
protected:
  cString name;
public:
  cHelpEntry(const cString & _name) : name(_name) { ; }
  virtual ~cHelpEntry() { ; }

  const cString & GetName() const { return name; }
  virtual const cString & GetKeyword() const = 0;
  virtual const cString & GetDesc() const = 0;
  virtual cHelpType * GetType() const = 0;

  virtual bool IsAlias() const = 0;

  cString GetHTMLFilename() const
    { return cStringUtil::Stringf("help.%s.html", GetKeyword()()); }
};

#endif

Index: avida/current/source/tools/help_full_entry.hh
+++ avida/current/source/tools/help_full_entry.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef HELP_FULL_ENTRY_HH
#define HELP_FULL_ENTRY_HH

#ifndef HELP_ENTRY_HH
#include "help_entry.hh"
#endif
#ifndef STRING_HH
#include "string.hh"
#endif

class cHelpType;
class cString; // aggregate

class cHelpFullEntry : public cHelpEntry {
private:
  cHelpType * type;
  cString desc;
public:
  cHelpFullEntry(const cString & _name, cHelpType * _type, const cString _desc)
    : cHelpEntry(_name), type(_type), desc(_desc) { ; }
  cHelpFullEntry() : cHelpEntry(""), type(NULL) { ; }
  ~cHelpFullEntry() { ; }

  const cHelpFullEntry & operator=(const cHelpEntry & in_entry) {
    name = in_entry.GetName();
    type = in_entry.GetType();
    desc = in_entry.GetDesc();
    return *this;
  }

  const cString & GetKeyword() const { return name; }
  const cString & GetDesc() const { return desc; }
  cHelpType * GetType() const { return type; }

  bool IsAlias() const { return false; }
};

#endif

Index: avida/current/source/tools/help_manager.cc
+++ avida/current/source/tools/help_manager.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef HELP_MANAGER_HH
#include "help_manager.hh"
#endif

#ifndef HELP_TYPE_HH
#include "help_type.hh"
#endif
#ifndef INIT_FILE_HH
#include "init_file.hh"
#endif
#ifndef STRING_HH
#include "string.hh"
#endif
#ifndef TLIST_HH
#include "tList.hh"
#endif

#include <iostream>

using namespace std;

cHelpType * cHelpManager::GetType(const cString type_name)
{
  // See if we can find this type in the already existant list...
  tListIterator<cHelpType> type_it(type_list);
  while (type_it.Next() != NULL) {
    if (type_it.Get()->GetName() == type_name) return type_it.Get();
  }

  // Otherwise, create it.
  if (verbose == true) {
    cout << "  Creating help type \"" << type_name << "\"." << endl;
  }
  cHelpType * type = new cHelpType(type_name, this);
  type_list.Push(type);
  return type;
}

void cHelpManager::LoadFile(const cString & filename)
{
  cInitFile help_file(filename);
  help_file.Load();
  help_file.Compress();
  help_file.Close();

  cHelpType * type = NULL;
  cString keyword;

  for (int line_id = 0; line_id < help_file.GetNumLines(); line_id++) {
    cString cur_string = help_file.GetLine(line_id);
    cString command = cur_string.PopWord();
    command.ToLower();

    if (command == "type:") {
      type = GetType(cur_string);
    }
    else if (command == "keyword:") {
      keyword = cur_string;
    }
    else if (command == "desc:") {
      if (type == NULL) type = GetType("None"); // Make sure we have a type.
      if (keyword == "") {
	if (verbose == true) {
	  cerr << "  Help description set without keyword;"
	       << " setting keyword to \"None\"." << endl;
	}
	keyword = "None";
      }
      last_entry = type->AddEntry(keyword, cur_string);
    }
    else if (command == "alias:") {
      if (last_entry == NULL) {
	cerr << "  Warning: Setting aliases \"" << cur_string
	     << "\" to incomplete entry!" << endl;
      }
      while (cur_string.GetSize() > 0) {
	type->AddAlias(cur_string.PopWord(), last_entry);
      }
    }
    else if (verbose == true) {
      cerr << "Warning: Unknown command \"" << command
	   << "\" in file " << filename << endl;
    }
  }

}


void cHelpManager::PrintHTML()
{
  tListIterator<cHelpType> type_it(type_list);
  while (type_it.Next() != NULL) {
    type_it.Get()->PrintHTML();
  }
}

Index: avida/current/source/tools/help_manager.hh
+++ avida/current/source/tools/help_manager.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef HELP_MANAGER_HH
#define HELP_MANAGER_HH

#ifndef HELP_TYPE_HH
#include "help_type.hh"
#endif
#ifndef STRING_HH
#include "string.hh"
#endif
#ifndef TLIST_HH
#include "tList.hh"
#endif

class cHelpFullEntry;
class cHelpType; // accessed
class cString; // aggregate
template <class T> class tList; // aggregate
template <class T> class tListIterator; // aggregate

class cHelpManager {
private:
  tList<cHelpType> type_list;
  cHelpFullEntry * last_entry;
  bool verbose;   // Should we print messages to the screen?

  // Private methods...
  cHelpType * GetType(const cString type_name);
public:
  cHelpManager() : last_entry(NULL), verbose (false) { ; }
  ~cHelpManager() { while (type_list.GetSize() > 0) delete type_list.Pop(); }

  void LoadFile(const cString & filename);
  void PrintHTML();
  cHelpEntry * FindEntry(cString entry_name) {
    entry_name.ToLower();

    tListIterator<cHelpType> type_it(type_list);
    while (type_it.Next() != NULL) {
      cHelpEntry * found_entry = type_it.Get()->FindEntry(entry_name);
      if (found_entry != NULL) return found_entry;
    }
    return NULL;
  }
  
  void SetVerbose(bool _verbose = true) { verbose = _verbose; }
  bool GetVerbose() const { return verbose; }
};

#endif

Index: avida/current/source/tools/help_type.cc
+++ avida/current/source/tools/help_type.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef HELP_TYPE_HH
#include "help_type.hh"
#endif

#ifndef HELP_ALIAS_HH
#include "help_alias.hh"
#endif
#ifndef HELP_ENTRY_HH
#include "help_entry.hh"
#endif
#ifndef HELP_FULL_ENTRY_HH
#include "help_full_entry.hh"
#endif
#ifndef HELP_MANAGER_HH
#include "help_manager.hh"
#endif

#include <fstream>

using namespace std;

cHelpAlias * cHelpType::AddAlias(const cString & alias_name, cHelpFullEntry * entry) {
  cHelpAlias * new_alias = new cHelpAlias(alias_name, entry);
  entry_list.Push(new_alias);
  return new_alias;
}

cHelpFullEntry * cHelpType::AddEntry(const cString & _name, const cString & _desc) {
  cHelpFullEntry * new_entry = new cHelpFullEntry(_name, this, _desc);
  entry_list.Push(new_entry);
  num_entries++;
  return new_entry;
}

cHelpEntry * cHelpType::FindEntry(const cString & entry_name) {
  tListIterator<cHelpEntry> entry_it(entry_list);
  while (entry_it.Next() != NULL) {
    if (entry_it.Get()->GetName() == entry_name) {
      return entry_it.Get(); // Found!
    }
  }
  return NULL;  // Not found...
}

cHelpType::~cHelpType() { while (entry_list.GetSize() > 0) delete entry_list.Pop(); }

void cHelpType::PrintHTML()
{
  if (manager->GetVerbose()) cout << "  Category: " << GetName() << endl;

  cHelpEntry * cur_entry = NULL;
  tListIterator<cHelpEntry> entry_it(entry_list);

  while ( (cur_entry = entry_it.Next()) != NULL) {
    // Only print non-alias entries...
    if (cur_entry->IsAlias() == true) continue;
    
    ofstream fp(cur_entry->GetHTMLFilename());
    
    fp << "<html>" << endl
       << "<title>" << GetName() << " : "
       << cur_entry->GetName() << "</title>" << endl << endl
       << "<h1>" << cur_entry->GetName() << "</h1>" << endl << endl;
    
    cString out_desc( cur_entry->GetDesc() );
    int pos = 0;
    while ((pos = out_desc.Find('!', pos)) != -1) {
      // Grab the word we need to replace
      cString found_word(out_desc.GetWordAt(pos));
      cString new_word;
      
      // If we have a double '!' reduce it to a single one and continue...
      if (found_word[1] == '!') {
	out_desc.Replace("!!", "!", pos);
	pos++;
      }
      
      // Otherwise, do a proper replacement...
      else {
	// Find the root keyword...
	cString keyword(found_word);
	keyword.ClipFront(1); // Clip off the '!' on the string.
	
	// Clip end punctuation and save it if there is any.
	char end_char = ' ';
	const int last_pos = keyword.GetSize() - 1;
	if (keyword.IsNumeric(last_pos) == false &&
	    keyword.IsLetter(last_pos) == false) {
	  end_char = keyword[keyword.GetSize() - 1];
	  keyword.ClipEnd(1);
	}
	// User can end a word in a '!' to preserve other punctuation...
	if (end_char == '!') end_char = ' ';

	// Determine what filename contains the new word...
	cHelpEntry * found_entry = manager->FindEntry(keyword);
	if (found_entry == NULL) {
	  if (manager->GetVerbose() == true) {
	    cerr << "  Warning: unknown help keyword \""
		 << keyword << "\"." << endl;
	  }
	  new_word.Set("<a href=\"help.%s.html\">%s</a>%c",
		       keyword(), keyword(), end_char);
	}
	else {
	  new_word.Set("<a href=\"%s\">%s</a>%c",
		  found_entry->GetHTMLFilename()(), keyword(), end_char);
	}

	// Rebuild the description with the new word...
	out_desc.Replace(found_word, new_word, pos);
	pos += new_word.GetSize();
      }
    }

    fp << out_desc << endl;
  }
}


Index: avida/current/source/tools/help_type.hh
+++ avida/current/source/tools/help_type.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef HELP_TYPE_HH
#define HELP_TYPE_HH

#ifndef STRING_HH
#include "string.hh"
#endif
#ifndef TLIST_HH
#include "tList.hh"
#endif

class cHelpAlias;
class cHelpEntry;
class cHelpFullEntry;
class cHelpManager;
class cString; // aggregate
template <class T> class tList; // aggregate

class cHelpType {
private:
  cString name;
  tList<cHelpEntry> entry_list;
  cHelpManager * manager;
  int num_entries;
public:
  cHelpType(const cString & _name, cHelpManager * _manager)
    : name(_name), manager(_manager), num_entries(0) { ; }
  ~cHelpType();
  cHelpFullEntry * AddEntry(const cString & _name, const cString & _desc);
  cHelpAlias * AddAlias(const cString & alias_name, cHelpFullEntry * entry);
  const cString & GetName() const { return name; }
  cHelpEntry * FindEntry(const cString & entry_name);

  void PrintHTML();
};

#endif

Index: avida/current/source/tools/histogram.cc
+++ avida/current/source/tools/histogram.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef HISTOGRAM_HH
#include "histogram.hh"
#endif

#ifndef FUNCTIONS_HH
#include "functions.hh"
#endif

#include <stdio.h>

// cHistogram /////////////////////////////////////////////////////////////////

cHistogram::cHistogram(int in_max, int in_min) {
  max_bin = in_max;
  min_bin = in_min;
  entry_count = 0;
  entry_total = 0;

  int num_bins = max_bin - min_bin + 1;
  bins = new int[num_bins];
  for (int i = 0; i < num_bins; i++)   bins[i] = 0;
}

void cHistogram::Resize(int new_max, int new_min)
{
#ifdef DEBUG
  if (new_max < new_min) {
    fprintf(stderr, "ERROR: Trying to resize histogram to [%d,%d]\n",
	    new_min, new_max);
    return;
  }
#endif

  // Calculate new num bins.
  int new_num_bins = new_max - new_min + 1;

  // Setup new bins, copying over information...
  int cur_bin = 0;
  int overlap_min = Max(min_bin, new_min);
  int overlap_max = Min(max_bin, new_max);

  int * new_bins = new int[new_num_bins];
  for (cur_bin = new_min; cur_bin < min_bin; cur_bin++)
    new_bins[cur_bin - new_min] = 0;
  for (cur_bin = max_bin; cur_bin <= new_max; cur_bin++)
    new_bins[cur_bin - new_min] = 0;
  for (cur_bin = overlap_min; cur_bin <= overlap_max; cur_bin++)
    new_bins[cur_bin - new_min] = bins[cur_bin - min_bin];

  // Re-count bins...
  int new_count = 0;
  int new_total = 0;
  for (int i = 0; i < new_num_bins; i++) {
    new_count += new_bins[i];
    new_total += new_bins[i] * (i + new_min);
  }
  entry_count = new_count;
  entry_total = new_total;

  delete [] bins;
  bins = new_bins;
  max_bin = new_max;
  min_bin = new_min;
}

void cHistogram::Print()
{
  FILE * fp = fopen("test.dat", "w");
  fprintf(fp, "Min = %d, Max = %d, Count = %d, Total = %d, Ave = %f\n",
	  min_bin, max_bin, entry_count, entry_total, GetAverage());
  for (int i = min_bin; i <= max_bin; i++) {
    fprintf(fp, "%d : %d\n", i, bins[i - min_bin]);
  }
  fflush(fp);
  fclose(fp);
}

Index: avida/current/source/tools/histogram.hh
+++ avida/current/source/tools/histogram.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef HISTOGRAM_HH
#define HISTOGRAM_HH

#include <iostream>

class cHistogram {
private:
  int * bins;
  int min_bin;
  int max_bin;
  int entry_count;
  int entry_total;
public:
  cHistogram(int in_max=1, int in_min=0);
  inline ~cHistogram() { delete [] bins; }

  void Resize(int new_max, int new_min=0);
  void Print();
  inline void Clear();
  inline void Insert(int value, int count=1);
  inline void Remove(int value);
  inline void RemoveBin(int value);

  inline double GetAverage()
    { return ((double)entry_total) / (double)entry_count; }
  inline double GetCountAverage()
    { return (double) entry_count / (double) GetNumBins(); }
  inline int GetMode();
  inline double GetVariance();
  inline double GetCountVariance();
  inline double GetStdDev();
  inline double GetCountStdDev();
  inline double GetEntropy();
  inline double GetNormEntropy();

  inline int GetCount() { return entry_count; }
  inline int GetCount(int value) { return bins[value - min_bin]; }
  inline int GetTotal() { return entry_total; }
  inline int GetMinBin() { return min_bin; }
  inline int GetMaxBin() { return max_bin; }
  inline int GetNumBins() { return max_bin - min_bin + 1; }
};

inline void cHistogram::Clear()
{
  int num_bins = GetNumBins();
  for (int i = 0; i < num_bins; i++) {
    bins[i] = 0;
  }
  entry_count = 0;
  entry_total = 0;
}


inline void cHistogram::Insert(int value, int count)
{
  if (value > max_bin || value < min_bin) {
    std::cerr << "Trying to insert " << value << " into Histogram of range ["
	 << min_bin << "," << max_bin << "]" << std::endl;
  }

  bins[value - min_bin] += count;
  entry_count += count;
  entry_total += value * count;
}

inline void cHistogram::Remove(int value)
{
#ifdef DEBUG
  if (value > max_bin || value < min_bin) {
    std::cerr << "Trying to remove " << value << " into Histogram of range ["
	 << min_bin << "," << max_bin << "]" << std::endl;
    return;
  }
  if (bins[value] <= 1) {
    std::cerr << "WARNING: Trying to remove " << value << " from bin with "
	 << bins[value] << " entries" << std::endl;
    return;
  }
#endif

  bins[value - min_bin]--;
  entry_count--;
  entry_total -= value;
}

inline void cHistogram::RemoveBin(int value)
{
#ifdef DEBUG
  if (value > max_bin || value < min_bin) {
    std::cerr << "WARNING: Trying to remove " << value
	 << " in histogram of range [" << min_bin << "," <<  max_bin
	 << "]" << std::endl;
    return;
  }
#endif

  int old_size = bins[value - min_bin];
  bins[value - min_bin] = 0;

  entry_count -= old_size;
  entry_total -= value * old_size;
}

inline int cHistogram::GetMode()
{
  int num_bins = GetNumBins();
  int mode = 0;
  for (int i = 1; i < num_bins; i++) {
    if (bins[i] > bins[mode]) mode = i;
  }

  return mode + min_bin;
}

inline double cHistogram::GetVariance()
{
  if (entry_count < 2) return 0;

  double mean = GetAverage();
  double var = 0;
  double value = 0;

  int num_bins = GetNumBins();
  for (int i = 0; i < num_bins; i++) {
    value = (double) (i + min_bin) - mean;
    var += bins[i] * value * value;
  }
  var /= entry_count - 1;

  return var;
}

inline double cHistogram::GetCountVariance()
{
  int num_bins = GetNumBins();
  if (num_bins < 2) return 0;

  double mean = GetCountAverage();
  double var = 0;
  double value = 0;

  for (int i = 0; i < num_bins; i++) {
    value = (double) bins[i] - mean;
    var += value * value;
  }
  var /= num_bins - 1;

  return var;
}

inline double cHistogram::GetStdDev()
{
  return sqrt(GetVariance());
}

inline double cHistogram::GetCountStdDev()
{
  return sqrt(GetCountVariance());
}

inline double cHistogram::GetEntropy()
{
  int num_bins = GetNumBins();

  double entropy = 0.0;
  double prob = 0.0;

  for (int i = 0; i < num_bins; i++) {
    prob = (double) bins[i] / (double) entry_count;
    entropy -= prob * log(prob);
  }

  return entropy;
}

inline double cHistogram::GetNormEntropy()
{
  int num_bins = GetNumBins();

  double entropy = 0.0;
  double prob = 0.0;

  for (int i = 0; i < num_bins; i++) {
    prob = ((double) bins[i]) / (double) entry_count;
    if (prob != 0.0) entropy -= prob * log(prob);
  }

  return entropy / log((double) num_bins);
}

#endif

Index: avida/current/source/tools/indexed_block_struct.cc
+++ avida/current/source/tools/indexed_block_struct.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef INDEXED_BLOCK_STRUCT_HH
#include "indexed_block_struct.hh"
#endif

//////////////////////////
//  cIndexedBlockStruct
//////////////////////////

cIndexedBlockStruct::cIndexedBlockStruct(int in_num_scaled, int in_num_fixed,
					 int in_num_ref)
{
  num_fixed = in_num_fixed;
  num_scaled = in_num_scaled;
  num_ref = in_num_ref;
  num_data = 0;

  fixed_array = new cFixedBlock[num_fixed];
  scaled_array = new cRefBlock[num_scaled];
  ref_array = new int[num_ref];

  int i;
  for (i = 0; i < num_ref; i++) {
    ref_array[i] = -1;
  }

  fixed_used(0, 0);
  scaled_used = 0;

  total_size = 0;
  fixed_size = 0;
}

cIndexedBlockStruct::~cIndexedBlockStruct()
{
  delete [] scaled_array;
  delete [] fixed_array;
  delete [] ref_array;
}

int cIndexedBlockStruct::AddData(int in_ref, int in_size)
{
  // Only allow positive sized data, and only if there is room.
  if (in_size <= 0 || scaled_used >= num_scaled) return -1;    

  // If this reference is already represented, combine them.
  if (ref_array[in_ref] >= 0) {
    in_size += scaled_array[ref_array[in_ref]].GetSize();
    RemoveRef(in_ref);
  }

  scaled_array[scaled_used].SetRef(in_ref);
  scaled_array[scaled_used].SetSize(in_size);
  ref_array[in_ref] = scaled_used;
  
  total_size += in_size;
  num_data++;

  return scaled_used++;
}

int cIndexedBlockStruct::AddDataTo(int in_ref, int in_index)
{
  if (ref_array[in_ref] < 0) num_data++;

  scaled_array[in_index].SetRef(in_ref);
  ref_array[in_ref] = in_index;

  return scaled_array[in_index].GetSize();
}

void cIndexedBlockStruct::Clear()
{
  for (int i = 0; i < num_ref; i++) {
    ref_array[i] = -1;
  }

  fixed_used(0,0);
  scaled_used = 0;

  total_size = 0;
  num_data = 0;
}

int cIndexedBlockStruct::Process()
{
  if (!fixed_size) {
    CalcFixedSize();
  }

  int cur_scaled = 0;
  int cur_fixed = 0;
  int size_left = scaled_array[0].GetSize();

  // Set up the internal data for the first scaled block.

  scaled_array[0].SetStart(0, 0);

  // Move through the fixed blocks assigning each to the corresponding scaled
  // block.  This is done by keeping track of the current scaled block for
  // a particular location, and keeping track the "size" until the next block.
  
  for(cur_fixed = 0; cur_fixed < num_fixed; cur_fixed++) {
    // Set the current fixed block to point to whatever scaled block we are
    // currently in.

    fixed_array[cur_fixed].SetStart(cur_scaled);

    // If the current scaled block covers the entire fixed block, then just
    // adjust the size_left and move on.

    if (size_left > fixed_size) {
      size_left -= fixed_size;
      continue;
    }

    // Otherwise, start moving through the scaled blocks until the size can
    // be covered.

    while (size_left <= fixed_size) {
      // move onto the next scaled block...
      cur_scaled++;

      //  Check to see if we are finished...
      if (cur_scaled == scaled_used) {
	fixed_used(cur_fixed, size_left);  // Store max coord
	return cur_fixed + 1;
      }

      // Setup the next cRefBlock...

      scaled_array[cur_scaled].SetStart(cur_fixed, size_left);
      if (size_left == fixed_size) {
	scaled_array[cur_scaled].SetStart(cur_fixed + 1, 0);
      }

      // Add the size of the new cRefBlock onto the size_left.

      size_left += scaled_array[cur_scaled].GetSize();
    }

    // Move onto the next fixed block.
    size_left -= fixed_size;
  }

  return -1;
}

int cIndexedBlockStruct::Update()
{
  // @CAO make sure a process has been done at some point in the past?

  // If the data to NULL ratio is too low, have the update fail.
  // @CAO make this configurable!

  if (num_data * 2 + 2 < scaled_used) {
    return -1;
  }

  // Start out where the last Process() finished.

  int cur_scaled = fixed_array[fixed_used.GetBlockNum()].GetStart();
  int cur_fixed = scaled_array[cur_scaled].GetStart().GetBlockNum();
  int cur_offset = scaled_array[cur_scaled].GetStart().GetOffset();
  int size_left = scaled_array[cur_scaled].GetSize();

  // Re-adjust to make sure we are starting at the begining of a fixed block.

  if (cur_offset) {
    size_left += cur_offset - fixed_size;
    cur_fixed++;
  }

  // Move through the fixed blocks assigning each to the corresponding scaled
  // block.  This is done by keeping track of the current scaled block for
  // a particular location, and keeping track the "size" until the next block.
  
  for(; cur_fixed < num_fixed; cur_fixed++) {
    // Set the current fixed block to point to whatever scaled block we are
    // currently in.

    fixed_array[cur_fixed].SetStart(cur_scaled);

    // If the current scaled block covers the entire fixed block, then just
    // adjust the size_left and move on.

    if (size_left > fixed_size) {
      size_left -= fixed_size;
      continue;
    }

    // Otherwise, start moving through the scaled blocks until the size can
    // be covered.

    while (size_left <= fixed_size) {
      // move onto the next scaled block...
      cur_scaled++;

      //  Check to see if we are finished...
      if (cur_scaled == scaled_used) {
	fixed_used(cur_fixed, size_left);  // Store max coord
	return cur_fixed + 1;
      }

      // Setup the next cScaledBlock...

      scaled_array[cur_scaled].SetStart(cur_fixed, size_left);
      if (size_left == fixed_size) {
	scaled_array[cur_scaled].SetStart(cur_fixed + 1, 0);
      }

      // Add the size of the new cScaledBlock onto the size_left.

      size_left += scaled_array[cur_scaled].GetSize();
    }

    // Move onto the next fixed block.
    size_left -= fixed_size;
  }

  return -1;
}

int cIndexedBlockStruct::Compress()
{
  int scan_loc;
  int write_loc = 0;

  total_size = 0;
  for (scan_loc = 0; scan_loc < scaled_used; scan_loc++) {
    if (scaled_array[scan_loc].GetRef() >= 0) {
      if (scan_loc != write_loc) {
	scaled_array[write_loc] = scaled_array[scan_loc];
	scaled_array[scan_loc].SetRef(-1);
	scaled_array[scan_loc].SetSize(0);
	ref_array[scaled_array[write_loc].GetRef()] = write_loc;
      }
      total_size += scaled_array[write_loc].GetSize();
      write_loc++;
    }
  }

  scaled_used = write_loc;

  if (scaled_used != num_data)
    printf("WARNING: after Compress() scaled_used = %d, while num_data = %d\n",
	   scaled_used, num_data);

  return scaled_used;
}

void cIndexedBlockStruct::RemoveRef(int in_ref)
{
  if (ref_array[in_ref] >= 0) num_data--;
  scaled_array[ref_array[in_ref]].SetRef(-1);
  ref_array[in_ref] = -1;
}

Index: avida/current/source/tools/indexed_block_struct.hh
+++ avida/current/source/tools/indexed_block_struct.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

// See block_struct_proto.hh for a good description of this structure.

// This file is a variation of the cBlockStruct data structure.  It uses
// reference numbers (which it takes in and passed out) rather than void
// pointers.  Additionally, it has a third array in which index i contains
// the location in the scaled array for reference number i, so that 
// reference numbers are not lost with compression.  The structure must be
// initialized with the maximum reference number which will be passed into
// it (so as to create the third array of that size.

#ifndef INDEXED_BLOCK_STRUCT_HH
#define INDEXED_BLOCK_STRUCT_HH

#ifndef FIXED_BLOCK_HH
#include "fixed_block.hh"
#endif
#ifndef FIXED_COORDS_HH
#include "fixed_coords.hh"
#endif
#ifndef REF_BLOCK_HH
#include "ref_block.hh"
#endif
#ifndef UINT_HH
#include "uint.hh"
#endif

class cFixedBlock; // accessed
class cRefBlock; // accessed
class cFixedCoords; // aggregate
class cUInt; // aggregate

class cIndexedBlockStruct {
private:
  cFixedBlock * fixed_array;
  cRefBlock * scaled_array;
  int * ref_array;

  int num_fixed;
  int num_scaled;
  int num_ref;
  int num_data;

  cFixedCoords fixed_used;
  int scaled_used;

  cUInt total_size;
  int fixed_size;
public:
  cIndexedBlockStruct(int in_num_scaled = 1, int in_num_fixed = 1,
		      int in_num_ref = 1);
  ~cIndexedBlockStruct();

  // The following functions add a single piece of data to the scaled array,
  // but do not update the fixed array yet.  In the first, the data and its
  // size are entered, and an index into the scaled block array returned, or
  // else -1 if the array is full.  In the second, the data and the index
  // into the array are entered, and the size at that location returned.
  int AddData(int in_ref, int in_size);
  int AddDataTo(int in_ref, int in_index);

  // This function removes all of the data from the structure.
  void Clear();

  // This function takes the scaled array, and from it fully constructs the
  // proper fixed array.  Any information  which was in the fixed array is
  // completely erased and re-constructed.  The number of cFixedBlock's used
  // is returned, or -1 if it overflows.
  int Process();

  // The next function looks at data which has been taken in since the last
  // time the fixed array was built or updated, and the new info at the end.
  // The total number of cFixedBlock's used is returned, or -1 if it overflows.
  int Update();

  // This function takes the scaled array, and removes any elements from it
  // which no longer point to data, and compresses everything to the begining.
  // This should always be followed shortly by adding any new data, and then
  // a Process().  The new number of cRefBlock's used is returned.
  int Compress();

  // Two functions to retrieve data from the structure.
  inline int Find(cFixedCoords & search_coords) const;
  inline int Find(int in_block, int in_offset) const;
  inline int Find(cUInt in_position) const;

  // A function to remove data from the structure...
  void RemoveRef(int in_ref);

  // Finally, internal variable control...
  inline int GetFixedSize() const { return fixed_size; }
  inline int GetBlocksUsed() const { return fixed_used.GetBlockNum() + 1; }
  inline void SetFixedSize(int in_fs) {
    fixed_size = in_fs;
  }
  inline void CalcFixedSize() {
    if (num_data && total_size.AsInt()) {
      fixed_size = (total_size / num_data).AsInt();
    }
    else fixed_size = 1;
  }
};

inline int cIndexedBlockStruct::Find(cFixedCoords & search_coords) const
{
  // Make sure the find is within range.
  if (search_coords >= fixed_used) {
    return -1;
  }

  // Find the starting point in the scaled array for the search.
  int scaled_loc = fixed_array[search_coords.GetBlockNum()].GetStart();
  cFixedCoords cur_coords = scaled_array[scaled_loc].GetStart();

  // Starting at the starting point, move through the array until the entry
  // which covers this area is found.
  cur_coords.Add(0, scaled_array[scaled_loc].GetSize(), fixed_size);

  while (cur_coords <= search_coords) {
    scaled_loc++;
    cur_coords.Add(0, scaled_array[scaled_loc].GetSize(), fixed_size);
  }

  // Return the data in the found entry.
  return scaled_array[scaled_loc].GetRef();
}

inline int cIndexedBlockStruct::Find(int in_block, int in_offset) const
{
  cFixedCoords search_coords(in_block, in_offset);
  return Find(search_coords);
}

inline int cIndexedBlockStruct::Find(cUInt in_position) const
{
  cFixedCoords search_coords((in_position /= fixed_size).AsInt(),
			     (in_position %= fixed_size).AsInt());
  return Find(search_coords);
}

#endif

Index: avida/current/source/tools/init_file.cc
+++ avida/current/source/tools/init_file.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef INIT_FILE_HH
#include "init_file.hh"
#endif

#ifndef STRING_ITERATOR_HH
#include "string_iterator.hh"
#endif

using namespace std;

////////////////
//  cInitFile
////////////////

cInitFile::cInitFile() : filetype("unknown"), active_line(0)
{
}

cInitFile::cInitFile(cString in_filename)
  : cFile(in_filename)
  , filetype("unknown")
  , active_line(0)
{
}

cInitFile::~cInitFile()
{
}

void cInitFile::Load()
{
  if (!IsOpen()) return;   // The file must be opened!
  cStringList line_list;   // Create a list to load all of the lines into.

  cString buf;
  ReadLine(buf);

  // If this file doesn't work properly, return!
  if ( Eof() && !buf.GetSize() ) return;

  line_list.PushRear(buf);

  ReadLine(buf);
  while( !Eof() || buf.GetSize() ){
    line_list.PushRear(buf);
    ReadLine(buf);
  }

  // Copy all of the lines into the line array.
  const int file_size = line_list.GetSize();
  line_array.Resize(file_size);

  for (int i = 0; i < file_size; i++) {
    line_array[i].line = line_list.Pop();
    line_array[i].line_num = i;
    line_array[i].used = false;
  }
}

void cInitFile::LoadStream(istream & in_stream)
{
  if (in_stream.good() == false) {
    cerr << "Bad stream sent to cInitFile::LoadStream()" << endl;
    return;
  }

  cStringList line_list;   // Create a list to load all of the lines into.

  char cur_line[MAX_STRING_LENGTH];
  in_stream.getline(cur_line, MAX_STRING_LENGTH);

  // If this file doesn't work properly, return.
  if( !in_stream && !strlen(cur_line) )  return;

  in_stream.getline(cur_line, MAX_STRING_LENGTH);
  while ( in_stream ) {
    line_list.PushRear(cur_line);
    in_stream.getline(cur_line, MAX_STRING_LENGTH);
  }

  // Copy all of the lines into the line array.
  const int file_size = line_list.GetSize();
  line_array.Resize(file_size);

  for (int i = 0; i < file_size; i++) {
    line_array[i].line = line_list.Pop();
    line_array[i].line_num = i;
    line_array[i].used = false;
  }
}


void cInitFile::Save(const cString & in_filename)
{
  cString save_filename(GetFilename());
  if (in_filename != "") save_filename = in_filename;
  
  ofstream fp_save(save_filename());

  // Go through the lines saving them...
  for (int i = 0; i < line_array.GetSize(); i++) {
    fp_save << line_array[i].line << endl;
  }

  fp_save.close();
}


void cInitFile::ReadHeader()
{
  cString type_line = GetLine(0);
  cString format_line = GetLine(1);

  if (type_line.PopWord() == "#filetype") filetype = type_line.PopWord();
  if (format_line.PopWord() == "#format") file_format.Load(format_line);
}


void cInitFile::Compress()
{
  // We're going to handle this compression in multiple passes to make it
  // clean and easy.

  const int num_lines = line_array.GetSize();

  // PASS 1: Remove all comments -- everything after a '#' sign -- and
  // compress all whitespace into a single space.
  for (int i = 0; i < num_lines; i++) {
    cString & cur_line = line_array[i].line;

    // Remove all characters past a comment mark and reduce whitespace.
    int comment_pos = cur_line.Find('#');
    if (comment_pos >= 0) cur_line.Clip(comment_pos);
    cur_line.CompressWhitespace();
  }

  // PASS 2: Merge each line ending with a continue marker '\' with the
  // next line.

  int prev_line_id = -1;
  bool continued = false;
  for (int i = 0; i < num_lines; i++) {
    // If the current line is a continuation, append it to the previous line.
    if (continued == true) {
      line_array[prev_line_id].line += line_array[i].line;
      line_array[i].line = "";
    }
    else prev_line_id = i;

    // See if the prev_line is continued, and if it is, take care of it.
    cString & prev_line = line_array[prev_line_id].line;
    if (prev_line.GetSize() > 0 &&
	prev_line[prev_line.GetSize() - 1] == '\\') {
      prev_line.ClipEnd(1);  // Remove continuation mark.
      continued = true;
    }
    else continued = false;
  }

  // PASS 3: Remove now-empty lines.

  int next_id = 0;
  for (int i = 0; i < num_lines; i++) {
    // If we should keep this line, compact it.
    if (line_array[i].line.GetSize() > 0) {
      if (next_id != i) line_array[next_id] = line_array[i];
      next_id++;
    }
  }

  // Clip any extra lines at the end of the array.

  line_array.Resize(next_id);

  // Move the active line back to the beginning to avoid confusion.
  active_line = 0;
}


void cInitFile::AddLine(cString & in_string)
{
  extra_lines.Push(in_string);
}

cString cInitFile::GetLine(int line_num)
{
  if (line_num < 0 || line_num >= line_array.GetSize()) return "";
  return line_array[line_num].line;
}


bool cInitFile::Find(cString & in_string, const cString & keyword,
		     int col) const
{
  bool found = false;

  // Loop through all of the lines looking for this keyword.  Start with
  // the actual file...
  for (int line_id = 0; line_id < line_array.GetSize(); line_id++) {
    cString cur_string = line_array[line_id].line;

    // If we found the keyword, return it and stop.    
    if (cur_string.GetWord(col) == keyword) {
      line_array[line_id].used = true;
      in_string = cur_string;
      found = true;
    }
  }

  // Next, look through any extra lines appended to the file.
  cStringIterator list_it(extra_lines);
  while ( list_it.AtEnd() == false ) {
    list_it.Next();
    cString cur_string = list_it.Get();

    // If we found the keyword, return it and stop.
    if (cur_string.GetWord(col) == keyword) {
      in_string = cur_string;
      found = true;
    }
  }

  return found;    // Not Found...
}


cString cInitFile::ReadString(const cString & name, cString def) const
{
  // See if we definately can't find the keyword.
  if (name == "" || IsOpen() == false) return def;

  // Search for the keyword.
  cString cur_line;
  if (Find(cur_line, name, 0) == false) {
    if (verbose == true) {
      cerr << "Warning: " << name << " not in \"" << GetFilename()
	   << "\", defaulting to: " << def <<endl;
    }
    return def;
  }

  // Pop off the keyword, and return the remainder of the line.
  cur_line.PopWord();
  return cur_line;
}


bool cInitFile::WarnUnused() const
{
  bool found = false;

  for (int i = 0; i < line_array.GetSize(); i++) {
    if (line_array[i].used == false) {
      if (found == false) {
	found = true;
	cerr << "Warning unknown lines in input file '" << filename
	     << "':" << endl;
      }
      cerr << " " << line_array[i].line_num + 1
	   << ": " << line_array[i].line
	   << endl;
    }
  }

  return found;
}

Index: avida/current/source/tools/init_file.hh
+++ avida/current/source/tools/init_file.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef INIT_FILE_HH
#define INIT_FILE_HH

#include <istream>

#ifndef FILE_HH
#include "file.hh"
#endif
#ifndef STRING_HH
#include "string.hh"
#endif
#ifndef STRING_LIST_HH
#include "string_list.hh"
#endif
#ifndef TARRAY_HH
#include "tArray.hh"
#endif

/**
 * A class to handle initialization files.
 **/

class cString; // aggregate
class cStringList; // aggregate
template <class T> class tArray; // aggregate

class cInitFile : public cFile {
private:
  struct sFileLineInfo {
    cString line;
    int line_num;
    mutable bool used;
  };

  tArray<sFileLineInfo> line_array;
  cStringList extra_lines;
  cString filetype;
  cStringList file_format;

  int active_line;
public:
  /**
   * The empty constructor constructs an object that is in a clean
   * state. You can set the file to open with @ref cFile::Open() later on.
   **/
  cInitFile();
  
  /**
   * Opens the file with the given name.
   * 
   * @param in_filename Name of the initialization file to open.
   **/
  cInitFile(cString in_filename);
  
  ~cInitFile();
  
  /**
   * Loads the file into memory.
   **/
  void Load();
  
  /**
   * Loads a stream into memory rather than a file.
   **/
  void LoadStream(std::istream & in_steam);
  
  void Save(const cString & in_filename = "");
  
  /**
   * Parse heading information about the contents of the file loaded into
   * memory, if available.
   **/
  void ReadHeader();

  /**
   * Remove all comments and whitespace from a file loaded into memory.
   * Comments are currently marked with the character '#'.
   **/
  void Compress();
  
  /** 
   * Add a line to the beginning of the file in memory.
   * This function is used by @ref cGenesis.
   *
   * @param in_string The string to be added.
   **/
  void AddLine(cString & in_string);
  
  /**
   * Get a line from the file in memory. If called without parameters,
   * the first line of the file is returned.
   *
   * @param line_num The line count of the line to be returned 
   * (starting from 0).
   **/
  cString GetLine(int line_num=0);
  

  /**
   * Get the active line and advance to the next line.
   **/
  cString GetNextLine() { return GetLine(active_line++); }


  /**
   * Reset the active line to the beginning (or the point specified...
   **/
  void ResetLine(int new_pos=0) { active_line = new_pos; }

  /**
   * Returns the line number that is active.
   **/
  int GetLineNum() { return active_line; }

  /**
   * Checks whether any line contains a given keyword in the specified 
   * column. Stops when the first occurrence of the keyword is found.
   *
   * @return TRUE if keyword is found, FALSE otherwise.
   * @param in_string A string variable that will contain the found line
   * if search succeeds, and will have undefined contents otherwise.
   * @param keyword The keyword to look for.
   * @param col The column in which the keyword should be found.
   **/
  bool Find(cString & in_string, const cString & keyword, int col) const;
  
  /**
   * Reads an entry in the initialization file that has a given keyword
   * in the first column. The keyword is not part of the returned string.
   *
   * @return The entry that has been found.
   * @param name The keyword to look for (the name of the entry).
   * @param def If the keyword is not found, def is returned. This allows
   * one to set standard values that are used if the user does not override
   * them.
   **/
  cString ReadString(const cString & name, cString def = "") const;
  
  /**
   * Looks over all lines loaded into the file, and warns if any of them
   * have not been the targets of the Find() method.  All methods that
   * search the file for a keyword use find, so this can be used to locate
   * keywords that are not understood by the program.
   **/
  bool WarnUnused() const;

  /**
   * Return the number of lines in memory.
   **/
  int GetNumLines() const { return line_array.GetSize(); }

  const cString & GetFiletype() { return filetype; }
  cStringList & GetFormat() { return file_format; }
};

#endif

Index: avida/current/source/tools/int_sum.cc
+++ avida/current/source/tools/int_sum.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef INT_SUM_HH
#include "int_sum.hh"
#endif

// cIntSum ///////////////////////////////////////////////////////////////////

const double cIntSum::INF_ERR = 0;

Index: avida/current/source/tools/int_sum.hh
+++ avida/current/source/tools/int_sum.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef INT_SUM_HH
#define INT_SUM_HH

#include <math.h>
#include <limits.h>

class cIntSum {
private:
  long s1;  // Sum (x)
  long s2;  // Sum of squares (x^2)
  long s3;  // Sum of cubes (x^3)
  long s4;  // Sum of x^4
  long n;

public:
  static const double INF_ERR;  // Value Returned by StdError if Infinate

  cIntSum(){ Clear(); }

  void Clear(){ s1=0; s2=0; s3=0; s4=0; n=0; }

  long Count()        const { return n; }
  long N()            const { return n; }
  long Sum()          const { return s1; }
  long S1()           const { return s1; }
  long SumOfSquares() const { return s2; }
  long S2()           const { return s2; }
  long SumOfCubes()   const { return s3; }
  long S3()           const { return s3; }
  long S4()           const { return s4; }

  double Average() const { return ( n >1 ) ? ((double)s1/n) : 0; }

  double Variance() const { return ( n > 1 ) ?
      (s2 - s1*s1/(double)n) / (double)(n-1) : INF_ERR; }
    //n*(s2/n - s1/n*s1/n) / (n-1) : INF_ERR; }
  double StdDeviation() const { return sqrt(Variance()); }
  double StdError()  const { return (n > 1) ?
       sqrt(s2 / (double)(n * (n-1))) : INF_ERR; }

  double Skewness() const { return ( n > 2 ) ?
   (n*s3 - 3*s2*s1 + 2*s1*s1*s1/(double)n) / (double)((n-1)*(n-2)) : INF_ERR; }
     //n*n*(s3/n - 3*s2/n*s1/n + 2*s1/n*s1/n*s1/n)/((n-1)*(n-2)) : INF_ERR; }

  double Kurtosis() const { return ( n > 3 ) ?
     //n*n*(n+1)*(s4/n - 4*s3/n*s1/n + 6*s2/n*s1/n*s1/n -
     //3*s1/n*s1/n*s1/n*s1/n)/((n-1)*(n-2)*(n-3)) :
       (n+1)*(n*s4 - 4*s3*s1 + 6*s2*s1*s1/(double)n -
	      3*s1*s1*s1/(double)n*s1/(double)n) /
			      (double)((n-1)*(n-2)*(n-3)) :
    INF_ERR; }

  // Notation Shortcuts
  double Ave() const { return Average(); }
  double Var() const { return Variance(); }
  double Kur() const { return Kurtosis(); }
  double Skw() const { return Skewness(); }


  void Add(long value, long weight=1){
    long w_val = value * weight;
    n += weight;
    s1 += w_val;
    s2 += w_val * w_val;
    s3 += w_val * w_val * w_val;
    s4 += w_val * w_val * w_val * w_val;
  }

  void Subtract(long value, long weight=1){
    long w_val = value * weight;
    n -= weight;
    s1 -= w_val;
    s2 -= w_val * w_val;
    s3 -= w_val * w_val * w_val;
    s4 -= w_val * w_val * w_val * w_val;
  }
};

#endif

Index: avida/current/source/tools/integrated_schedule.cc
+++ avida/current/source/tools/integrated_schedule.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef INTEGRATED_SCHEDULE_HH
#include "integrated_schedule.hh"
#endif

#ifndef FUNCTIONS_HH
#include "functions.hh"
#endif
#ifndef INTEGRATED_SCHEDULE_NODE_HH
#include "integrated_schedule_node.hh"
#endif
#ifndef MERIT_HH
#include "merit.hh"
#endif

/////////////////////////
//  cIntegratedSchedule
/////////////////////////

cIntegratedSchedule::cIntegratedSchedule(int _item_count)
  : cSchedule(_item_count)
{
  num_active_nodes = 0;

  // Create the merit_chart; they should all init to default value.
  merit_chart = new cMerit[item_count];
  for (int i = 0; i < item_count; i++) {
    merit_chart[i] = 0;
  }
}

cIntegratedSchedule::~cIntegratedSchedule()
{
  for (int i = 0; i < node_array.GetSize(); i++) {
    if (node_array[i] != NULL) delete node_array[i];
  }
  delete [] merit_chart;
}

bool cIntegratedSchedule::OK()
{
  // Test that we have an acurate count of the number of active nodes.

  int test_active_nodes = 0;
  for (int i = 0; i < node_array.GetSize(); i++) {
    if (node_array[i]) test_active_nodes++;
  }

  assert(test_active_nodes == num_active_nodes); // active_node count mismatch.

  // Test each node to make sure it is OK.

  for (int i = 0; i < node_array.GetSize(); i++) {
    if (node_array[i] != NULL) node_array[i]->OK();
  }

  return true;
}


void cIntegratedSchedule::Adjust(int item_id, const cMerit & new_merit)
{
  // Grab the old_merit, the new merit, and compare them.
  const cMerit old_merit = merit_chart[item_id];

  // If the merit is still the same, we're done here.
  if (old_merit == new_merit) return;

  // Save the new merit to the merit_chart.
  merit_chart[item_id] = new_merit;

  // Re-adjust the lists.
  int merit_magnitude = Max( old_merit.GetNumBits(), new_merit.GetNumBits() );
  for (int i = 0; i < merit_magnitude; i++) {
    bool old_bit = old_merit.GetBit(i);
    bool new_bit = new_merit.GetBit(i);

    if (old_bit && !new_bit) {
      // Remove the item from this node...
      node_array[i]->Remove(item_id);
      if (node_array[i]->GetSize() == 0) RemoveNode(i);
    }

    if (!old_bit && new_bit) {
      // Add the item from this node...
      if (i >= node_array.GetSize() || !node_array[i]) InsertNode(i);
      node_array[i]->Insert(item_id);
    }
  }
}


int cIntegratedSchedule::GetNextID()
{
  assert(node_array.GetSize() > 0);  // Running scheduler w/ no entries!

  int next_id = -1;
  while (next_id < 0) {
    next_id = node_array[node_array.GetSize() - 1]->GetNextID();
  }
  
  return next_id;
}

double cIntegratedSchedule::GetStatus(int id)
{
  return merit_chart[id].GetDouble();
}


///////// --- private //////////

void cIntegratedSchedule::InsertNode(int node_id)
{
  // Test if trying to create node that already exists.
  assert(node_id >= node_array.GetSize() || node_array[node_id] == NULL);

  cIntegratedScheduleNode * new_node =
    new cIntegratedScheduleNode(item_count, node_id);

  if (node_id >= node_array.GetSize()) ResizeNodes(node_id);

  node_array[node_id] = new_node;

  // Find the node to mark as the 'prev'.
  for (int prev_id = node_id + 1; prev_id < node_array.GetSize(); prev_id++) {
    cIntegratedScheduleNode * prev_node = node_array[prev_id];
    if (prev_node) {
      new_node->SetPrev(prev_node);
      prev_node->SetNext(new_node);
      prev_node->SetProcessSize(1 << (prev_id - node_id - 1));
      break;
    }
  }

  // And find the node to mark as the 'next'.
  for (int next_id = node_id - 1; next_id >= 0; next_id--) {
    cIntegratedScheduleNode * next_node = node_array[next_id];
    if (next_node) {
      new_node->SetNext(next_node);
      next_node->SetPrev(new_node);
      new_node->SetProcessSize(1 << (node_id - next_id - 1));
      break;
    }
  }

  num_active_nodes++;
}

void cIntegratedSchedule::RemoveNode(int node_id)
{
  assert(node_array[node_id] != NULL); // Trying to remove non-existant node.

  cIntegratedScheduleNode * old_node = node_array[node_id];
  cIntegratedScheduleNode * next_node = old_node->GetNext();
  cIntegratedScheduleNode * prev_node = old_node->GetPrev();
  node_array[node_id] = NULL;

  if (next_node) next_node->SetPrev(prev_node);
  if (prev_node) {
    prev_node->SetNext(next_node);
    prev_node->SetProcessSize(old_node->GetProcessSize() *
			      prev_node->GetProcessSize() * 2);
  }

  if (node_id == node_array.GetSize() - 1) {
    if (!old_node->GetNext()) ResizeNodes(0);
    else ResizeNodes(old_node->GetNext()->GetID());
  }

  delete old_node;

  num_active_nodes--;
}

void cIntegratedSchedule::ResizeNodes(int new_max)
{
  int old_size = node_array.GetSize();
  int new_size = new_max + 1;  // 0 to new_max...

  // Clean up tail portions of the array being cut off.
  for (int i = new_size; i < old_size; i++) {
    if (node_array[i]) delete node_array[i];
  }

  node_array.Resize(new_size);

  // Mark as NULL any new cells added to the array.
  for (int i = old_size; i < new_size; i++) {
    node_array[i] = NULL;
  }
}

Index: avida/current/source/tools/integrated_schedule.hh
+++ avida/current/source/tools/integrated_schedule.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef INTEGRATED_SCHEDULE_HH
#define INTEGRATED_SCHEDULE_HH

#ifndef SCHEDULE_HH
#include "schedule.hh"
#endif
#ifndef TARRAY_HH
#include "tArray.hh"
#endif

/**
 * The cIntegratedSchedule method relies on breaking up all merits into
 * sums of powers of 2 (i.e. using the binary representation of the merit).
 * All items with merits in the highest power of two will get the most
 * time, and subsequent merit components will have time divided,
 * continuing recursively.  The simplest way of doing this while maximizing
 * evenness of distribution of time slices is to simply alternate executing
 * the best, and everything else (where in everything else we again alternate
 * with the best of this sub-list recursively).
 **/

class cIntegratedScheduleNode;
class cMerit;
template <class T> class tArray; // aggregate

class cIntegratedSchedule : public cSchedule {
private:
  tArray<cIntegratedScheduleNode *> node_array;
  int num_active_nodes;
  cMerit * merit_chart;

  void InsertNode(int node_id);
  void RemoveNode(int node_id);
  void ResizeNodes(int new_size);
public:
  cIntegratedSchedule(int _item_count);
  ~cIntegratedSchedule();

  void Adjust(int item_id, const cMerit & new_merit);
  int GetNextID();
  double GetStatus(int id);

  bool OK();
};

#endif

Index: avida/current/source/tools/integrated_schedule_node.cc
+++ avida/current/source/tools/integrated_schedule_node.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef INTEGRATED_SCHEDULE_NODE_HH
#include "integrated_schedule_node.hh"
#endif

/////////////////////////////
//  cIntegratedScheduleNode
/////////////////////////////

cIntegratedScheduleNode::cIntegratedScheduleNode(int _item_count, int in_id)
  : active_array(_item_count)
{
  // Store the input variables.

  node_id = in_id;

  // Initialize the remaining variables.

  for (int i = 0; i < active_array.GetSize(); i++) {
    active_array[i] = 0;
  }
  first_entry = -1;
  active_entry = -1;
  size = 0;
  process_size = 1;
  process_count = 0;
  execute = true;
  next = NULL;
  prev = NULL;
}

cIntegratedScheduleNode::~cIntegratedScheduleNode()
{
}


bool cIntegratedScheduleNode::OK()
{
  bool result = true;

  // Make sure the active_array is setup correctly.

  int size_check = 0;
  int next_check = first_entry;
  for (int i = 0; i < active_array.GetSize(); i++) {
    if (active_array[i] != 0) {
      size_check++;
      assert(next_check == i);  //  Node entries do no match!
      next_check = active_array[i];
    }
  }
  assert(next_check == -1);  // Node array not properly terminated.

  // Make sure the sizes line up...
  assert(size == size_check);  // size and active node count mismatch.

  return result;
}

void cIntegratedScheduleNode::Insert(int item_id)
{
  assert(item_id >= 0 && item_id < active_array.GetSize());  // Illegal ID

  // If this item is already active in this node, ignore this call...
  if (active_array[item_id] != 0) return;

  // See if we're dealing with a new first_entry...
  if (first_entry == -1 || item_id < first_entry) {
    active_array[item_id] = first_entry;
    first_entry = item_id;
  }
  else {
    // Otherwise find the predecessor to this item in the list...
    int prev_item;
    for (prev_item = item_id - 1; prev_item >= 0; prev_item--) {
      if (active_array[prev_item] != 0) break;
    }
    assert(prev_item >= 0);  // prev_item is first, but not identified.
    
    // Make the predecessor point to it, and have it point to the CPU that
    // the old predecessor pointed to.
    active_array[item_id] = active_array[prev_item];
    active_array[prev_item] = item_id;
  }

  size++;
}

void cIntegratedScheduleNode::Remove(int item_id)
{
  assert(item_id >= 0 && item_id < active_array.GetSize()); // Illegal ID

  // If this item is already inactive, ignore this call...
  if (active_array[item_id] == 0) return;

  // If this is the first_entry, adjust it!
  if (first_entry == item_id) {
    first_entry = active_array[item_id];
  }
  else {
    // Find the predecessor to this item in the list...
    int prev_item;
    for (prev_item = item_id - 1; prev_item >= 0; prev_item--) {
      if (active_array[prev_item] != 0) break;
    }
    assert(prev_item >= 0);  // prev_item is first, but not identified.

    // Make the predecessor point to the item removed used to point to.
    active_array[prev_item] = active_array[item_id];
  }

  active_array[item_id] = 0;
  size--;
}


// Execute everything on list, and then shift to calling the next node.
// Wait for the next node to return a -1 before shifting back to this one.

int cIntegratedScheduleNode::GetNextID()
{
  // Alternate between this node's Process and the next's.
  if (execute == false) {
    // If there is a next node, we may be working on it... 
    int next_id = -1;
    if (next != NULL) next_id = next->GetNextID();
   
    // If next_id is a -1, either we don't have a next node, or else it
    // is finished with its execution.

    if (next_id == -1) {
      execute = true;
      process_count = 0;
      active_entry = -1;
    }

    return next_id;
  }

  // Find the next active_entry...
  
  // If we were at the end of the list, start over...
  if (active_entry == -1) active_entry = first_entry;

  // If this entry no longer exists, hunt for the next active entry manually...
  else if (active_array[active_entry] == 0) {
    while (active_entry < active_array.GetSize() &&
	   active_array[active_entry] == 0) {
      active_entry++;
    }
    if (active_entry == active_array.GetSize()) active_entry = -1;
  }
  
  // Otherwise, if the entry does exist, we can just look the next one up.
  else active_entry = active_array[active_entry];


  // If we have now hit the end of this list, move on to the next node.

  if (active_entry == -1) {
    process_count++;
    if (process_count >= process_size) execute = false;
  }

//  cout << "Running " << active_entry << " from node " << node_id
//       << " (size = " << size << ", first = " << first_entry << ")" << endl;

  return active_entry;
}

Index: avida/current/source/tools/integrated_schedule_node.hh
+++ avida/current/source/tools/integrated_schedule_node.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef INTEGRATED_SCHEDULE_NODE_HH
#define INTEGRATED_SCHEDULE_NODE_HH

#ifndef TARRAY_HH
#include "tArray.hh"
#endif

/**
 * The cIntegratedScheduleNode object manages bundlings of item's for the
 * integrated time slicing object (cIntegratedSchedule).  When GetNextID()
 * is called on one of these nodes, it must either choose from itself, or
 * pass the call down to the nodes below it (by running the GetNextID()
 * method of the next node).  If the node alternates between everything in
 * its own list the next node's list, then we have a perfect Logrithmic
 * (base 2) decrease in activity.  Sometimes a merit will be skipped in the
 * list, so the next node should only be called one out of every four times,
 * etc.
 *
 * This allows binary representations of merits to determine which nodes
 * each item should be included in.
 **/

template <class T> class tArray; // aggregate

class cIntegratedScheduleNode {
private:
  tArray<int> active_array; // Each cell in this array corressponds to the
                      //  item with the same ID.  If creature is not in the
                      //  list, its value in the array will be 0. If it is in
                      //  the list, it will  point to the cell of the next
                      //  included creature.  The last included creature has
                      //  a -1 in its cell.
  int first_entry;    // ID of first active creature.
  int active_entry;   // ID of next scheduled entry.
  int node_id;        // A unique id (representing the relative merit bit).

  int size;           // Number of active items in this node.
  int process_size;   // Number of times this node should be executed before
                      //   the next node is.
  int process_count;  // Number of times this node has been executed.
  bool execute;       // Should this node execute or pass?

  cIntegratedScheduleNode * next;
  cIntegratedScheduleNode * prev;
public:
  cIntegratedScheduleNode(int _item_count = 0, int in_id = -1);
  ~cIntegratedScheduleNode();

  void Insert(int item_id);
  void Remove(int item_id);
  int GetNextID();

  bool OK();

  inline void SetProcessSize(int in_p_size) { process_size = in_p_size; }
  inline void SetNext(cIntegratedScheduleNode * in_next) { next = in_next; }
  inline void SetPrev(cIntegratedScheduleNode * in_prev) { prev = in_prev; }

  inline int GetID() { return node_id; }
  inline int GetSize() { return size; }
  inline int GetProcessSize() { return process_size; }
  inline int GetProcessCount() { return process_count; }
  inline cIntegratedScheduleNode * GetNext() { return next; }
  inline cIntegratedScheduleNode * GetPrev() { return prev; }
};

#endif

Index: avida/current/source/tools/message_class.hh
+++ avida/current/source/tools/message_class.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef MESSAGE_CLASS_HH
#define MESSAGE_CLASS_HH

class cMessageDisplay;
class cMessageType;

class cMessageClass{
public:
  cMessageClass(
    const char *class_name,
    cMessageDisplay **msg_display,
    bool is_fatal,
    bool is_prefix,
    bool no_prefix
  );
public:
  void configure(cMessageType *message_type);
public:
  const char *const m_class_name;
  cMessageDisplay **m_msg_display;
  bool const m_is_fatal;
  bool const m_is_prefix;
  bool const m_no_prefix;
private:
  bool _configured;
};

/*
Declaration of the five message classes.
*/
extern cMessageClass MCInfo;
extern cMessageClass MCDebug;
extern cMessageClass MCError;
extern cMessageClass MCFatal;
extern cMessageClass MCNoPrefix;

#endif

Index: avida/current/source/tools/message_closure.hh
+++ avida/current/source/tools/message_closure.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef MESSAGE_CLOSURE_HH
#define MESSAGE_CLOSURE_HH

#ifndef STRING_HH
#include "string.hh"
#endif

class cMessageType;
class cString; // aggregate
class QString;

class cMessageClosure{
private:
  cMessageType &_type;
  const char *_function;
  const char *_file;
  int _line;
  int _error;
  int _op_count;
  cString _msg;
public:
  cMessageClosure(
    cMessageType &type,
    const char *function_name,
    const char *file_name,
    int line_number
  );
  ~cMessageClosure(void);
public:
  /*
  operator<< and operator() definitions for cMessageClosure.

  Any kind of input can be placed behind the operator<<, really, but try
  to not (further) overcrowd the class...

  The operator is meant to convert its input into a string for display.
  If for example you implement
    cMessageClosure &operator<<(const myClass &instance);
  then you can write a message thus:
    DemoDebug << "this is a myClass instance: " << my_instance;
  with the result:
    "Debug [Demo] this is a myClass instance: stuff in my_instance."
  */
  cMessageClosure &operator<<(char c);
  cMessageClosure &operator<<(unsigned char c);
  cMessageClosure &operator<<(int i);
  cMessageClosure &operator<<(unsigned int i);
  cMessageClosure &operator<<(long i);
  cMessageClosure &operator<<(unsigned long i);
  cMessageClosure &operator<<(float f);
  cMessageClosure &operator<<(double f);
  cMessageClosure &operator<<(const void *p);
  cMessageClosure &operator<<(const char *s);
  cMessageClosure &operator<<(const QString &s);
  /*
  QString support is implemented outside of core of avida, in qt gui, so
  that QString can remain undefined in gui-less builds.  -- kgn
  */

  cMessageClosure &operator()(char c){ return operator<<(c); }
  cMessageClosure &operator()(unsigned char c){ return operator<<(c); }
  cMessageClosure &operator()(int i){ return operator<<(i); }
  cMessageClosure &operator()(unsigned int i){ return operator<<(i); }
  cMessageClosure &operator()(long i){ return operator<<(i); }
  cMessageClosure &operator()(unsigned long i){ return operator<<(i); }
  cMessageClosure &operator()(float f){ return operator<<(f); }
  cMessageClosure &operator()(double f){ return operator<<(f); }
  cMessageClosure &operator()(const void *p){ return operator<<(p); }
  cMessageClosure &operator()(const char *s){ return operator<<(s); }
  cMessageClosure &operator()(const QString &s){ return operator<<(s); }

  /*
  cMessageClosure::va():
  
  Support for cString-based operator<< and operator() definitions in
  cMessageClosure.  Variable argument lists are formatted and printed, a
  la printf, into a temporary buffer; the contents of this buffer are
  then appended to the cString _msg.
  */
  cMessageClosure &va(const char *fmt, ...);
private:
  void prefix(void);
};

/*
you probably don't need to change these macros...
*/

// window compatibility
#ifdef WIN32
# ifndef __PRETTY_FUNCTION__
#  define __PRETTY_FUNCTION__ "<unknown on win32>"
# endif
#endif

#define _MSG_CLOSURE_FL(x)\
  cMessageClosure(\
    x,\
    __PRETTY_FUNCTION__,\
    __FILE__,\
    __LINE__\
  )

#define _INFO_MSG(type)\
  if (Info_ ## type ## _Msg.m_is_active)\
    _MSG_CLOSURE_FL(Info_ ## type ## _Msg)

#define _DEBUG_MSG(type)\
  if (Debug_ ## type ## _Msg.m_is_active)\
    _MSG_CLOSURE_FL(Debug_ ## type ## _Msg)

#define _ERROR_MSG(type)\
  if (Error_ ## type ## _Msg.m_is_active)\
    _MSG_CLOSURE_FL(Error_ ## type ## _Msg)

#define _FATAL_MSG(type)\
  if (Fatal_ ## type ## _Msg.m_is_active)\
    _MSG_CLOSURE_FL(Fatal_ ## type ## _Msg)

#define _PLAIN_MSG(type)\
  if (type ## _Msg.m_is_active)\
    _MSG_CLOSURE_FL(type ## _Msg)

#endif

Index: avida/current/source/tools/message_type.hh
+++ avida/current/source/tools/message_type.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef MESSAGE_TYPE_HH
#define MESSAGE_TYPE_HH

class cMessageClass;

class cMessageType{
public:
  cMessageType(
    const char *type_name,
    cMessageClass &message_class
  );
public:
  const char *m_type_name;
  const cMessageClass &m_message_class;
  bool m_is_active;
};

#endif

Index: avida/current/source/tools/prob_schedule.cc
+++ avida/current/source/tools/prob_schedule.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef PROB_SCHEDULE_HH
#include "prob_schedule.hh"
#endif

#ifndef MERIT_HH
#include "merit.hh"
#endif
#ifndef TOOLS_HH
#include "tools.hh"
#endif

///////////////////
//  cProbSchedule
///////////////////

// The larger merits cause problems here; things need to be re-thought out.

cProbSchedule::cProbSchedule(int _item_count)
  : cSchedule(_item_count)
  , chart(_item_count)
{
}

cProbSchedule::~cProbSchedule()
{
}


int cProbSchedule::GetNextID()
{
  assert(chart.GetTotalWeight() > 0);
  const double position = g_random.GetDouble(chart.GetTotalWeight());
  return chart.FindPosition(position);
}

void cProbSchedule::Adjust(int item_id, const cMerit & item_merit)
{
  chart.SetWeight(item_id, item_merit.GetDouble());
}

Index: avida/current/source/tools/prob_schedule.hh
+++ avida/current/source/tools/prob_schedule.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef PROB_SCHEDULE_HH
#define PROB_SCHEDULE_HH

#ifndef SCHEDULE_HH
#include "schedule.hh"
#endif
#ifndef WEIGHTED_INDEX_HH
#include "weighted_index.hh"
#endif

/**
 * The Probiblistic Schedule has the chance for an item to
 * be scheduled proportional to the merit of that item.
 **/

class cWeightedIndex; // aggregate
class cMerit;

class cProbSchedule : public cSchedule {
private:
  cWeightedIndex chart;
public:
  cProbSchedule(int num_cells);
  ~cProbSchedule();

  void Adjust(int item_id, const cMerit & merit);
  int GetNextID();
};

#endif

Index: avida/current/source/tools/ref_block.cc
+++ avida/current/source/tools/ref_block.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef REF_BLOCK_HH
#include "ref_block.hh"
#endif

////////////////////
//  cRefBlock
////////////////////

cRefBlock::cRefBlock(int in_ref, int in_size)
{
  ref_num = in_ref;
  size = in_size;
}

cRefBlock::~cRefBlock()
{
  // nothing needed here...
}

Index: avida/current/source/tools/ref_block.hh
+++ avida/current/source/tools/ref_block.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef REF_BLOCK_HH
#define REF_BLOCK_HH

#ifndef FIXED_COORDS_HH
#include "fixed_coords.hh"
#endif

class cFixedCoords; // aggregate

class cRefBlock {
private:
  int ref_num;
  int size;
  cFixedCoords start_coords;
public:
  cRefBlock(int in_ref = 0, int in_size = 0);
  ~cRefBlock();

  inline int GetRef() const { return ref_num; }
  inline int GetSize() const { return size; }
  inline cFixedCoords GetStart() const { return start_coords; }

  inline void SetRef(int in_ref) { ref_num = in_ref; }
  inline void SetSize(int in_size) { size = in_size; }
  inline void SetStart(cFixedCoords &in_coords) { start_coords = in_coords; }
  inline void SetStart(int in_block, int in_offset) {
    start_coords(in_block, in_offset);
  }

  inline void operator=(const cRefBlock & in_block) {
    ref_num = in_block.GetRef();
    size = in_block.GetSize();
  }
};

#endif

Index: avida/current/source/tools/running_average.cc
+++ avida/current/source/tools/running_average.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef RUNNING_AVERAGE_HH
#include "running_average.hh"
#endif

#include <assert.h>

// cRunningAverage ////////////////////////////////////////////////////////////

cRunningAverage::cRunningAverage( int window_size ) : 
  m_values(0), m_s1(0), m_s2(0), m_window_size( window_size ),
  m_pointer(0), m_n(0) 
{
  assert( m_window_size > 1 );
  m_values = new double[ m_window_size ];
}


cRunningAverage::~cRunningAverage() {
  delete [] m_values;
}


void
cRunningAverage::Add( double value ) {
  m_s1 += value;
  m_s2 += value*value;
  if ( m_n < m_window_size ) {
    m_values[ m_n ] = value;
    m_n += 1;
  }
  else{
    double out_v = m_values[ m_pointer ];
    m_s1 -= out_v;
    m_s2 -= out_v * out_v;
    m_values[ m_pointer++ ] = value;
    if ( m_pointer == m_window_size ) m_pointer = 0;
  }
}


void
cRunningAverage::Clear() {
  m_s1 = 0;
  m_s2 = 0;
  m_pointer = 0;
  m_n = 0;
}

Index: avida/current/source/tools/running_average.hh
+++ avida/current/source/tools/running_average.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef RUNNING_AVERAGE_HH
#define RUNNING_AVERAGE_HH

#include <math.h>

class cRunningAverage {
private:
  double *m_values;  // Array of actual values
  double m_s1;       // average
  double m_s2;       // sum of squares
  int m_window_size;        // Size of sliding window
  int m_pointer;
  int m_n;
  
  
  cRunningAverage();
  cRunningAverage( const cRunningAverage & );
  cRunningAverage & operator=( const cRunningAverage & );
public:
  cRunningAverage( int window_size );
  ~cRunningAverage();
  
  
  //manipulators
  void Add( double value );
  void Clear();
  
  
  //accessors
  double Sum()          const { return m_s1; }
  double S1()           const { return m_s1; }
  double SumOfSquares() const { return m_s2; }
  double S2()           const { return m_s2; }
  
  double Average() const { return ( m_n == m_window_size ) ? (m_s1/m_n) : 0; }

  double Variance() const { return ( m_n == m_window_size ) ?
      (m_s2 - m_s1*m_s1/m_n) / (m_n-1) : 0; }
    
  double StdDeviation() const { return sqrt(Variance()); }
  double StdError()  const { return ( m_n == m_window_size ) ?
       sqrt(m_s2 - m_s1*m_s1/m_n / (m_n * (m_n-1))) : 0; }

  // Notation Shortcuts
  double Ave() const { return Average(); }
  double Var() const { return Variance(); }
};

#endif

Index: avida/current/source/tools/scaled_block.cc
+++ avida/current/source/tools/scaled_block.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2000 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef SCALED_BLOCK_HH
#include "scaled_block.hh"
#endif

////////////////////
//  cScaledBlock
////////////////////

cScaledBlock::cScaledBlock(void * in_data, int in_size)
{
  data = in_data;
  size = in_size;
}

cScaledBlock::~cScaledBlock()
{
}



Index: avida/current/source/tools/scaled_block.hh
+++ avida/current/source/tools/scaled_block.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef SCALED_BLOCK_HH
#define SCALED_BLOCK_HH

#ifndef FIXED_COORDS_HH
#include "fixed_coords.hh"
#endif

/**
 * Class used by @ref cBlockStruct.
 **/

class cFixedCoords; // aggregate

class cScaledBlock {
private:
  void * data;
  int size;
  cFixedCoords start_coords;
public:
  cScaledBlock(void * in_data = NULL, int in_size = 0);
  ~cScaledBlock();

  inline void * GetData() const { return data; }
  inline int GetSize() const { return size; }
  inline cFixedCoords GetStart() const { return start_coords; }

  inline void SetData(void * in_data) { data = in_data; }
  inline void SetSize(int in_size) { size = in_size; }
  inline void SetStart(const cFixedCoords &in_coords)
    { start_coords = in_coords; }
  inline void SetStart(int in_block, int in_offset) {
    start_coords(in_block, in_offset);
  }

  inline void operator=(const cScaledBlock & in_block) {
    data = in_block.GetData();
    size = in_block.GetSize();
  }
};

#endif

Index: avida/current/source/tools/schedule.cc
+++ avida/current/source/tools/schedule.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef SCHEDULE_HH
#include "schedule.hh"
#endif

////////////////
//  cSchedule
////////////////

cSchedule::cSchedule(int _item_count) : item_count(_item_count)
{
}

cSchedule::~cSchedule()
{
}

Index: avida/current/source/tools/schedule.hh
+++ avida/current/source/tools/schedule.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef SCHEDULE_HH
#define SCHEDULE_HH

/**
 * This class is the base object to handle time-slicing. All other schedulers
 * are derived from this class.  This is a pure virtual class.
 *
 **/

class cMerit;

class cSchedule {
protected:
  int item_count;
public:
  cSchedule(int _item_count);
  virtual ~cSchedule();

  virtual bool OK() { return true; }
  virtual void Adjust(int item_id, const cMerit & merit) { ; }
  virtual int GetNextID() = 0;
  virtual double GetStatus(int id) { return 0.0; }

  inline void SetSize(int _item_count)  { item_count = _item_count; }
};

#endif

Index: avida/current/source/tools/string_iterator.cc
+++ avida/current/source/tools/string_iterator.cc
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef STRING_ITERATOR_HH
#include "string_iterator.hh"
#endif

#ifndef STRING_HH
#include "string.hh"
#endif
#ifndef STRING_LIST_HH
#include "string_list.hh"
#endif

const cString cStringIterator::null_str("");

cStringIterator::cStringIterator(const cStringList & in_list)
  : list_it(in_list.GetList())
{
  Reset();
}

Index: avida/current/source/tools/string_iterator.hh
+++ avida/current/source/tools/string_iterator.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef STRING_ITERATOR_HH
#define STRING_ITERATOR_HH

#ifndef STRING_HH
#include "string.hh"
#endif
#ifndef TLIST_HH
#include "tList.hh"
#endif

class cString; // aggregate
class cStringList;
template <class T> class tConstListIterator; // aggregate

class cStringIterator {
private:
  tConstListIterator<cString> list_it;
  static const cString null_str;
public:
  cStringIterator(const cStringList & in_list);

  void Reset() { list_it.Reset(); }
  const cString & Get() {
    if (list_it.Get() == NULL) return null_str;
    return *(list_it.Get());
  }
  const cString & Next() { list_it.Next(); return Get(); }
  const cString & Prev() { list_it.Prev(); return Get(); }
  bool AtRoot() const { return list_it.AtRoot(); }
  bool AtEnd() const { return list_it.AtEnd(); }
};

#endif

Index: avida/current/source/tools/tArgDataEntry.hh
+++ avida/current/source/tools/tArgDataEntry.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////


#ifndef TARGDATAENTRY_HH
#define TARGDATAENTRY_HH

#include <iostream>

#ifndef TDATAENTRYBASE_HH
#include "tDataEntryBase.hh"
#endif

class cString;

template <class T, class OUT, class ARG> class tArgDataEntry
  : public tDataEntryBase<T> {
protected:
  OUT (T::*DataRetrieval)(ARG) const;
  int (T::*DataCompare)(T*,ARG) const;
  ARG arg;
public:
  tArgDataEntry(const cString & _name, const cString & _desc,
		OUT (T::*_funR)(ARG) const, ARG _arg,
		//int (T::*_funC)(T * _o, ARG _i) const = &T::CompareArgNULL,
		int (T::*_funC)(T * _o, ARG _i) const = 0,
		const cString & _null="0",
		const cString & _html_cell="align=center")
    : tDataEntryBase<T>(_name, _desc, _null, _html_cell),
      DataRetrieval(_funR), DataCompare(_funC), arg(_arg) { ; }

  bool Print(std::ostream & fp) const {
    if (target == NULL) return false;
    fp << (target->*DataRetrieval)(arg);
    return true;
  }

  //int Compare(T * other) const { return (target->*DataCompare)(other, arg); }
  int Compare(T * other) const {
    return (DataCompare)?((target->*DataCompare)(other, arg)):(0);
  }
};

#endif

Index: avida/current/source/tools/tDataEntry.hh
+++ avida/current/source/tools/tDataEntry.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef TDATAENTRY_HH
#define TDATAENTRY_HH

#include <iostream>

#ifndef STRING_HH
#include "string.hh"
#endif
#ifndef STRING_UTIL_HH
#include "string_util.hh"
#endif
#ifndef TDATAENTRYBASE_HH
#include "tDataEntryBase.hh"
#endif

class cString;
class cStringUtil; // access

template <class T, class OUT> class tDataEntry : public tDataEntryBase<T> {
protected:
  OUT  (T::*DataRetrieval)() const;
  void (T::*DataSet)(OUT);
  int  (T::*DataCompare)(T*) const;

  int CmpNULL(T *) const { return 0; }
public:
  tDataEntry(const cString & _name, const cString & _desc,
	     OUT (T::*_funR)() const,
	     void (T::*_funS)(OUT _val) = NULL,
	     //int (T::*_funC)(T * _o) const = &T::CompareNULL,
	     int (T::*_funC)(T * _o) const = 0,
	     const cString & _null="0",
	     const cString & _html_cell="align=center")
    : tDataEntryBase<T>(_name, _desc, _null, _html_cell), DataRetrieval(_funR),
      DataSet(_funS), DataCompare(_funC) { ; }

  bool Print(std::ostream & fp) const {
    if (target == NULL) return false;
    fp << (target->*DataRetrieval)();
    return true;
  }

  //int Compare(T * other) const { return (target->*DataCompare)(other); }
  int Compare(T * other) const {
    return (DataCompare)?((target->*DataCompare)(other)):(0);
  }
  bool Set(const cString & value) {
    OUT new_value(0);
    if (DataSet == 0) return false;
    (target->*DataSet)( cStringUtil::Convert(value, new_value) );
    return true;
  }
};

#endif

Index: avida/current/source/tools/tDataEntryBase.hh
+++ avida/current/source/tools/tDataEntryBase.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef TDATAENTRYBASE_HH
#define TDATAENTRYBASE_HH

#include <iostream>

#ifndef DATA_ENTRY_HH
#include "data_entry.hh"
#endif

class cString;

template <class T> class tDataEntryBase : public cDataEntry {
protected:
  T * target;
public:
  tDataEntryBase(const cString & _name, const cString & _desc,
		 const cString & _null="0",
		 const cString & _html_cell="align=center")
    : cDataEntry(_name, _desc, _null, _html_cell), target(NULL) { ; }
  
  void SetTarget(T * _target) { target = _target; }

  virtual bool Print(std::ostream & fp) const { (void) fp;  return false; }
  virtual int Compare(T * other) const { (void) other; return 0; }
  virtual bool Set(const cString & value) { (void) value; return false; }

  void HTMLPrint(std::ostream & fp, int compare=0, bool print_text=true) {
    fp << "<td " << GetHtmlCellFlags() << " ";
    if (compare == -2) {
      fp << "bgcolor=\"#FF0000\">";
      if (print_text == true) fp << GetNull() << " ";
      else fp << "&nbsp; ";
      return;
    }

    if (compare == -1)     fp << "bgcolor=\"#FFCCCC\">";
    else if (compare == 0) fp << ">";
    else if (compare == 1) fp << "bgcolor=\"#CCFFCC\">";
    else if (compare == 2) fp << "bgcolor=\"#00FF00\">";
    else {
      std::cerr << "Error! Illegal case in Compare:" << compare << std::endl;
      exit(0);
    }

    if (print_text == true) fp << *this << " ";
    else fp << "&nbsp; ";
  }
};

#endif

Index: avida/current/source/tools/tDataEntryCommand.hh
+++ avida/current/source/tools/tDataEntryCommand.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef TDATAENTRYCOMMAND_HH
#define TDATAENTRYCOMMAND_HH

#include <iostream>

#ifndef STRING_LIST_HH
#include "string_list.hh"
#endif
#ifndef TDATAENTRYBASE_HH
#include "tDataEntryBase.hh"
#endif

class cString;
class cStringList; // aggregate
template <class T> class tDataEntryBase; // access

template <class T> class tDataEntryCommand {
private:
  tDataEntryBase<T> * data_entry;
  cStringList args;
public:
  tDataEntryCommand(tDataEntryBase<T> * _entry, const cString & _args="")
    : data_entry(_entry), args(_args, ':') { ; }
  
  tDataEntryBase<T> & GetEntry() { return *data_entry; }
  const cStringList & GetArgs() const { return args; }
  bool HasArg(const cString & test_arg) { return args.HasString(test_arg); }

  const cString & GetName() const { return data_entry->GetName(); }
  const cString & GetDesc() const { return data_entry->GetDesc(); }
  const cString & GetNull() const { return data_entry->GetNull(); }
  const cString & GetHtmlCellFlags() const
    { return data_entry->GetHtmlCellFlags(); }

  void SetTarget(T * _target) { data_entry->SetTarget(_target); }
  bool Print(std::ostream & fp) const { return data_entry->Print(fp); }
  int Compare(T * other) const { return data_entry->Compare(other); }
  bool SetValue(const cString & value) { return data_entry->Set(value); }
  void HTMLPrint(std::ostream & fp, int compare=0, bool print_text=true)
    { data_entry->HTMLPrint(fp, compare, print_text); }
};

#endif

Index: avida/current/source/tools/tDataManager.hh
+++ avida/current/source/tools/tDataManager.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef TDATAMANAGER_HH
#define TDATAMANAGER_HH

#include <iostream>

#ifndef DATA_MANAGER_BASE_HH
#include "data_manager_base.hh"
#endif
#ifndef TDATAENTRYBASE_HH
#include "tDataEntryBase.hh"
#endif
#ifndef TDICTIONARY_HH
#include "tDictionary.hh"
#endif

// This template manages a collection of keywords and associates each with
// an accessor for a specific object.  When a list of keywords is then
// fed in with an output file, the associated data for that object will
// then be printed to the output file.

class cString;
template <class T, class U> class tDataEntry;
template <class T> class tDataEntryBase; // access
template <class T> class tDictionary; // aggregate

template <class T> class tDataManager : public cDataManager_Base {
private:
  T * target;
  tDictionary< tDataEntryBase<T> * > entry_dict;
public:
  tDataManager(T * _target, const cString & in_filetype="unknown")
    : cDataManager_Base(in_filetype), target(_target) { ; }
  ~tDataManager() { ; }

  template<class OUT> bool Add(const cString & name,  const cString & desc,
			       OUT (T::*_funR)() const,
			       void (T::*_funS)(OUT _val) = NULL,
			       int (T::*_funC)(T * _o) const = NULL,
			       const cString & null="0",
			       const cString & html_cell="align=center") {
    tDataEntryBase<T> * new_entry =
     new tDataEntry<T, OUT> (name, desc, _funR, _funS, _funC, null, html_cell);
    new_entry->SetTarget(target);
    entry_dict.Add(name, new_entry);
    return true;
  }

  bool Print(const cString & name, std::ostream & fp) {
    tDataEntryBase<T> * cur_entry = NULL;
    if (entry_dict.Find(name, cur_entry) == false) return false;
    cur_entry->Print(fp);
    return true;
  }

  bool GetDesc(const cString & name, cString & out_desc) {
    tDataEntryBase<T> * cur_entry = NULL;
    if (entry_dict.Find(name, cur_entry) == false) return false;
    out_desc = cur_entry->GetDesc();
    return true;
  }
};

#endif

Index: avida/current/source/tools/uint.hh
+++ avida/current/source/tools/uint.hh
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993 - 2003 California Institute of Technology             //
//                                                                          //
// Read the COPYING and README files, or contact 'avida at alife.org',         //
// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
//////////////////////////////////////////////////////////////////////////////

#ifndef UINT_HH
#define UINT_HH

#include <stdio.h>

#ifndef UCHAR
#define UCHAR unsigned char
#endif

// Should this just use a long?  For testing only...
#define LONG_C_UINT

#ifdef LONG_C_UINT
class cUInt {
private:
  long value;
  int size;
public:
  inline cUInt() { size = 0; value = 0; }
  inline cUInt(int in_size) { size = in_size, value = 0; }
  inline cUInt(int in_size, int in_value) { size = in_size, value = in_value; }
  inline ~cUInt() {;}

  inline void Print() const { printf ("%ld", value); }
  inline int AsInt() const { return (int) value; }
  inline long AsLong() const { return value; }

  inline void ShiftLeft(int num_bytes = 1) { value = value << (8 * num_bytes);}
  inline void ShiftRight(int num_bytes = 1){ value = value >> (8 * num_bytes);}

  inline cUInt& operator=(const UCHAR in_char) {
    value = (long) in_char;
    return *this;
  }
  inline cUInt& operator=(const int in_int) {
    value = (long) in_int;
    return *this;
  }
  inline cUInt&  operator=(const cUInt& in_cUInt) {
    value = in_cUInt.AsLong();
    return *this;
  }

  inline cUInt& operator*=(const UCHAR in_char){
    value *= (long) in_char;
    return *this;
  }

  inline cUInt& operator+=(const int in_int) {
    value += (long) in_int;
    return *this;
  }

  inline cUInt& operator-=(const int in_int) {
    value -= in_int;
    return *this;
  }

  inline cUInt& operator*=(const int in_int) {
    value *= in_int;
    return *this;
  }

  inline cUInt& operator/=(const int in_int) {
    value /= in_int;
    return *this;
  }

  inline cUInt& operator%=(const int in_int) {
    value %= in_int;
    return *this;
  }


  inline cUInt& operator+=(const cUInt& in_cUInt) {
    value += in_cUInt.AsLong();
    return *this;
  }

  inline cUInt& operator-=(const cUInt& in_cUInt) {
    value -= in_cUInt.AsLong();
    return *this;
  }

  inline cUInt& operator*=(const cUInt& in_cUInt) {
    value *= in_cUInt.AsLong();
    return *this;
  }

  inline cUInt& operator/=(const cUInt& in_cUInt) {
    value /= in_cUInt.AsLong();
    return *this;
  }

  inline cUInt& operator%=(const cUInt& in_cUInt) {
    value %= in_cUInt.AsLong();
    return *this;
  }


  inline cUInt& operator+(const int in_int) {
    cUInt * temp = new cUInt;
    *temp = *this;
    *temp += in_int;
    return *temp;
  }
  inline cUInt& operator-(const int in_int) {
    cUInt * temp = new cUInt;
    *temp = *this;
    *temp -= in_int;
    return *temp;
  }
  inline cUInt& operator*(const int in_int) {
    cUInt * temp = new cUInt;
    *temp = *this;
    *temp *= in_int;
    return *temp;
  }
  inline cUInt& operator/(const int in_int) {
    cUInt * temp = new cUInt;
    *temp = *this;
    *temp /= in_int;
    return *temp;
  }
  inline cUInt& operator%(const int in_int) {
    cUInt * temp = new cUInt;
    *temp = *this;
    *temp %= in_int;
    return *temp;
  }

  inline cUInt& operator+(const cUInt& in_cUInt) {
    cUInt * temp = new cUInt;
    *temp = *this;
    *temp += in_cUInt;
    return *temp;
  }
  inline cUInt& operator-(const cUInt& in_cUInt) {
    cUInt * temp = new cUInt;
    *temp = *this;
    *temp -= in_cUInt;
    return *temp;
  }
  inline cUInt& operator*(const cUInt& in_cUInt) {
    cUInt * temp = new cUInt;
    *temp = *this;
    *temp *= in_cUInt;
    return *temp;
  }
  inline cUInt& operator/(const cUInt& in_cUInt) {
    cUInt * temp = new cUInt;
    *temp = *this;
    *temp /= in_cUInt;
    return *temp;
  }
  inline cUInt& operator%(const cUInt& in_cUInt) {
    cUInt * temp = new cUInt;
    *temp = *this;
    *temp %= in_cUInt;
    return *temp;
  }

  inline int operator==(const cUInt& in_cUInt) const {
    return (value == in_cUInt.AsLong());
  }

  inline int operator<(const cUInt& in_cUInt) const {
    return (value < in_cUInt.AsLong());
  }

  inline int operator<=(const cUInt& in_cUInt) const {
    return (value <= in_cUInt.AsLong());
  }

  inline int operator>(const cUInt& in_cUInt) const {
    return (value > in_cUInt.AsLong());
  }

  inline int operator>=(const cUInt& in_cUInt) const {
    return (value >= in_cUInt.AsLong());
  }

};
#endif


#ifndef LONG_C_UINT

/**
 * This class constructs an arbitrary (pre-set) large integer.  Not all of the
 * possible operators have been added yet; they will be as they are needed.
 **/

class cUInt {
private:
  UCHAR * value;
  int size;

public:
  inline cUInt();
  inline cUInt(int in_size);
  inline cUInt(int in_size, int in_value);
  inline ~cUInt();

  inline void Resize(int new_size);
  inline void PrintBytes() const;
  inline void Print(cUInt * input_thing = NULL) const;
  inline int AsInt() const;
  inline long AsLong() const; //Do not use!! Assumes 8 byte longs... for tests.

  inline int GetSize() const { return size; }
  inline int GetSizeUsed() const;
  inline UCHAR GetByte(int byte_num) const { return value[byte_num]; }
  inline void SetByte(int byte_num, UCHAR in_char) {value[byte_num] = in_char;}

  inline void ShiftLeft(int num_bytes = 1);
  inline void ShiftRight(int num_bytes = 1);

  inline cUInt& operator=(const UCHAR in_char);
  inline cUInt& operator=(const int in_int);
  inline cUInt& operator=(const cUInt& in_cUInt);

  inline cUInt& operator*=(const UCHAR in_char);

  inline cUInt& operator+=(const int in_int);
  inline cUInt& operator-=(const int in_int);
  inline cUInt& operator*=(const int in_int);
  inline cUInt& operator/=(const int in_int);
  inline cUInt& operator%=(const int in_int);

  inline cUInt& operator+=(const cUInt& in_cUInt);
  inline cUInt& operator-=(const cUInt& in_cUInt);
  inline cUInt& operator*=(const cUInt& in_cUInt);
  inline cUInt& operator/=(const cUInt& in_cUInt);
  inline cUInt& operator%=(const cUInt& in_cUInt);

  inline int operator==(const cUInt& in_cUInt) const;
  inline int operator<( const cUInt& in_cUInt) const;
  inline int operator<=(const cUInt& in_cUInt) const;
  inline int operator>( const cUInt& in_cUInt) const;
  inline int operator>=(const cUInt& in_cUInt) const;

  inline cUInt& operator+(const int in_int) {
    cUInt * temp = new cUInt;
    *temp = *this;
    *temp += in_int;
    return *temp;
  }
  inline cUInt& operator-(const int in_int) {
    cUInt * temp = new cUInt;
    *temp = *this;
    *temp -= in_int;
    return *temp;
  }
  inline cUInt& operator*(const int in_int) {
    cUInt * temp = new cUInt;
    *temp = *this;
    *temp *= in_int;
    return *temp;
  }
  inline cUInt& operator/(const int in_int) {
    cUInt * temp = new cUInt;
    *temp = *this;
    *temp /= in_int;
    return *temp;
  }
  inline cUInt& operator%(const int in_int) {
    cUInt * temp = new cUInt;
    *temp = *this;
    *temp %= in_int;
    return *temp;
  }

  inline cUInt& operator+(const cUInt& in_cUInt) {
    cUInt * temp = new cUInt;
    *temp = *this;
    *temp += in_cUInt;
    return *temp;
  }
  inline cUInt& operator-(const cUInt& in_cUInt) {
    cUInt * temp = new cUInt;
    *temp = *this;
    *temp -= in_cUInt;
    return *temp;
  }
  inline cUInt& operator*(const cUInt& in_cUInt) {
    cUInt * temp = new cUInt;
    *temp = *this;
    *temp *= in_cUInt;
    return *temp;
  }
  inline cUInt& operator/(const cUInt& in_cUInt) {
    cUInt * temp = new cUInt;
    *temp = *this;
    *temp /= in_cUInt;
    return *temp;
  }
  inline cUInt& operator%(const cUInt& in_cUInt) {
    cUInt * temp = new cUInt;
    *temp = *this;
    *temp %= in_cUInt;
    return *temp;
  }
};

inline cUInt::cUInt()
{
  int i;
  size = 10;
  value = new UCHAR[size];
  for (i = 0; i < size; i++) {
    value[i] = 0;
  }
}

inline cUInt::cUInt(int in_size)
{
  int i;

  size = in_size;
  value = new UCHAR[size];
  for (i = 0; i < size; i++) {
    value[i] = 0;
  }
}

inline cUInt::cUInt(int in_size, int in_value)
{
  int i;

  size = in_size;
  value = new UCHAR[size];
  for (i = 0; i < size && i < 4; i++) {
    value[i] = (UCHAR) (in_value >> (8 * i));
  }
  while (i < size) {
    value[i++] = 0;
  }
}

inline cUInt::~cUInt()
{
  delete value;
}

inline void cUInt::Resize(int new_size)
{
  UCHAR * new_value = new UCHAR[new_size];

  int i;
  for (i = 0; i < new_size && i < size; i++) {
    new_value[i] = value[i];
  }
  while (i < new_size) {
    new_value[i++] = 0;
  }

  delete value;
  size = new_size;
  value = new_value;
}

inline void cUInt::PrintBytes() const
{
  int i;

  for (i = 0; i < GetSizeUsed(); i++) {
    printf("[%d] ", (int) value[i]);
  }
}

// This is *very* poorly written currently!
inline void cUInt::Print(cUInt * input_thing) const
{
  if (!input_thing) {
    cUInt * input_thing2;
    input_thing2 = new cUInt(size);
    *input_thing2 = *this;
    Print(input_thing2);
  }
  else if (input_thing->GetSizeUsed()) {
    cUInt this_num(size);
    this_num = *input_thing;
    this_num %= 10;

    *input_thing /= 10;
    Print(input_thing);
    printf("%01d", this_num.AsInt());
  }
}

inline int cUInt::AsInt() const
{
  int i, ret_value = 0;

  for (i = 3; i >= 0; i--) {
    ret_value = ret_value << 8;
    ret_value += value[i];
  }

  return ret_value;
}

inline long cUInt::AsLong() const
{
  int i;
  long ret_value = 0;

  for (i = 7; i >= 0; i--) {
    ret_value = ret_value << 8;
    ret_value += value[i];
  }

  return ret_value;
}

inline int cUInt::GetSizeUsed() const
{
  int size_used = size, i;
  for (i = size - 1; i >= 0 && !value[i]; i--) size_used--;
  return size_used;
}

inline void cUInt::ShiftLeft(int num_bytes)
{
  int i;

  // Starting at the end, copy down all the applicable bytes.

  for (i = size - 1; i >= num_bytes; i--) {
    value[i] = value[i - num_bytes];
  }

  // Now fill in all of the 'new' bytes with 0's.

  for (i = num_bytes - 1; i >= 0; i--) {
    value[i] = 0;
  }
}

inline void cUInt::ShiftRight(int num_bytes)
{
  int i;

  // Shift over the numbers...

  for (i = 0; i < size - num_bytes; i++) {
    value[i] = value[i + num_bytes];
  }

  // And fill in 0's where applicable.

  for (i = size - num_bytes; i < size; i++) {
    value[i] = 0;
  }
}

inline cUInt& cUInt::operator=(const UCHAR in_char)
{
  int i;
  value[0] = in_char;
  for (i = 1; i < size; i++) {
    value[i] = 0;
  }

  return *this;
}

inline cUInt& cUInt::operator=(const int in_int)
{
  int i;
  for (i = 0; i < 4 && i < size; i++) {
    value[i] = (UCHAR) (in_int >> (8*i));
  }
  for (i = 4; i < size; i++) {
    value[i] = 0;
  }

  return *this;
}

inline cUInt& cUInt::operator=(const cUInt& in_cUInt)
{
  int i;
  int size2 = in_cUInt.GetSize();

  for (i = 0; i < size && i < size2; i++) {
    value[i] = in_cUInt.GetByte(i);
  }
  for (i = size2; i < size; i++) {
    value[i] = 0;
  }

  return *this;
}

inline cUInt& cUInt::operator*=(const UCHAR in_char)
{
  int this_byte = 0, carry = 0;
  int i;

  for (i = 0; i < size; i++) {
    this_byte = (int) value[i] * (int) in_char + carry;
    value[i] = this_byte & 255;
    carry = this_byte >> 8;
  }

  return *this;
}

inline cUInt& cUInt::operator+=(const int in_int)
{
  cUInt add_int(4, in_int);
  operator+=(add_int);

  return *this;
}

inline cUInt& cUInt::operator-=(const int in_int)
{
  cUInt sub_int(4, in_int);
  operator-=(sub_int);

  return *this;
}

inline cUInt& cUInt::operator*=(const int in_int)
{
  cUInt mult_int(4, in_int);
  operator*=(mult_int);

  return *this;
}

inline cUInt& cUInt::operator/=(const int in_int)
{
  cUInt div_int(4, in_int);
  operator/=(div_int);

  return *this;
}

inline cUInt& cUInt::operator%=(const int in_int)
{
  cUInt mod_int(4, in_int);
  operator%=(mod_int);

  return *this;
}

inline cUInt& cUInt::operator+=(const cUInt& in_cUInt)
{
  int i;
  int cur_sum = 0;

  // Add up sums byte by byte, carrying any remainders.

  for (i = 0; i < size && i < in_cUInt.GetSize(); i++) {
    cur_sum += value[i];
    cur_sum += in_cUInt.GetByte(i);
    value[i] = (UCHAR) (cur_sum & 255);
    cur_sum = cur_sum >> 8;
  }

  // If there is still a remainder, and room for it, continue.

  while (cur_sum && i < size) {
    value[i++] = (UCHAR) (cur_sum & 255);
  }

  return *this;
}

inline cUInt& cUInt::operator-=(const cUInt& in_cUInt)
{
  int i;
  int next_byte = 0, byte1, byte2;

  for (i = 0; i < size && i < in_cUInt.GetSize(); i++) {
    byte1 = (int) value[i];
    byte2 = (int) in_cUInt.GetByte(i);
    if (byte1 + next_byte >= byte2) {
      value[i] = (UCHAR) (byte1 + next_byte - byte2);
      next_byte = 0;
    }
    else {
      value[i] = (UCHAR) (256 + byte1 + next_byte - byte2);
      next_byte = -1;
    }
  }

  // Check to see if there are any more effects of the carry...

  for (i = in_cUInt.GetSize(); i < size && next_byte < 0; i++) {
    if (value[i] + next_byte >= 0) {
      value[i] += next_byte;
      next_byte = 0;
    }
    else {
      value[i] = (UCHAR) (256 + next_byte + (int) value[i]);
      next_byte = -1;
    }
  }

  return *this;
}

inline cUInt& cUInt::operator*=(const cUInt& in_cUInt)
{
  cUInt sum_cUInt(size), temp_cUInt(size);
  int i;

  for (i = in_cUInt.GetSize() - 1; i >= 0; i--) {
    temp_cUInt = *this;
    temp_cUInt *= in_cUInt.GetByte(i);
    sum_cUInt.ShiftLeft();
    sum_cUInt += temp_cUInt;
  }

  operator=(sum_cUInt);

  return *this;
}

inline cUInt& cUInt::operator/=(const cUInt& in_cUInt)
{
  // Guess the approximate size of the result, and start from there.

  cUInt result(size + 2);  // @CAO FIX THIS

  // Now, loops through filling in one byte of the result at a time.

  int cur_byte, cur_bit;
  for (cur_byte = GetSizeUsed() - in_cUInt.GetSizeUsed(); cur_byte >= 0; cur_byte--) {
    for (cur_bit = 7; cur_bit >= 0; cur_bit--) {
      cUInt cur_test(result.GetSize(), 1 << cur_bit);
      cur_test.ShiftLeft(cur_byte);
      cur_test += result;

      if (*this >= (cur_test * in_cUInt)) result = cur_test;
    }
  }

  operator=(result);

  return *this;
}

inline cUInt& cUInt::operator%=(const cUInt& in_cUInt)
{
  cUInt multiple(size);

  multiple = *this;
  multiple /= in_cUInt;
  multiple *= in_cUInt;
  *this -= multiple;

  return *this;
}

/* int operator==(int in_int)
{
  cUInt temp_int(4, in_int);
  return operator==(temp_int);
}

int operator<(int in_int)
{
  cUInt temp_int(4, in_int);
  return operator<(temp_int);
}

int operator<=(int in_int)
{
  cUInt temp_int(4, in_int);
  return operator<=(temp_int);
}

int operator>(int in_int)
{
  cUInt temp_int(4, in_int);
  return operator>(temp_int);
}

int operator>=(int in_int)
{
  cUInt temp_int(4, in_int);
  return operator>=(temp_int);
}
*/

inline bool cUInt::operator==(const cUInt& in_cUInt) const
{
  int i;

  // Make sure all of the overlaped bytes are identical.

  for (i = 0; i < size && i < in_cUInt.GetSize(); i++) {
    if (value[i] != in_cUInt.GetByte(i)) return false;
  }

  // Make sure all of the bytes one contains beyond the other are 0.

  for (i = in_cUInt.GetSize(); i < size; i++) {
    if (value[i]) return false;
  }
  for (i = size; i < in_cUInt.GetSize(); i++) {
    if (in_cUInt.GetByte(i)) return false;
  }

  return true;
}

inline bool cUInt::operator<(const cUInt& in_cUInt) const
{
  // First check the extra digits to see if they effect things...

  for (int i = size; i < in_cUInt.GetSize(); i++) {
    if (in_cUInt.GetByte(i)) return true;
  }
  for (int i = in_cUInt.GetSize(); i < size; i++) {
    if (value[i]) return false;
  }

  // Now loop through the matching digits until there is a difference

  int match_size = size;
  if (size > in_cUInt.GetSize()) match_size = in_cUInt.GetSize();

  for (int i = match_size - 1; i >= 0; i--) {
    if (value[i] > in_cUInt.GetByte(i)) return false;
    if (value[i] < in_cUInt.GetByte(i)) return true;
  }

  // And if they are equal...

  return false;
}

inline bool cUInt::operator<=(const cUInt& in_cUInt) const
{
  // First check the extra digits to see if they effect things...

  for (int i = size; i < in_cUInt.GetSize(); i++) {
    if (in_cUInt.GetByte(i)) return true;
  }
  for (int i = in_cUInt.GetSize(); i < size; i++) {
    if (value[i]) return false;
  }

  // Now loop through the matching digits until there is a difference

  int match_size = size;
  if (size > in_cUInt.GetSize()) match_size = in_cUInt.GetSize();

  for (int i = match_size - 1; i >= 0; i--) {
    if (value[i] > in_cUInt.GetByte(i)) return false;
    if (value[i] < in_cUInt.GetByte(i)) return true;
  }

  // And if they are equal...

  return true;
}

inline bool cUInt::operator>(const cUInt& in_cUInt) const
{
  return !operator<=(in_cUInt);
}

inline cUInt::operator>=(const cUInt& in_cUInt) const
{
  return !operator<(in_cUInt);
}

#endif

#endif


More information about the Avida-cvs mailing list