[Avida-cvs] [Avida2-svn] r304 - trunk/source/python/AvidaGui2

baerb@myxo.css.msu.edu baerb at myxo.css.msu.edu
Tue Aug 30 12:06:34 PDT 2005


Author: baerb
Date: 2005-08-30 15:06:34 -0400 (Tue, 30 Aug 2005)
New Revision: 304

Modified:
   trunk/source/python/AvidaGui2/pyEduWorkspaceCtrl.py
   trunk/source/python/AvidaGui2/pyEduWorkspaceView.ui
   trunk/source/python/AvidaGui2/pyFreezerCtrl.py
   trunk/source/python/AvidaGui2/pyMapProfile.py
   trunk/source/python/AvidaGui2/pyOnePop_PetriDishCtrl.py
   trunk/source/python/AvidaGui2/pyOnePopulationCtrl.py
   trunk/source/python/AvidaGui2/pyPetriConfigureCtrl.py
   trunk/source/python/AvidaGui2/pyPetriConfigureView.ui
   trunk/source/python/AvidaGui2/pyWriteGenesisEvent.py
Log:
Allow for multiple start creatures.

Started to add code for plotting lineages -- may need to be removed for class.

Added menu control to restart population -- does not work.



Modified: trunk/source/python/AvidaGui2/pyEduWorkspaceCtrl.py
===================================================================
--- trunk/source/python/AvidaGui2/pyEduWorkspaceCtrl.py	2005-08-30 18:56:56 UTC (rev 303)
+++ trunk/source/python/AvidaGui2/pyEduWorkspaceCtrl.py	2005-08-30 19:06:34 UTC (rev 304)
@@ -56,14 +56,23 @@
     self.m_one_organism_ctrl.construct(self.m_session_mdl)
     self.m_one_analyze_ctrl.construct(self.m_session_mdl)
         
-    self.connect(self, PYSIGNAL("quitAvidaPhaseISig"), self.startQuitProcessSlot)
+    self.connect(
+      self, PYSIGNAL("quitAvidaPhaseISig"), self.startQuitProcessSlot)
     self.connect(self, PYSIGNAL("quitAvidaPhaseIISig"), qApp, SLOT("quit()"))
