Cellular automaton script

Hi everyone, I’m fairly new to Python Scripting and this forum. I wrote a short script which creates a simulation of a cellular automaton system (like the Game Of Life). It isn’t really useful for anything, but it’s kind of funny to play with.
I’m posting it here because I would like to have more experienced coders’ feedback on the script, whether it’s easy to use, if there are bugs, etc. It is not exactly light, because the simulation grid extends to infinity, and the simulation quickly freezes depending on the settings…
I couldn’t find any such script in for blender, but if there are, sorry for the redundancy…
Have fun!

PS. I’m not really sure how to share the script, but since it’s not that heavy and there is no .blend, I guess I’ll just put it here. Please tell me if it’s not the proper way :wink:

###########################################################################################################################
#
#
#    Use :   Make sure you delete every object before using the script, except cubes with a "*_*_*" name format
#            To add or remove cells prior to simulation, choose the coordinates for the cell and click add/remove
#
#            Use the left and right arrow to navigate the simulation time (one frame = one iteration).
#
#            Have fun !
#
###########################################################################################################################

bl_info = {
    "name": "Cellular Automaton",
    "author": "M.Zob",
    "version": (0, 0),
    "blender": (2, 6, 5),
    "api": 35853,
    "location": "View3D > Tool Shelf > Cellular Automaton",
    "description": "Creates a cellular automaton system",
    "warning": "",
    "wiki_url": "",
    "tracker_url": "",
    "category": "3D View"}

import bpy


###Programme definition

listeCellulesInit = [[0,1,0],[0,0,1],[1,0,0]]

def creerCubes(listeCoordonnees):
        for a in range(len(listeCoordonnees)):
            bpy.ops.mesh.primitive_cube_add(location = (listeCoordonnees[a][0],listeCoordonnees[a][1],listeCoordonnees[a][2]))
            bpy.ops.transform.resize(value=(0.5,0.5,0.5))
            
            nom = str(listeCoordonnees[a][0]) + '_' + str(listeCoordonnees[a][1]) + '_' + str(listeCoordonnees[a][2])
            bpy.context.object.name = nom
            bpy.data.objects[nom].hide = True
            bpy.context.object.keyframe_insert('hide', frame = bpy.context.scene.frame_current - 1, group = "groupAutomate")
            bpy.data.objects[nom].hide = False
            bpy.context.object.keyframe_insert('hide', frame = bpy.context.scene.frame_current, group = "groupAutomate")

#def init():
#    """Initialization"""
#    for object in bpy.data.objects:
#        object.hide = False
#    bpy.ops.object.select_all(action='SELECT')
#    bpy.ops.object.delete()
#    creerCubes(listeCellulesInit)


def iteration():
    nbrIterations = bpy.context.scene.cell_aut_iter
    min = bpy.context.scene.cell_aut_min
    max = bpy.context.scene.cell_aut_max
    for iter in range(0,nbrIterations):
        listeCellules = []
        coeffCellules = []
        bpy.context.scene.frame_set(bpy.context.scene.frame_current + 1)
        
        for object in bpy.data.objects:
            
            if object.hide == False:
                nom = object.name
                coordonnees = nom.split('_')
                
                ###Listing adjacent cells
                for x in range(-1,2):
                    for y in range(-1,2):
                        for z in range(-1,2):
                            ### Counting nimber of adjacent old cells for each new cell.
                            if not [int(coordonnees[0])+x, int(coordonnees[1])+y, int(coordonnees[2])+z] in listeCellules:
                                listeCellules.append([int(coordonnees[0])+x, int(coordonnees[1])+y, int(coordonnees[2])+z])
                                coeffCellules.append(1)
                            else:
                                indexCell = listeCellules.index([int(coordonnees[0])+x, int(coordonnees[1])+y, int(coordonnees[2])+z])
                                coeffCellules[indexCell] = coeffCellules[indexCell] + 1
                object.hide = True
                            
        ###Creating / showing new cells
        
        for newCell in range(len(listeCellules)):
            if coeffCellules[newCell] <= max and coeffCellules[newCell] >= min:
                nomNewCell = str(listeCellules[newCell][0]) + "_" + str(listeCellules[newCell][1]) + "_" + str(listeCellules[newCell][2])
                if nomNewCell in bpy.data.objects:
                    bpy.data.objects[nomNewCell].hide = False
                    
                if not nomNewCell in bpy.data.objects:
                    creerCubes([[listeCellules[newCell][0], listeCellules[newCell][1], listeCellules[newCell][2]]])
        
        for object in bpy.data.objects:
                object.keyframe_insert('hide', frame = bpy.context.scene.frame_current, group = "groupAutomate")



