[avida-cvs] avida(Sherri) CVS commits: /current/source/cpu hardware_4stack.cc hardware_4stack.hh hardware_cpu.cc hardware_cpu.hh hardware_util.cc hardware_util.hh /current/source/main analyze.cc config.cc config.hh inst_set.cc mutations.cc mutations.hh /current/source/tools file.cc file.hh string_list.hh tList.hh

goingssh avida-cvs at alife.org
Tue May 27 19:45:42 PDT 2003


goingssh		Tue May 27 11:45:42 2003 EDT

  Modified files:              (Branch: Sherri)
    /avida/current/source/cpu	hardware_4stack.cc hardware_4stack.hh 
                             	hardware_cpu.cc hardware_cpu.hh 
                             	hardware_util.cc hardware_util.hh 
    /avida/current/source/main	analyze.cc config.cc config.hh 
                              	inst_set.cc mutations.cc mutations.hh 
    /avida/current/source/tools	file.cc file.hh string_list.hh tList.hh 
  Log:
  commiting merge of head and my branch back to my branch (Sherri)
  
-------------- next part --------------
Index: avida/current/source/cpu/hardware_4stack.cc
diff -u avida/current/source/cpu/hardware_4stack.cc:1.2.4.1 avida/current/source/cpu/hardware_4stack.cc:1.2.4.2
--- avida/current/source/cpu/hardware_4stack.cc:1.2.4.1	Fri May 23 12:05:36 2003
+++ avida/current/source/cpu/hardware_4stack.cc	Tue May 27 11:45:36 2003
@@ -263,8 +263,7 @@
     cInstEntry4Stack("nop-B",     &cHardware4Stack::Inst_Nop),
     cInstEntry4Stack("nop-C",     &cHardware4Stack::Inst_Nop),
 
-    // Added "map-null" for use in analyze mode. -- kgn
-    cInstEntry4Stack("map-null",  &cHardware4Stack::Inst_Nop),
+    cInstEntry4Stack("NULL",  &cHardware4Stack::Inst_Nop),
     cInstEntry4Stack("nop-X",     &cHardware4Stack::Inst_Nop),
     cInstEntry4Stack("if-equ-0",  &cHardware4Stack::Inst_If0),
     cInstEntry4Stack("if-not-0",  &cHardware4Stack::Inst_IfNot0),
Index: avida/current/source/cpu/hardware_4stack.hh
diff -u avida/current/source/cpu/hardware_4stack.hh:1.2 avida/current/source/cpu/hardware_4stack.hh:1.2.4.1
--- avida/current/source/cpu/hardware_4stack.hh:1.2	Mon May 19 12:30:06 2003
+++ avida/current/source/cpu/hardware_4stack.hh	Tue May 27 11:45:36 2003
@@ -107,6 +107,8 @@
   ~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);
Index: avida/current/source/cpu/hardware_cpu.cc
diff -u avida/current/source/cpu/hardware_cpu.cc:1.45.2.1 avida/current/source/cpu/hardware_cpu.cc:1.45.2.2
--- avida/current/source/cpu/hardware_cpu.cc:1.45.2.1	Fri May 23 12:05:36 2003
+++ avida/current/source/cpu/hardware_cpu.cc	Tue May 27 11:45:36 2003
@@ -241,9 +241,10 @@
 cInstLibCPU *cHardwareCPU::s_inst_slib = cHardwareCPU::initInstLib();
 cInstLibCPU *cHardwareCPU::initInstLib(void){
   struct cNOPEntryCPU {
-    cNOPEntryCPU(const cString &name, int nop_mod):name(name), nop_mod(nop_mod){}
     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),
@@ -251,10 +252,15 @@
     cNOPEntryCPU("nop-C", REG_CX)
   };
 