-    self.connect(self.m_nav_bar_ctrl.m_list_view, SIGNAL("clicked(QListViewItem *)"), self.navBarItemClickedSlot)
-    self.connect(self.m_widget_stack, SIGNAL("aboutToShow(QWidget *)"), self.ctrlAboutToShowSlot)
-    # self.connect(self.fileOpenFreezerAction,SIGNAL("activated()"),self.freezerOpenSlot)
-    self.connect(self.controlNext_UpdateAction,SIGNAL("activated()"),self.next_UpdateActionSlot)
-    self.connect(self.controlStartAction,SIGNAL("activated()"),self.startActionSlot)
     self.connect(
+      self.m_nav_bar_ctrl.m_list_view, SIGNAL("clicked(QListViewItem *)"), 
+      self.navBarItemClickedSlot)
+    self.connect(
+      self.m_widget_stack, SIGNAL("aboutToShow(QWidget *)"), 
+      self.ctrlAboutToShowSlot)
+    # self.connect(
+    #   self.fileOpenFreezerAction,SIGNAL("activated()"),self.freezerOpenSlot)
+    self.connect(
+      self.controlNext_UpdateAction,SIGNAL("activated()"),
+      self.next_UpdateActionSlot)
+    self.connect(
+      self.controlStartAction,SIGNAL("activated()"),self.startActionSlot)
+    self.connect(
       self.m_session_mdl.m_session_mdtr, PYSIGNAL("setAvidaSig"),
       self.setAvidaSlot)
     self.connect(
@@ -86,6 +95,9 @@
     #   PYSIGNAL("doNextUpdateSig"),
     #   self.updatePBClickedSlot)
 
+    self.connect(self.controlRepopulateAction,SIGNAL("activated()"),
+      self.RepopulateActionSlot)
+
     self.m_nav_bar_ctrl.m_one_population_cli.setState(QCheckListItem.On)
     self.m_widget_stack.raiseWidget(self.m_one_population_ctrl)
     self.splitter1.setSizes([100])
@@ -283,8 +295,6 @@
     # (actually only works with one population will need to expand to
     # two populations in the future)
 
-    print "BDB: self.m_one_population_ctrl.m_session_mdl.saved_full_dish = " + str(self.m_one_population_ctrl.m_session_mdl.saved_full_dish)
-    print "BDB: self.m_one_population_ctrl.m_session_mdl.new_full_dish = " + str(self.m_one_population_ctrl.m_session_mdl.new_full_dish)
     if (not self.m_one_population_ctrl.m_session_mdl.saved_full_dish and
         not self.m_one_population_ctrl.m_session_mdl.new_full_dish):
       m_quit_avida_ed = pyQuitDialogCtrl()
@@ -295,3 +305,15 @@
         self.m_one_population_ctrl.m_session_mdl.m_session_mdtr.emit(PYSIGNAL("freezeDishPhaseISig"), (False, True, ))
     else:
       self.emit(PYSIGNAL("quitAvidaPhaseIISig"), ())
+
+  def RepopulateActionSlot(self):
+
+    # If the user clicks the repopulate button pretend that they double
+    # the default empty petri dish from the freezer
+
+    file_name = os.path.join(self.m_session_mdl.m_current_freezer, 
+      "default.empty")
+    self.m_session_mdl.m_session_mdtr.emit(
+      PYSIGNAL("freezerItemDoubleClicked"), (file_name, ))
+
+

Modified: trunk/source/python/AvidaGui2/pyEduWorkspaceView.ui
===================================================================
--- trunk/source/python/AvidaGui2/pyEduWorkspaceView.ui	2005-08-30 18:56:56 UTC (rev 303)
+++ trunk/source/python/AvidaGui2/pyEduWorkspaceView.ui	2005-08-30 19:06:34 UTC (rev 304)
@@ -160,6 +160,7 @@
     <item text="&amp;Control" name="Control">
         <action name="controlStartAction"/>
         <action name="controlNext_UpdateAction"/>
+        <action name="controlRepopulateAction"/>
     </item>
     <item text="&amp;View" name="View">
     </item>
@@ -617,6 +618,17 @@
             <string>Minimize Window</string>
         </property>
     </action>
+    <action>
+        <property name="name">
+            <cstring>controlRepopulateAction</cstring>
+        </property>
+        <property name="text">
+            <string>Repopulate Dish</string>
+        </property>
+        <property name="menuText">
+            <string>Repopulate dish</string>
+        </property>
+    </action>
 </actions>
 <images>
     <image name="image0">

Modified: trunk/source/python/AvidaGui2/pyFreezerCtrl.py
===================================================================
--- trunk/source/python/AvidaGui2/pyFreezerCtrl.py	2005-08-30 18:56:56 UTC (rev 303)
+++ trunk/source/python/AvidaGui2/pyFreezerCtrl.py	2005-08-30 19:06:34 UTC (rev 304)
@@ -118,17 +118,13 @@
   class itemDrag(QTextDrag):
     def __init__(self, item_name, parent=None, name=None):
         QStoredDrag.__init__(self, 'item name (QString)', parent, name)
-        print "setting up itemDrag, my parent is"
-        print parent
         self.setText(item_name)
 
   def dropEvent( self, e):
     freezer_item_name = QString()
-    print "dropEvent in freezer"
     if e.source() is self:
       return
     if ( QTextDrag.decode( e, freezer_item_name ) ) : #freezer_item_name is a string...the file name 
-      print freezer_item_name
       if freezer_item_name[:9] == 'organism.':
         freezer_item_name = freezer_item_name[9:] 
         self.FreezeOrganismSlot(freezer_item_name)
@@ -137,10 +133,7 @@
     
   def FreezeOrganismSlot(self, freezer_item_name, 
       send_reset_signal = False, send_quit_signal = False):
-    print "freezer_item_name"
-    print freezer_item_name
     tmp_dict = {1:freezer_item_name}
-#    tmp_dict["SETTINGS"] = self.Form2Dictio`nary()
     m_pop_up_organism_file_name = pyFreezeOrganismCtrl()
     file_name = m_pop_up_organism_file_name.showDialog(self.m_session_mdl.m_current_freezer)
 

Modified: trunk/source/python/AvidaGui2/pyMapProfile.py
===================================================================
--- trunk/source/python/AvidaGui2/pyMapProfile.py	2005-08-30 18:56:56 UTC (rev 303)
+++ trunk/source/python/AvidaGui2/pyMapProfile.py	2005-08-30 19:06:34 UTC (rev 304)
@@ -27,7 +27,7 @@
     GestationTimeIdx = lambda c: c.GetOrganism().GetPhenotype().GetGestationTime()
     SizeIdx = lambda c: c.GetOrganism().GetPhenotype().GetGenomeLength()
     #GenotypeIdx = lambda c: c.GetOrganism().GetGenotype()
-    #LineageIdx = lambda c: c.GetOrganism().GetLineageLabel()
+    LineageIdx = lambda c: c.GetOrganism().GetLineageLabel()
 
 
     class gradualLinScaleUpdater:
@@ -140,6 +140,7 @@
     FitnessRng = lambda p: (p.GetStats().GetMinFitness(), p.GetStats().GetMaxFitness())
     GestationTimeRng = lambda p: (p.GetStats().GetMinGestationTime(), p.GetStats().GetMaxGestationTime())
     SizeRng = lambda p: (p.GetStats().GetMinGenomeLength(), p.GetStats().GetMaxGenomeLength())
+    LineageRng = lambda p: (0, p.GetStats().GetNumLineages())
 
 
     def sigmoid(x, midpoint, steepness):
@@ -192,6 +193,11 @@
         gradualLinScaleUpdater(RangeReport(SizeRng, self.m_session_mdl)),
         sigmoidColorLookup
         ),