def main(context):
#    init()
    iteration()

def ajout(context):
    xAjout = bpy.context.scene.cell_aut_x_add
    yAjout = bpy.context.scene.cell_aut_y_add
    zAjout = bpy.context.scene.cell_aut_z_add
    nom = str(xAjout) + "_" + str(yAjout) + "_" + str(zAjout)
    if not nom in bpy.data.objects:
        creerCubes([[xAjout,yAjout,zAjout]])
    elif bpy.data.objects[nom].hide == False:
        bpy.data.objects[nom].hide = True
    else:
        bpy.data.objects[nom].hide = False


###Definition des proprietes de l'operateur

def init_properties():

    sc = bpy.types.Scene

    sc.cell_aut_min = bpy.props.IntProperty(
            name="Min neighbours",
            description="Minimum neighbour number for a cell to live on.",
            default=3,
            min=1,
            max=27)
            
            
    sc.cell_aut_max = bpy.props.IntProperty(
            name="Max neighbours",
            description="Minimum neighbour number for a cell to live on.",
            default=5,
            min=1,
            max=27)

    sc.cell_aut_iter = bpy.props.IntProperty(
            name="Iterations",
            description="Number of iterations (frames).",
            default=3,
            min=0,
            max=100)

    sc.cell_aut_x_add = bpy.props.IntProperty(
            name="x",
            description="X coordinate for the cell to add / remove.",
            default=0)

    sc.cell_aut_y_add = bpy.props.IntProperty(
            name="y",
            description="Y coordinate for the cell to add / remove.",
            default=0)

    sc.cell_aut_z_add = bpy.props.IntProperty(
            name="z",
            description="Z coordinate for the cell to add / remove.",
            default=0)

def clear_properties():
    props = ["cell_aut_min", "cell_aut_max", "cell_aut_iter", "cell_aut_x_add", "cell_aut_y_add", "cell_aut_z_add"]
    for p in props:
        if bpy.context.window_manager.get(p) != None:
            del bpy.context.window_manager[p]
        try:
            x = getattr(bpy.types.WindowManager, p)
            del x
        except:
            pass


class OperateurAutomateCellulaire(bpy.types.Operator):
    bl_label = "Operateur automate cellulaire"
    bl_idname = "view3d.automate_cellulaire"
    
    @classmethod
    def poll(cls, context):
        return (1 is not None)
    
    def execute(self, context):
        main(context)
        return {'FINISHED'}
    
class OperateurAutomateCellulaireAjout(bpy.types.Operator):
    bl_label = "Operateur automate cellulaire : ajout / retrait"
    bl_idname = "view3d.automate_cellulaire_ajout"

    @classmethod
    def poll(cls, context):
        return (1 is not None)

    def execute(self, context):
        ajout(context)
        return {'FINISHED'}
    
###Definition de l'UI

class PanneauAutomateCellulaire(bpy.types.Panel):
    bl_label = "Cellular automaton"
    bl_idname = "3D_VIEW_PT_automate_cellulaire"
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOLS"
    
    
    def draw(self,context):
        sc = context.scene
        layout = self.layout
        
        col = layout.column(align = True)
        row = col.row(align = True)
        row.label("Add / remove cell")
        
        row = col.row(align = True)
        row.prop(sc,"cell_aut_x_add")
        row.prop(sc,"cell_aut_y_add")
        row.prop(sc,"cell_aut_z_add")
        
        row = col.row(align = True)
        row.operator("view3d.automate_cellulaire_ajout", text = "Add / remove")
        
        col = layout.column(align = True)
        row = col.row(align = True)
        row.label("Automaton settings")
        
        row = col.row(align = True)
        row.prop(sc, "cell_aut_min")
        row.prop(sc, "cell_aut_max")
        
        row = col.row(align = True)
        row.prop(sc, "cell_aut_iter")
        
        row = col.row(align = True)
        row.operator("view3d.automate_cellulaire", text = "Automaton !")



def register():
    init_properties()
    bpy.utils.register_class(OperateurAutomateCellulaire)
    bpy.utils.register_class(OperateurAutomateCellulaireAjout)
    bpy.utils.register_class(PanneauAutomateCellulaire)

def unregister():
    clear_properties()
    bpy.utils.unregister_class(OperateurAutomateCellulaire)
    bpy.utils.unregister_class(OperateurAutomateCellulaireAjout)
    bpy.utils.unregister_class(PanneauAutomateCellulaire)

if __name__ == "__main__":
    register()

I get script error when I click Automation. Line #74

I did a short test animation to show a possible use of this script.
Here it is.