def mutateAdditionalParameters(self, rnd):
        if rnd.random() < 0.1:  self.branch_radius = Utilities.getRandomTwoDigitFloat(rnd,0.1,2)
        if rnd.random() < 0.1:  self.tropism_susceptibility = Utilities.getRandomTwoDigitFloat(rnd,0,0.2)
        if rnd.random() < 0.1:  self.details_scale = Utilities.getRandomTwoDigitFloat(rnd,0.1,5.0)
        if rnd.random() < 0.1:  self.use_canopy = 0 # rnd.random()<0.5

        if rnd.random() < 0.1: self.trunk_material_choice = rnd.randint(0,1)
        if rnd.random() < 0.1: self.leaf_material_choice = rnd.randint(0,1)
        if rnd.random() < 0.1: self.leaf_choice = rnd.randint(0,len(DetailsHandler.LEAF_NAMES)-1)
        if rnd.random() < 0.1: self.bulb_choice = rnd.randint(0,len(DetailsHandler.BULB_NAMES)-1)
        if rnd.random() < 0.1: self.flower_choice = rnd.randint(0,len(DetailsHandler.FLOWER_NAMES)-1)
        if rnd.random() < 0.1: self.fruit_choice = rnd.randint(0,len(DetailsHandler.FRUIT_NAMES)-1)
    def splitProductionRandomly(self,production,production_index):
        """ Splits a production into two productions, with stochastic probabilities that sum to 1 """

        # Remove the chosen production
        self.deleteProductionAt(production_index,redistribute = False)

        initialConditionValue = production.condition.value

        # Choose a split value
        split_value = Utilities.getRandomTwoDigitFloat(self.rnd,0,initialConditionValue)

        # Create two mutated productions from the original and add them
        successor = self.mutateProductionSuccessorRandomly(production.successor)
        stochastic_value = "{0:.2f}".format(split_value)
        self.addProductionFromElements(production.predecessor, stochastic_value, successor)

        #print("New production 1: " + str(production[0] + " -- " + str(stochastic_value) + " -- " + productionSubsequent))

        successor = self.mutateProductionSuccessorRandomly(production.successor)
        stochastic_value = "{0:.2f}".format(initialConditionValue-split_value)
        self.addProductionFromElements(production.predecessor, stochastic_value, successor)
    def changeRandomParameter(self, pString, predecessor_module = None):
        """
        Changes a random parameter in one of the modules of this parametric string into another parameter.
        """
        #TODO: optionally use defines too

        pString = ParametricString.copyFrom(pString)
        #print("We are changing pString: " + str(pString))

        # Choose the module
        actualModules = pString.getActualModules()
        module = self.getRandomItemFromList(actualModules)
        #print("Module " + str(module) +  " has parameters: " + str(module.params))

        # Choose what parameter to change
        choice = self.rnd.randint(0,len(module.params)-1)
        parameterToChange = module.params[choice]
        #print("We will change parameter " + str(choice) + ": " + str(parameterToChange))

        # Choose what to change it into
        usePredecessorParameter = False
        if predecessor_module is not None:
            usePredecessorParameter = self.rnd.random() <= 0.5

        #print("Using predecessor parameter? " + str(usePredecessorParameter))
        if usePredecessorParameter:
            changeTo = self.getRandomItemFromList(predecessor_module.params)  # TODO: use other parameters too
        else:
            genModule = self.template_modules_library.getTemplateModuleByLetter(module.letter)
            changeTo = genModule.generateConstantParameterValue(self.rnd)

        # Optionally, multiply by a constant
        if self.rnd.random() <= 0.5:
            changeTo = str(changeTo) + "*" + str(Utilities.getRandomTwoDigitFloat(self.rnd,0.5,2.0))

        module.params[choice] = changeTo
        #print("We changed it to: " + str(changeTo))

        #print("The resulting pString is: " + str(pString))
        return pString
 def generateRandomDefine(self):
     return self.addGlobalDefine("d"+str(len(self.lsystem.globalDefines)),
                                 Utilities.getRandomTwoDigitFloat(self.rnd,MIN_DEFINE_VALUE,MAX_DEFINE_VALUE))
 def generateConstantParameterValue(self,rnd):
     return Utilities.getRandomTwoDigitFloat(rnd,self.scale_min,self.scale_max)