+      ('Ancestor Organism',
+        continuousIndexer(LineageIdx),
+        gradualLinScaleUpdater(RangeReport(LineageRng, self.m_session_mdl)),
+        sigmoidColorLookup
+        ),
       #('Genotype',       GenotypeIdx,),
       #('Lineage',        LineageIdx,),
     )

Modified: trunk/source/python/AvidaGui2/pyOnePop_PetriDishCtrl.py
===================================================================
--- trunk/source/python/AvidaGui2/pyOnePop_PetriDishCtrl.py	2005-08-30 18:56:56 UTC (rev 303)
+++ trunk/source/python/AvidaGui2/pyOnePop_PetriDishCtrl.py	2005-08-30 19:06:34 UTC (rev 304)
@@ -160,11 +160,10 @@
 
   def petriDropped(self, e):
     # Try to decode to the data you understand...
-    print "*** Entered petriDropped"
     freezer_item_name = QString()
     if ( QTextDrag.decode( e, freezer_item_name ) ) :
       if freezer_item_name[-8:] == 'organism':
-        print "we can't yet deal with organims in the population view"
+        # We can't yet deal with organims in the population view
         return
       elif freezer_item_name[-4:] == 'full':
         freezer_item_name_temp = os.path.join(str(freezer_item_name), 'petri_dish')
@@ -195,7 +194,7 @@
         # widget) the dish
 
         if (not self.m_session_mdl.saved_full_dish):
-          m_check_to_freeze = pyQuitDialogCtrl("Restart")
+          m_check_to_freeze = pyQuitDialogCtrl("Repopulate")
           quit_return = m_check_to_freeze.showDialog()
           if quit_return == m_check_to_freeze.QuitFlag:
             Restart_Only_Flag = True
@@ -208,7 +207,6 @@
           # if the user clicked the cancel button
   
           else:
-            print "BDB: hit cancel button"
             return
 
       self.RenameDishSlot(dish_name)
@@ -223,7 +221,6 @@
         pass
 
       if (Restart_Only_Flag):
-        print "BDB: sending reset signal from pyPetriConfigureCtrl:FillDishSlot"
         self.m_session_mdl.m_session_mdtr.emit(
           PYSIGNAL("restartPopulationSig"), (self.m_session_mdl, ))
 
@@ -234,34 +231,3 @@
     print "pyOnePop_PetriDishCtrl.py:restart called"
     self.dishDisabled = False
 