-  struct cInstEntryCPU {
-    cInstEntryCPU(const cString &name, tHardwareCPUMethod function):name(name), function(function){}
-    cString name;
-    tHardwareCPUMethod function;
+  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[] = {
     /*
@@ -262,30 +268,39 @@
     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),
-    cInstEntryCPU("nop-B",     &cHardwareCPU::Inst_Nop),
-    cInstEntryCPU("nop-C",     &cHardwareCPU::Inst_Nop),
-
-    // Added "map-null" for use in analyze mode. -- kgn
-    cInstEntryCPU("map-null",     &cHardwareCPU::Inst_Nop),
-    cInstEntryCPU("nop-X",     &cHardwareCPU::Inst_Nop),
-    cInstEntryCPU("if-equ-0",  &cHardwareCPU::Inst_If0),
-    cInstEntryCPU("if-not-0",  &cHardwareCPU::Inst_IfNot0),
-    cInstEntryCPU("if-n-equ",  &cHardwareCPU::Inst_IfNEqu),
-    cInstEntryCPU("if-equ",    &cHardwareCPU::Inst_IfEqu),
+    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),
+    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),
@@ -293,11 +308,15 @@
     cInstEntryCPU("call",      &cHardwareCPU::Inst_Call),
     cInstEntryCPU("return",    &cHardwareCPU::Inst_Return),
 
-    cInstEntryCPU("pop",       &cHardwareCPU::Inst_Pop),
-    cInstEntryCPU("push",      &cHardwareCPU::Inst_Push),
-    cInstEntryCPU("swap-stk",  &cHardwareCPU::Inst_SwitchStack),
+    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),
+    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),
@@ -317,25 +336,35 @@
     cInstEntryCPU("push-B",    &cHardwareCPU::Inst_PushB),
     cInstEntryCPU("push-C",    &cHardwareCPU::Inst_PushC),
 
-    cInstEntryCPU("shift-r",   &cHardwareCPU::Inst_ShiftR),
-    cInstEntryCPU("shift-l",   &cHardwareCPU::Inst_ShiftL),
+    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),
-    cInstEntryCPU("dec",       &cHardwareCPU::Inst_Dec),
-    cInstEntryCPU("zero",      &cHardwareCPU::Inst_Zero),
+    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),
-    cInstEntryCPU("sub",       &cHardwareCPU::Inst_Sub),
-    cInstEntryCPU("mult",      &cHardwareCPU::Inst_Mult),
-    cInstEntryCPU("div",       &cHardwareCPU::Inst_Div),
+    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),
+    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),
@@ -359,7 +388,8 @@
     cInstEntryCPU("stk-get",   &cHardwareCPU::Inst_TaskStackGet),
     cInstEntryCPU("stk-load",  &cHardwareCPU::Inst_TaskStackLoad),
     cInstEntryCPU("put",       &cHardwareCPU::Inst_TaskPut),
-    cInstEntryCPU("IO",        &cHardwareCPU::Inst_TaskIO),
+    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),
@@ -376,21 +406,30 @@
     cInstEntryCPU("id-th",     &cHardwareCPU::Inst_ThreadID),
 
     // Head-based instructions
-    cInstEntryCPU("h-alloc",   &cHardwareCPU::Inst_MaxAlloc),
-    cInstEntryCPU("h-divide",  &cHardwareCPU::Inst_HeadDivide),
+    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),
-    cInstEntryCPU("h-search",  &cHardwareCPU::Inst_HeadSearch),
+    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),
-    cInstEntryCPU("jmp-head",  &cHardwareCPU::Inst_JumpHead),
-    cInstEntryCPU("get-head",  &cHardwareCPU::Inst_GetHead),
-    cInstEntryCPU("if-label",  &cHardwareCPU::Inst_IfLabel),
-    cInstEntryCPU("set-flow",  &cHardwareCPU::Inst_SetFlow),
+    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),
@@ -2217,8 +2256,8 @@
 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_AX)); return true;}
-bool cHardwareCPU::Inst_PushC() { 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;}
Index: avida/current/source/cpu/hardware_cpu.hh
diff -u avida/current/source/cpu/hardware_cpu.hh:1.28 avida/current/source/cpu/hardware_cpu.hh:1.28.2.1
--- avida/current/source/cpu/hardware_cpu.hh:1.28	Sun May 18 21:15:22 2003
+++ avida/current/source/cpu/hardware_cpu.hh	Tue May 27 11:45:37 2003
@@ -107,6 +107,8 @@
   ~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);
Index: avida/current/source/cpu/hardware_util.cc
diff -u avida/current/source/cpu/hardware_util.cc:1.23.2.1 avida/current/source/cpu/hardware_util.cc:1.23.2.2
--- avida/current/source/cpu/hardware_util.cc:1.23.2.1	Fri May 23 12:05:36 2003
+++ avida/current/source/cpu/hardware_util.cc	Tue May 27 11:45:37 2003
@@ -23,17 +23,54 @@
 
 
 #ifdef USE_INST_SET_CODE
-void cHardwareUtil::LoadInstSet(const cString & filename, cInstSet & inst_set, 
+void cHardwareUtil::LoadInstSet(cString filename, cInstSet & inst_set, 
 				tDictionary<int> & nop_dict,
 				tDictionary<int> & inst_dict
 ){
 #else /* USE_INST_SET_CODE */
-void cHardwareUtil::LoadInstSet(const cString & filename, cInstSet & inst_set, 
+void cHardwareUtil::LoadInstSet(cString & filename, cInstSet & inst_set, 
 				tDictionary<int> & nop_dict,
 				tDictionary<tHardwareMethod> & inst_dict
 ){
 #endif /* USE_INST_SET_CODE */
+  // 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();
 
Index: avida/current/source/cpu/hardware_util.hh
diff -u avida/current/source/cpu/hardware_util.hh:1.6.2.1 avida/current/source/cpu/hardware_util.hh:1.6.2.2
--- avida/current/source/cpu/hardware_util.hh:1.6.2.1	Fri May 23 12:05:36 2003
+++ avida/current/source/cpu/hardware_util.hh	Tue May 27 11:45:37 2003
@@ -20,19 +20,11 @@
 class cHardwareUtil {
 public:
 #ifdef USE_INST_SET_CODE
-  static void LoadInstSet(
-    const cString & filename,
-    cInstSet & inst_set, 
-		tDictionary<int> & nop_dict,
-		tDictionary<int> & inst_dict
-  );
+  static void LoadInstSet( cString filename, cInstSet & inst_set, 
+	tDictionary<int> & nop_dict, tDictionary<int> & inst_dict );
 #else /* USE_INST_SET_CODE */
-  static void LoadInstSet(
-    const cString & filename,
-    cInstSet & inst_set, 
-		tDictionary<int> & nop_dict,
-		tDictionary<tHardwareMethod> & inst_dict
-  );
+  static void LoadInstSet( cString filename, cInstSet & inst_set, 
+	tDictionary<int> & nop_dict, tDictionary<tHardwareMethod> & inst_dict);
 #endif /* USE_INST_SET_CODE */
   static void LoadInstSet_CPUOriginal(const cString & filename,
 				      cInstSet & inst_set);
Index: avida/current/source/main/analyze.cc
diff -u avida/current/source/main/analyze.cc:1.70.2.1 avida/current/source/main/analyze.cc:1.70.2.2
--- avida/current/source/main/analyze.cc:1.70.2.1	Fri May 23 12:05:37 2003
+++ avida/current/source/main/analyze.cc	Tue May 27 11:45:38 2003
@@ -1808,13 +1808,13 @@
     cInstSet map_inst_set(inst_set);
 #ifdef USE_INST_SET_CODE
     /* XXX start -- kgn */
-    // Locate instruction corresponding to "map-null" in the instruction library.
+    // Locate instruction corresponding to "NULL" in the instruction library.
     {
-      const cInstruction inst_lib_null_inst = map_inst_set.GetInstLib()->GetInst("map-null");
+      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 \"map-null\" isn't in the instruction library;" << endl;
-        cout << " --- get somebody to map a function to \"map-null\" in the library." << 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;
@@ -1823,12 +1823,12 @@
       // Add mapping to located instruction. 
       map_inst_set.Add2(inst_lib_null_inst.GetOp());
     }
-    const cInstruction null_inst = map_inst_set.GetInst("map-null");
+    const cInstruction null_inst = map_inst_set.GetInst("NULL");
     /* XXX end */
 #else /* USE_INST_SET_CODE */
     // Build an empty instruction into the instruction set.
-    map_inst_set.Add("map-null", &cHardwareBase::Inst_Nop);
-    const cInstruction null_inst = map_inst_set.GetInst("map-null");
+    map_inst_set.Add("NULL", &cHardwareBase::Inst_Nop);
+    const cInstruction null_inst = map_inst_set.GetInst("NULL");
 #endif /* USE_INST_SET_CODE */
 
     // Loop through all the lines of code, testing the removal of each.
@@ -2018,13 +2018,13 @@
     cInstSet map_inst_set(inst_set);
 #ifdef USE_INST_SET_CODE
     /* XXX start -- kgn */
-    // Locate instruction corresponding to "map-null" in the instruction library.
+    // Locate instruction corresponding to "NULL" in the instruction library.
     {
-      const cInstruction inst_lib_null_inst = map_inst_set.GetInstLib()->GetInst("map-null");
-      if(inst_lib_null_inst == map_inst_set.GetInstLib()->GetInstError()){
+      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 \"map-null\" isn't in the instruction library;" << endl;
-        cout << " --- get somebody to map a function to \"map-null\" in the library." << 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;
@@ -2033,12 +2033,12 @@
       // Add mapping to located instruction. 
       map_inst_set.Add2(inst_lib_null_inst.GetOp());
     }
-    const cInstruction null_inst = map_inst_set.GetInst("map-null");
+    const cInstruction null_inst = map_inst_set.GetInst("NULL");
     /* XXX end */
 #else /* USE_INST_SET_CODE */
     // Build an empty instruction into the instruction set.
-    map_inst_set.Add("map-null", &cHardwareBase::Inst_Nop);
-    const cInstruction null_inst = map_inst_set.GetInst("map-null");
+    map_inst_set.Add("NULL", &cHardwareBase::Inst_Nop);
+    const cInstruction null_inst = map_inst_set.GetInst("NULL");
 #endif /* USE_INST_SET_CODE */
 
     cString color_string;  // For coloring cells...
Index: avida/current/source/main/config.cc
diff -u avida/current/source/main/config.cc:1.55 avida/current/source/main/config.cc:1.55.2.1
--- avida/current/source/main/config.cc:1.55	Tue May 20 07:42:28 2003
+++ avida/current/source/main/config.cc	Tue May 27 11:45:39 2003
@@ -16,7 +16,7 @@
 
 using namespace std;
 
-
+tList<cConfig::cConfigGroup> cConfig::group_list;
 bool cConfig::analyze_mode;
 bool cConfig::primitive_mode;
 cString cConfig::default_dir;
@@ -43,9 +43,6 @@
 double cConfig::divide_ins_prob;
 double cConfig::divide_del_prob;
 double cConfig::parent_mut_prob;
-double cConfig::crossover_prob;
-double cConfig::aligned_cross_prob;
-double cConfig::exe_err_prob;
 int cConfig::num_instructions;
 int cConfig::hardware_type;
 int cConfig::max_cpu_threads;
@@ -54,7 +51,6 @@
 int cConfig::base_size_merit;
 int cConfig::task_merit_method;
 int cConfig::max_label_exe_size;
-int cConfig::max_num_tasks_rewarded;
 int cConfig::merit_time;
 int cConfig::num_tasks;
 int cConfig::num_reactions;
@@ -93,139 +89,260 @@
 int cConfig::test_cpu_time_mod;
 int cConfig::track_main_lineage;
 bool cConfig::log_threshold_only;
-bool cConfig::log_breed_count;
 bool cConfig::log_creatures;
-bool cConfig::log_phylogeny;
 bool cConfig::log_genotypes;
 bool cConfig::log_threshold;
 bool cConfig::log_species;
 bool cConfig::log_landscape;
-bool cConfig::log_mutations;
 bool cConfig::log_lineages;
 int cConfig::debug_level;
 int cConfig::view_mode;
-int cConfig::viewer_type;
 
 
 
 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(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\n    (after the divide, we have 2 children)");
+  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");
+
+  
+  // 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",
+		  "0 = One thread executed per time slice.\n1 = All threads executed each time slice.");
+  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.
+   ***/
 
-  // Load the default directory...
-  default_dir = genesis.ReadString("DEFAULT_DIR", DEFAULT_DIR);
+  // The default directory should end in a '/'.
   char dir_tail = default_dir[default_dir.GetSize() - 1];
   if (dir_tail != '\\' && dir_tail != '/') default_dir += "/";
 
-  // Input files...
-  inst_filename  = genesis.ReadString("INST_SET", "inst_set");
-  event_filename = genesis.ReadString("EVENT_FILE", "events.cfg");
-  analyze_filename = genesis.ReadString("ANALYZE_FILE", "analyze.cfg");
-  env_filename = genesis.ReadString("ENVIRONMENT_FILE", "environment.cfg");
-  start_creature = genesis.ReadString("START_CREATURE");
-
-
-  // Load Archetecture...
-  max_updates     = genesis.ReadInt("MAX_UPDATES", -1);
-  max_generations = genesis.ReadInt("MAX_GENERATIONS", -1);
-  end_condition_mode = genesis.ReadInt("END_CONDITION_MODE", 0);
-  world_x         = genesis.ReadInt("WORLD-X");
-  world_y         = genesis.ReadInt("WORLD-Y");
-  hardware_type   = genesis.ReadInt("HARDWARE_TYPE");
-
-  birth_method   = genesis.ReadInt("BIRTH_METHOD", POSITION_CHILD_AGE);
-  death_method   = genesis.ReadInt("DEATH_METHOD", DEATH_METHOD_OFF);
-  alloc_method   = genesis.ReadInt("ALLOC_METHOD", ALLOC_METHOD_DEFAULT);
-  divide_method  = genesis.ReadInt("DIVIDE_METHOD", DIVIDE_METHOD_SPLIT);
-  required_task   = genesis.ReadInt("REQUIRED_TASK", -1);
-  lineage_creation_method =
-    genesis.ReadInt("LINEAGE_CREATION_METHOD", 0);
-  generation_inc_method =
-    genesis.ReadInt("GENERATION_INC_METHOD", GENERATION_INC_BOTH);
-  age_limit      = genesis.ReadInt("AGE_LIMIT", -1);
-  age_deviation    = genesis.ReadFloat("AGE_DEVIATION", 0);
-  child_size_range = genesis.ReadFloat("CHILD_SIZE_RANGE", 2.0);
-  min_copied_lines = genesis.ReadFloat("MIN_COPIED_LINES", 0.5);
-  min_exe_lines    = genesis.ReadFloat("MIN_EXE_LINES", 0.5);
-  require_allocate = genesis.ReadInt("REQUIRE_ALLOCATE", 1);
-
-  revert_fatal = genesis.ReadFloat("REVERT_FATAL", 0.0);
-  revert_neg   = genesis.ReadFloat("REVERT_DETRIMENTAL", 0.0);
-  revert_neut  = genesis.ReadFloat("REVERT_NEUTRAL", 0.0);
-  revert_pos   = genesis.ReadFloat("REVERT_BENEFICIAL", 0.0);
-  sterilize_fatal = genesis.ReadFloat("STERILIZE_FATAL", 0.0);
-  sterilize_neg   = genesis.ReadFloat("STERILIZE_DETRIMENTAL", 0.0);
-  sterilize_neut  = genesis.ReadFloat("STERILIZE_NEUTRAL", 0.0);
-  sterilize_pos   = genesis.ReadFloat("STERILIZE_BENEFICIAL", 0.0);
+  // Determine if any variables were set that require test CPUs to be run
+  // at every divide.
   test_on_divide = (revert_fatal > 0.0) || (revert_neg > 0.0) ||
     (revert_neut > 0.0) || (revert_pos > 0.0) || (sterilize_fatal > 0.0) ||
     (sterilize_neg > 0.0) || (sterilize_neut > 0.0) || (sterilize_pos > 0.0);
-  fail_implicit = genesis.ReadInt("FAIL_IMPLICIT", 0);
-
-  // Genealogy
-  species_threshold  = genesis.ReadInt("SPECIES_THRESHOLD");
-  threshold          = genesis.ReadInt("THRESHOLD");
-  genotype_print     = genesis.ReadInt("GENOTYPE_PRINT");
-  species_print      = genesis.ReadInt("SPECIES_PRINT");
-  species_recording  = genesis.ReadInt("SPECIES_RECORDING");
-  genotype_print_dom = genesis.ReadInt("GENOTYPE_PRINT_DOM");
-  test_cpu_time_mod  = genesis.ReadInt("TEST_CPU_TIME_MOD", 20);
-  track_main_lineage = genesis.ReadInt("TRACK_MAIN_LINEAGE", 0);
-
-  // Thread Info
-  max_cpu_threads = genesis.ReadInt("MAX_CPU_THREADS", 1);
-  thread_slicing_method = genesis.ReadInt("THREAD_SLICING_METHOD", 0);
-  
-
-  // Time Slicing Info
-  slicing_method = genesis.ReadInt("SLICING_METHOD", SLICE_CONSTANT);
-  size_merit_method = genesis.ReadInt("SIZE_MERIT_METHOD", 0);
-  base_size_merit   = genesis.ReadInt("BASE_SIZE_MERIT", 0);
-  ave_time_slice = genesis.ReadInt("AVE_TIME_SLICE", 30);
-  merit_time = genesis.ReadInt("MERIT_TIME", 0);
-
-  // Task Merit Method
-  task_merit_method = genesis.ReadInt("TASK_MERIT_METHOD", TASK_MERIT_NORMAL);
-  max_num_tasks_rewarded = genesis.ReadInt("MAX_NUM_TASKS_REWARDED", -1);
-  max_label_exe_size = genesis.ReadInt("MAX_LABEL_EXE_SIZE", 1);
-
-  // Load Mutation Info
-  point_mut_prob  = genesis.ReadFloat("POINT_MUT_PROB");
-  copy_mut_prob   = genesis.ReadFloat("COPY_MUT_PROB");
-  ins_mut_prob    = genesis.ReadFloat("INS_MUT_PROB");
-  del_mut_prob    = genesis.ReadFloat("DEL_MUT_PROB");
-  div_mut_prob    = genesis.ReadFloat("DIV_MUT_PROB");
-  divide_mut_prob = genesis.ReadFloat("DIVIDE_MUT_PROB");
-  divide_ins_prob = genesis.ReadFloat("DIVIDE_INS_PROB");
-  divide_del_prob = genesis.ReadFloat("DIVIDE_DEL_PROB");
-  parent_mut_prob = genesis.ReadFloat("PARENT_MUT_PROB");
-  crossover_prob  = genesis.ReadFloat("CROSSOVER_PROB");
-  aligned_cross_prob = genesis.ReadFloat("ALIGNED_CROSS_PROB");
-  exe_err_prob    = genesis.ReadFloat("EXE_ERROR_PROB");
-
-  // Load Viewer Info...
-  view_mode = genesis.ReadInt("VIEW_MODE");
-  viewer_type = genesis.ReadInt("VIEWER_TYPE",0);
-
-  log_breed_count = genesis.ReadInt("LOG_BREED_COUNT", 0);
-  log_creatures   = genesis.ReadInt("LOG_CREATURES", 0);
-  log_phylogeny   = genesis.ReadInt("LOG_PHYLOGENY", 0);
 
-  log_genotypes = genesis.ReadInt("LOG_GENOTYPES", 0);
+  // Determine if we are only logging threshold genotypes...
   log_threshold_only = false;
   if (log_genotypes > 1) log_threshold_only = true;
 
-  log_threshold = genesis.ReadInt("LOG_THRESHOLD", 0);
-  log_species   = genesis.ReadInt("LOG_SPECIES", 0);
-  log_landscape = genesis.ReadInt("LOG_LANDSCAPE", 0);
-  log_mutations = genesis.ReadInt("LOG_MUTATIONS", 0);
-  log_lineages = genesis.ReadInt("LOG_LINEAGES", 0);
-
+  // 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()
@@ -251,6 +368,71 @@
 #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)
 //  {
@@ -274,7 +456,9 @@
 
 void cConfig::ProcessConfiguration(int argc, char * argv[], cGenesis & genesis)
 {
-  genesis_filename = "genesis"; // Name of genesis file.
+  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.
@@ -299,6 +483,16 @@
   // 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
@@ -390,16 +584,6 @@
       cString value(cur_arg);
       cout << "SET " << name() << " = " << value() << endl;
       genesis.AddInput(name(), value());
-    } else if (cur_arg == "-viewer") {
-      if (arg_num + 1 == argc || args[arg_num + 1][0] == '-') {
-	cerr<<"Must include viewer type"<<endl;
-	exit(0);
-      } else {
-	arg_num++;  if (arg_num < argc) cur_arg = args[arg_num];
-	viewer_type = cur_arg.AsInt();
-      }
-      genesis.AddInput("VIEWER_TYPE", viewer_type);
-
 
     } else if (cur_arg == "-g" || cur_arg == "-genesis") {
       cerr << "Error: -g[enesis] option must be listed first." << endl;
Index: avida/current/source/main/config.hh
diff -u avida/current/source/main/config.hh:1.48 avida/current/source/main/config.hh:1.48.2.1
--- avida/current/source/main/config.hh:1.48	Tue May 20 07:42:28 2003
+++ avida/current/source/main/config.hh	Tue May 27 11:45:40 2003
@@ -57,6 +57,90 @@
 
 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') { ; }
+
+    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 tConfigEntry<int>(_var,_def,_tag,_desc));
+    }
+
+    void Add(double & _var, const cString & _def, const cString & _tag,
+	     const cString & _desc)
+    {
+      group_entries.PushRear(new tConfigEntry<double>(_var,_def,_tag,_desc));
+    }
+
+    void Add(cString & _var, const cString & _def, const cString & _tag,
+	     const cString & _desc)
+    {
+      group_entries.PushRear(new tConfigEntry<cString>(_var,_def,_tag,_desc));
+    }
+
+    void Add(bool & _var, const cString & _def, const cString & _tag,
+	     const cString & _desc)
+    {
+      group_entries.PushRear(new 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?
@@ -92,9 +176,6 @@
   static double divide_ins_prob;
   static double divide_del_prob;
   static double parent_mut_prob;
-  static double crossover_prob;
-  static double aligned_cross_prob;
-  static double exe_err_prob;
 
   // CPU Configutation
   static int num_instructions;
@@ -114,7 +195,6 @@
 
   // Task Merit Method
   static int task_merit_method;
-  static int max_num_tasks_rewarded;
 
   static int merit_time;
 
@@ -160,9 +240,7 @@
   // Log files...
   static bool log_threshold_only;
 
-  static bool log_breed_count;
   static bool log_creatures;
-  static bool log_phylogeny;
   static bool log_genotypes;
   static bool log_threshold;
   static bool log_species;
@@ -175,13 +253,13 @@
 
   // Viewer
   static int view_mode;
-  static int viewer_type;
 
   // 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; }
@@ -221,9 +299,6 @@
   static double GetDivideInsProb() { return divide_ins_prob; }
   static double GetDivideDelProb() { return divide_del_prob; }
   static double GetParentMutProb() { return parent_mut_prob; }
-  static double GetCrossoverProb() { return crossover_prob; }
-  static double GetAlignedCrossProb() { return aligned_cross_prob; }
-  static double GetExeErrProb()    { return exe_err_prob; }
 
   static int GetNumInstructions() { return num_instructions; }
   static int GetHardwareType() { return hardware_type; }
@@ -233,7 +308,6 @@
   static int GetSizeMeritMethod() { return size_merit_method; }
   static int GetBaseSizeMerit()  { return base_size_merit; }
   static int GetTaskMeritMethod() { return task_merit_method; }
-  static int GetMaxNumTasksRewarded() { return max_num_tasks_rewarded; }
   static int GetMaxLabelExeSize() { return max_label_exe_size; }
 
   static int GetMeritTime() { return merit_time; }
@@ -282,20 +356,16 @@
 
   static bool GetLogThresholdOnly()  { return log_threshold_only; }
 
-  static bool GetLogBreedCount() { return log_breed_count; }
   static bool GetLogCreatures() { return log_creatures; }
-  static bool GetLogPhylogeny() { return log_phylogeny; }
   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 GetLogMutations() { return log_mutations; }
   static bool GetLogLineages()  { return log_lineages; }
 
   static int GetDebugLevel() { return debug_level; }
 
   static int GetViewMode() { return view_mode; }
-  static int GetViewerType() { return viewer_type; }
 
 
   // ``Set''
Index: avida/current/source/main/inst_set.cc
diff -u avida/current/source/main/inst_set.cc:1.1.4.1 avida/current/source/main/inst_set.cc:1.1.4.2
--- avida/current/source/main/inst_set.cc:1.1.4.1	Fri May 23 12:05:37 2003
+++ avida/current/source/main/inst_set.cc	Tue May 27 11:45:41 2003
@@ -34,7 +34,8 @@
 
 #ifdef USE_INST_SET_CODE
 cInstSet::cInstSet(const cInstSet & in_inst_set)
-  : m_lib_name_map(in_inst_set.m_lib_name_map)
+  : 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)
 {
Index: avida/current/source/main/mutations.cc
diff -u avida/current/source/main/mutations.cc:1.7 avida/current/source/main/mutations.cc:1.7.2.1
--- avida/current/source/main/mutations.cc:1.7	Sat May 17 02:48:09 2003
+++ avida/current/source/main/mutations.cc	Tue May 27 11:45:41 2003
@@ -119,7 +119,6 @@
 void cMutationRates::Clear()
 {
   exec.point_mut_prob = 0.0;
-  exec.exe_err_prob = 0.0;
   copy.copy_mut_prob = 0.0;
   divide.ins_mut_prob = 0.0;
   divide.del_mut_prob = 0.0;
@@ -135,7 +134,6 @@
 void cMutationRates::Copy(const cMutationRates & in_muts)
 {
   exec.point_mut_prob = in_muts.exec.point_mut_prob;
-  exec.exe_err_prob = in_muts.exec.exe_err_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;
@@ -153,11 +151,6 @@
 bool cMutationRates::TestPointMut() const
 {
   return g_random.P(exec.point_mut_prob);
-}
-
-bool cMutationRates::TestExeErr() const
-{
-  return g_random.P(exec.exe_err_prob);
 }
 
 bool cMutationRates::TestCopyMut() const
Index: avida/current/source/main/mutations.hh
diff -u avida/current/source/main/mutations.hh:1.7 avida/current/source/main/mutations.hh:1.7.2.1
--- avida/current/source/main/mutations.hh:1.7	Sat May 17 12:33:53 2003
+++ avida/current/source/main/mutations.hh	Tue May 27 11:45:41 2003
@@ -102,7 +102,6 @@
   // ...anytime during execution...
   struct sExecMuts {
     double point_mut_prob;
-    double exe_err_prob;
   };
   sExecMuts exec;
 
@@ -137,7 +136,6 @@
   void Copy(const cMutationRates & in_muts);
 
   bool TestPointMut() const;
-  bool TestExeErr() const;
   bool TestCopyMut() const;
   bool TestDivideMut() const;
   bool TestDivideIns() const;
@@ -147,7 +145,6 @@
   bool TestAlignedCrossover() const;
 
   double GetPointMutProb() const     { return exec.point_mut_prob; }
-  double GetExeErrProb() const       { return exec.exe_err_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; }
@@ -160,7 +157,6 @@
   double GetAlignedCrossProb() const { return divide.aligned_cross_prob; }
 
   void SetPointMutProb(double in_prob)  { exec.point_mut_prob  = in_prob; }
-  void SetExeErrProb(double in_prob)    { exec.exe_err_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; }
Index: avida/current/source/tools/file.cc
diff -u avida/current/source/tools/file.cc:1.19 avida/current/source/tools/file.cc:1.19.2.1
--- avida/current/source/tools/file.cc:1.19	Mon May 19 21:07:33 2003
+++ avida/current/source/tools/file.cc	Tue May 27 11:45:41 2003
@@ -387,6 +387,9 @@
   }
 
   int base_ret = cFile::Open(_filename, mode);
+  
+  if (IsOpen() == false) return base_ret;  // Failed to open!
+
   Load();
   Compress();
   Close();
Index: avida/current/source/tools/file.hh
diff -u avida/current/source/tools/file.hh:1.17 avida/current/source/tools/file.hh:1.17.2.1
--- avida/current/source/tools/file.hh:1.17	Mon May 19 21:07:33 2003
+++ avida/current/source/tools/file.hh	Tue May 27 11:45:41 2003
@@ -278,7 +278,23 @@
      * @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;
+     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/string_list.hh
diff -u avida/current/source/tools/string_list.hh:1.3 avida/current/source/tools/string_list.hh:1.3.4.1
--- avida/current/source/tools/string_list.hh:1.3	Thu Feb 14 07:57:41 2002
+++ avida/current/source/tools/string_list.hh	Tue May 27 11:45:41 2003
@@ -42,7 +42,7 @@
   cStringList & operator=(const cStringList & _list);
 
   int GetSize() const { return string_list.GetSize(); }
-  cString GetLine(int line_num) { return *(string_list.GetPos(line_num)); }
+  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;
Index: avida/current/source/tools/tList.hh
diff -u avida/current/source/tools/tList.hh:1.8 avida/current/source/tools/tList.hh:1.8.4.1
--- avida/current/source/tools/tList.hh:1.8	Thu Feb 14 07:57:41 2002
+++ avida/current/source/tools/tList.hh	Tue May 27 11:45:41 2003
@@ -1,5 +1,5 @@
 //////////////////////////////////////////////////////////////////////////////
-// Copyright (C) 1993 - 2001 California Institute of Technology             //
+// 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.     //
@@ -185,6 +185,13 @@
   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;


More information about the Avida-cvs mailing list