-    # self.m_petri_dish_ctrl.restart()
-    # self.m_gradient_scale_ctrl.destruct()
-    # self.m_live_controls_ctrl.restart()
-    # self.m_petri_configure_ctrl.destruct()
-    # self.disconnect(self.m_session_mdl.m_session_mdtr,
-    #   PYSIGNAL("freezeDishPhaseISig"),
-    #   self.m_petri_dish_ctrl.extractPopulationSlot)
-    # self.disconnect(self.m_session_mdl.m_session_mdtr, 
-    #   PYSIGNAL("freezeDishPhaseISig"), self.freezeDishPhaseISlot)
-    # self.disconnect(self.m_session_mdl.m_session_mdtr, 
-    #   PYSIGNAL("setAvidaSig"), self.setAvidaSlot)
-    # self.disconnect(self.m_petri_dish_toggle, SIGNAL("clicked()"), 
-    #   self.ToggleDishSlot)
-    # self.disconnect(self.m_session_mdl.m_session_mdtr, 
-    #   PYSIGNAL("doDefrostDishSig"), self.DefrostSlot)
-    # self.disconnect(self.m_session_mdl.m_session_mdtr, 
-    #    PYSIGNAL("doDisablePetriDishSig"), self.SetDishDisabledSlot)
-    # self.disconnect(self.m_zoom_spinbox, SIGNAL("valueChanged(int)"), 
-    #    self.m_petri_dish_ctrl.zoomSlot)
-    # self.disconnect(self.m_petri_dish_ctrl, PYSIGNAL("zoomSig"), 
-    #    self.m_zoom_spinbox.setValue)
-    # self.disconnect(self.m_mode_combobox, SIGNAL("activated(int)"), 
-    #    self.modeActivatedSlot)
-    # self.disconnect(self.m_session_mdl.m_session_mdtr, 
-    #   PYSIGNAL("petriDishDroppedInPopViewSig"), self.petriDropped)  
-    # self.m_mode_index = None
-    # self.m_session_mdl = None
-    # self.m_avida = None
-    self.m_update_label.setText("-")
-    # print "*** pyOnePop_PetriDishCtrl.py:restartPopulationSlot about to call se.f.construct ***"
-    # self.construct(session_mdl)

Modified: trunk/source/python/AvidaGui2/pyOnePopulationCtrl.py
===================================================================
--- trunk/source/python/AvidaGui2/pyOnePopulationCtrl.py	2005-08-30 18:56:56 UTC (rev 303)
+++ trunk/source/python/AvidaGui2/pyOnePopulationCtrl.py	2005-08-30 19:06:34 UTC (rev 304)
@@ -31,7 +31,6 @@
 
   def dropEvent( self, e ):
     freezer_item_name = QString()
-    print "dropEvent in one population"
     if ( QTextDrag.decode( e, freezer_item_name ) ) : #freezer_item_name is a string...the file name 
       if os.path.exists(str(freezer_item_name)) == False:
         print "that was not a valid path (1)" 

Modified: trunk/source/python/AvidaGui2/pyPetriConfigureCtrl.py
===================================================================
--- trunk/source/python/AvidaGui2/pyPetriConfigureCtrl.py	2005-08-30 18:56:56 UTC (rev 303)
+++ trunk/source/python/AvidaGui2/pyPetriConfigureCtrl.py	2005-08-30 19:06:34 UTC (rev 304)
@@ -19,7 +19,6 @@
     pyPetriConfigureView.__init__(self,parent,name,fl)
     self.setAcceptDrops(1)
 
-
   def setAvidaSlot(self, avida):
     old_avida = self.m_avida
     self.m_avida = avida
@@ -70,6 +69,8 @@
     self.connect( self, PYSIGNAL("petriDishDroppedInPopViewSig"), 
       self.m_session_mdl.m_session_mdtr, 
       PYSIGNAL("petriDishDroppedInPopViewSig"))
+    self.connect( self.m_session_mdl.m_session_mdtr, 
+      PYSIGNAL("petriDishDroppedInPopViewSig"), self.petriDropped)
     self.ChangeMutationTextSlot()
     self.ChangeWorldSizeTextSlot()
     self.populated = False
@@ -165,9 +166,19 @@
     
     self.full_petri_dict = petri_dict.dictionary
     settings_dict =  petri_dict.dictionary["SETTINGS"]
-    self.AncestorComboBox.removeItem (0)
-    start_creature = settings_dict["START_CREATURE"]
-    self.AncestorComboBox.insertItem(start_creature)
+
+    # Erase all items for the ancestor list (largest to smallest index)
+
+    for i in range((self.AncestorComboBox.count() - 1), -1, -1):
+      self.AncestorComboBox.removeItem (i)
+
+    # Find all ancestors with the name of the form START_CREATUREx
+
+    i = 0
+    while(settings_dict.has_key("START_CREATURE" + str(i))):
+      start_creature = settings_dict["START_CREATURE" + str(i)]
+      self.AncestorComboBox.insertItem(start_creature)
+      i = i + 1
     max_updates = int(settings_dict["MAX_UPDATES"])
     self.StopAtSpinBox.setValue(max_updates)
     if max_updates < 0:
@@ -296,7 +307,10 @@
   def Form2Dictionary(self):
     settings_dict = {}
     
-    settings_dict["START_CREATURE"] = str(self.AncestorComboBox.text(0))
+    # Write START_CREATUREx for all the organisms in the Ancestor Combo Box
+
+    for i in range(self.AncestorComboBox.count()):
+      settings_dict["START_CREATURE" + str(i)] = str(self.AncestorComboBox.text(i))
     if (self.StopAtRadioButton.isChecked() == True):
       settings_dict["MAX_UPDATES"] = self.StopAtSpinBox.value()
     else:
@@ -359,7 +373,6 @@
     self.m_session_mdl.m_session_mdtr.emit(
       PYSIGNAL("doRefreshFreezerInventorySig"), ())
     if send_reset_signal:
-      print "sending reset signal from pyPetriConfigureCtrl:FreezePetriSlot" 
       self.m_session_mdl.m_session_mdtr.emit(
         PYSIGNAL("restartPopulationSig"), (self.m_session_mdl, ))
 
@@ -395,10 +408,18 @@
       
   def dropEvent( self, e ):
     freezer_item_name = QString()
-    print "dropEvent"
     if ( QTextDrag.decode( e, freezer_item_name ) ) :
       if os.path.exists(str(freezer_item_name)) == False:
         print "that was not a valid path (2)" 
       else: 
         self.emit(PYSIGNAL("petriDishDroppedInPopViewSig"), (e,))
-        print "emitted(1)"
+
+  def petriDropped(self, e):
+    # Try to decode to the data you understand...
+    freezer_item_name = QString()
+    if ( QTextDrag.decode( e, freezer_item_name ) and not self.DishDisabled) :
+      if freezer_item_name[-8:] == 'organism':
+        core_name = freezer_item_name[:-9]
+        core_name = os.path.basename(str(freezer_item_name[:-9]))
+        self.AncestorComboBox.insertItem(core_name)
+        return

Modified: trunk/source/python/AvidaGui2/pyPetriConfigureView.ui
===================================================================
--- trunk/source/python/AvidaGui2/pyPetriConfigureView.ui	2005-08-30 18:56:56 UTC (rev 303)
+++ trunk/source/python/AvidaGui2/pyPetriConfigureView.ui	2005-08-30 19:06:34 UTC (rev 304)
@@ -304,7 +304,7 @@
                 <widget class="QComboBox">
                     <item>
                         <property name="text">
-                            <string>default.organism</string>
+                            <string>default</string>
                         </property>
                     </item>
                     <property name="name">
@@ -315,7 +315,7 @@
                         </font>
                     </property>
                     <property name="acceptDrops">
-                        <bool>true</bool>
+                        <bool>false</bool>
                     </property>
                     <property name="editable">
                         <bool>true</bool>

Modified: trunk/source/python/AvidaGui2/pyWriteGenesisEvent.py
===================================================================
--- trunk/source/python/AvidaGui2/pyWriteGenesisEvent.py	2005-08-30 18:56:56 UTC (rev 303)
+++ trunk/source/python/AvidaGui2/pyWriteGenesisEvent.py	2005-08-30 19:06:34 UTC (rev 304)
@@ -25,20 +25,34 @@
     else:
       cells_dict = {}
       organisms_dict = {}
-      if settings_dict.has_key("START_CREATURE"):
+      if settings_dict.has_key("START_CREATURE0"):
         world_x = settings_dict["WORLD-X"]
         world_y = settings_dict["WORLD-Y"]
-        self.start_cell_location = int(((world_y/2) * world_x) + (world_x/2))
-        cells_dict[str(self.start_cell_location)] = str(1)
 
-        # Read the genome from the organism file 
+        # Count all ancestors with the name of the form START_CREATUREx
 
-        org_file = open(os.path.join(freeze_dir, settings_dict["START_CREATURE"]))
-        org_string = org_file.readline()
-        org_string = org_string.rstrip()
-        org_string = org_string.lstrip()
-        org_file.close
-        organisms_dict[str(1)] = org_string
+        num_ancestors = 0
+        while(settings_dict.has_key("START_CREATURE" + str(num_ancestors))):
+          num_ancestors = num_ancestors + 1
+
+        # Process all the ancestors
+
+        for i in range(num_ancestors):
+          start_creature = settings_dict["START_CREATURE" + str(i)]
+
+          self.start_cell_location = self.find_location(world_x, world_y, 
+             num_ancestors, i)
+          cells_dict[str(self.start_cell_location)] = str(i)
+
+          # Read the genome from the organism file 
+
+          org_file = open(os.path.join(freeze_dir, start_creature+".organism"))
+          org_string = org_file.readline()
+          org_string = org_string.rstrip()
+          org_string = org_string.lstrip()
+          org_file.close
+          organisms_dict[str(i)] = org_string
+
     self.modifyEventFile(cells_dict, organisms_dict, 
       os.path.join(tmp_in_dir, "events.cfg"), tmp_out_dir)
     
@@ -81,13 +95,13 @@
   def modifyEventFile(self, cells_dict, organisms_dict, event_file_name, 
     tmp_out_dir = None):
 
-    # Routine to add to the event.cfg file by inject creatures into the population
-    # and adding print statements into the correct directory
+    # Routine to add to the event.cfg file by inject creatures into the
+    # population and adding print statements into the correct directory
 
     event_out_file = open(event_file_name, 'a')
     for cell in cells_dict.keys():
-      part1 = "u begin inject_sequence " +  organisms_dict[cells_dict[cell]] + " " 
-      part2 = cell + " " + str(int(cell)+1) + " -1 "
+      part1 = "u begin inject_sequence " +  organisms_dict[cells_dict[cell]]
+      part2 = " " + cell + " " + str(int(cell)+1) + " -1 "
       part3 = cells_dict[cell] + "\n"
       event_out_file.write(part1 +  part2 + part3)
     
@@ -99,3 +113,45 @@
                          os.path.join(tmp_out_dir, "count.dat") +"\n")
     event_out_file.close()
     
+  def find_location(self, world_x, world_y, num_ancestors=1, org_num=0):
+
+    # Routine to evenly place a given ancestor into the petri dish
+
+    # If there are more than 9 creatures place them evenly in the population
+    # array (ignoring the edges)
+
+    if (num_ancestors > 9):
+      return int(float(world_x * world_y) * (float(org_num + 1)/float(num_ancestors + 1))) 
+
+    spots = {};
+    if (num_ancestors == 1):
+      spots = [0.5,0.5]
+    elif (num_ancestors == 2):
+      spots = [0.5,0.33, 0.5,0.67]
+    elif (num_ancestors == 3):
+      spots = [0.25,0.25, 0.5,0.5, 0.75,0.75]
+    elif (num_ancestors == 4):
+      spots = [0.33,0.33, 0.33,0.67, 0.67,0.33, 0.67,0.67]
+    elif (num_ancestors == 5):
+      spots = [0.25,0.25, 0.75,0.25, 0.50,0.50, 0.25,0.75, 0.75,0.75]
+    elif (num_ancestors == 6):
+      spots = [0.25,0.25, 0.75,0.25, 
+               0.25,0.50, 0.75,0.50,
+               0.25,0.75, 0.75,0.75]
+    elif (num_ancestors == 7):
+      spots = [0.25,0.25, 0.75,0.25, 
+               0.25,0.50, 0.50,0.50, 0.75,0.50,
+               0.25,0.75, 0.75,0.75]
+    elif (num_ancestors == 8):
+      spots = [0.25,0.25, 0.50,0.375, 0.75,0.25, 
+               0.25,0.50, 0.75,0.50,
+               0.25,0.75, 0.50,0.625, 0.75,0.75]
+    elif (num_ancestors == 9):
+      spots = [0.25,0.25, 0.50,0.25, 0.75,0.25, 
+               0.25,0.50, 0.50,0.50, 0.75,0.50,
+               0.25,0.75, 0.50,0.75, 0.75,0.75]
+
+    x = spots[org_num * 2]
+    y = spots[(org_num * 2) + 1]
+    
+    return int((round(world_y * y) * world_x) + round(world_x * x))




More information about the Avida-cvs mailing list