//size versus energy //real proportions function init_chambers() { colors = ["1.0,1.0,0.0","1.0,0.5,0.0"]; chambers = [ ["0.0,0.0,0.0,", //coiled "1.08020961284637, -0.0597195439040661, -0.0393781512975693,", "1.08020961284637, -0.0597195439040661, -0.0393781512975693,", "0.615013539791107, 0.778662621974945, 0.535521030426025,", "0.488581955432892, 0.826426684856415, -0.381044268608093,", "0.732419908046722, -0.0084995785728097, -1.02214300632477,", "1.35288727283478, 0.875738024711609, -1.03719782829285,", "0.342692613601685, 0.938660383224487, -1.45657968521118,", "1.0958571434021, 0.316927701234818, -1.813929438591,", "0.903768002986908, 1.11856341362, -2.53161096572876,", "0.21014116704464, 0.295340299606323, -2.45328187942505,"], ["0.0,0.0,0.0,", //longitudal "0.98089325428009, 0.00591040402650833, 0.00389722990803421,", "1.90962779521942, -0.256769120693207, -0.16194811463356,", "2.63965249061584, -0.727959632873535, -0.609036147594452,", "3.17575979232788, -1.34843015670776, -1.14828503131866,", "3.55273032188416, -2.22369408607483, -1.3917418718338,", "3.64916682243347, -3.11888360977173, -1.01666414737701,", "3.50461649894714, -3.84039807319641, -0.377427101135254,", "3.15921688079834, -4.50001525878906, 0.261153399944305,", "2.51528453826904, -5.16421365737915, 0.59241509437561,"]]; } function createForamMorphology(morphotype, gen, chamber_num) { var rad = getProperty(gen, "chamber_proculus"); var geno = "//0\np:" + chambers[morphotype][0] + "sh=1,sx=" + rad + ",sy=" + rad + ",sz=" + rad + ", rz=3.14159265358979,vr=" + colors[gen]; chamber_num = Math.min(chamber_num, chambers[morphotype].size - 1); for (var i = 0; i < chamber_num; i++) { rad = getProperty(gen, "chamber_proculus") + getProperty(gen, "chamber_difference") * (i + 1); geno += "\n" + "p:" + chambers[morphotype][i+1] + "sh=1,sx=" + rad + ",sy=" + rad + ",sz=" + rad + ",vr=" + colors[gen]; } for (var i = 0; i < chamber_num; i++) { geno += "\n" + "j:"+ i +", "+ (i+1) +", sh=1"; } if (morphotype == 0) geno += "\nn:p=0,d=\"S\""; return geno; } function setGenotype(mode) { if (mode->opt == 0) //initial { mode->cr.data->genes = String.deserialize(String.serialize(mode->genes)); mode->cr.data->lifeparams = {"max_energy_level" : mode->energy0, "gen" : 0, "hibernated" : 0, "species" : mode->species, "reproduce" : 0, "dir" : randomDir(), "chamber_growth" : -1, "division_time" : -1}; } else if (mode->opt == 1) //child { mode->cr.data->lifeparams = {"max_energy_level" : mode->energy0, "gen" : 1 - mode->parent_lifeparams->gen, "hibernated" : 0, "species" : mode->parent_lifeparams->species, "reproduce" : 0, "dir" : randomDir(), "chamber_growth" : -1, "division_time" : -1}; mode->cr.data->genes = String.deserialize(String.serialize(mode->parent_genes)); } else //grow { mode->cr.data->genes = mode->parent_genes; mode->cr.data->lifeparams = mode->parent_lifeparams; } } function gametsDivision(parent_energy, energy0) { var number = 1; var result = parent_energy; while ((result-ExpProperties.divisionCost) >= energy0) { result = (result-ExpProperties.divisionCost)/2; number *= 2; } //Simulator.print("parent: " + parent_energy + " result: " + result + " number " + number); return {"energy" : result, "number" : number}; } function getEnergy0(radius) { return energyFromVolume(micronsToFrams(radius),1); } function reproduce_haploid(parent, parent2, clone) { var number, energy0, new_genes, gen; if (clone == 1) { var offspring = gametsDivision(parent.energy,getEnergy0(getGene(parent,"energies0",0)[0])); energy0 = offspring->energy; number = offspring->number; new_genes = parent.data->genes; parent.data->lifeparams->gen = 1 - parent.data->lifeparams->gen; //because of reversal of "gen" in createOffspring function gen = parent.data->lifeparams->gen; } else { var offspring1 = gametsDivision(parent.energy,getEnergy0(getGene(parent,"energies0", 0)[1])); var offspring2 = gametsDivision(parent2.energy,getEnergy0(getGene(parent2,"energies0", 0)[1])); energy0 = (offspring1->energy+offspring2->energy); number = ExpProperties.gametSuccessRate*(offspring1->number+offspring2->number)/2; new_genes = [parent.data->genes, parent2.data->genes]; gen = 1 - parent.data->lifeparams->gen; } Simulator.print("haploid number of offspring: " + number + " energ0: " + energy0); for (var j = 0; j < number; j++) { createOffspring(createForamMorphology(getGene(parent, "morphotype", 0), gen, 0), energy0, new_genes, parent.data->lifeparams); } } function reproduce_diploid(parent) { var energy0 =getEnergy0( getGene(parent,"energies0", 0)[0]); var number = ((1 - (getProperty(parent.data->lifeparams->gen, "e_repro_cost"))) * parent.energy) / energy0; Simulator.print("diploid number of offspring: " + number+ " energ0: " + energy0); for (var j = 0; j < number / 2; j++) { var crossed = 0; //crossover if (Math.rnd01 < ExpProperties.crossprob) { crossover(parent, "min_repro_energies"); crossed = 1; } for (var k = 0; k < 2; k++) { createOffspring(createForamMorphology(getGene(parent, "morphotype", 0), 1 - parent.data->lifeparams->gen, 0), energy0, parent.data->genes[0], parent.data->lifeparams); } //reverse of crossover for fossilization if (crossed == 1) { crossover(parent, "min_repro_energies"); crossed = 0; } } } function reproduce_parents(species) { var parent1 = null; var parent2 = null; var pop = Populations[0]; for (var i = pop.size-1; i >= 0; i--) { if (pop[i].data->lifeparams->reproduce == 1 && pop[i].data->lifeparams->species == species) { if ((pop[i].data->lifeparams->gen==1) || ((pop[i].data->lifeparams->gen==0) && ExpProperties.stress == 0)) { continue; } else if (parent1 == null) { parent1 = pop[i]; } else if (parent2 == null) { parent2 = pop[i]; } if (parent1 != null && parent2 != null) { //when parents are ready for reproduction start gametogenesis if (parent1.data->lifeparams->division_time == -1 && parent2.data->lifeparams->division_time == -1) { var time = int(ExpProperties.gametoPeriod/ExpProperties.secPerStep); parent1.data->lifeparams->division_time = time; parent2.data->lifeparams->division_time = time; parent1.idleen = 0; parent2.idleen = 0; //Simulator.print("parents "+parent1.uid + " " + parent2.uid + " ready to repro: "+Simulator.stepNumber); } //when gametogenesis is finished fuse gamets else if (parent1.data->lifeparams->division_time == 0 && parent2.data->lifeparams->division_time == 0) { reproduce_haploid(parent1, parent2, 0); print_repro_info(parent1); print_repro_info(parent2); //Simulator.print("parents "+parent1.uid + " " + parent2.uid + " reproduced: "+Simulator.stepNumber); pop.kill(parent1); pop.kill(parent2); parent1 = null; parent2 = null; } } } } } function readyToRepro(cr) { var reproduced = 1; if (cr.data->lifeparams->gen == 1) { reproduce_diploid(cr); } else if (ExpProperties.stress == 0) { reproduce_haploid(cr, null, 1); } else { if (cr.signals.size == 0) { cr.signals.add("repro"+cr.data->lifeparams->species); cr.signals[0].power = 1; } reproduced = 0; cr.data->lifeparams->reproduce = 1; } if (reproduced == 1) { print_repro_info(cr); Populations[0].kill(cr); } return reproduced; } function print_repro_info(cr) { Simulator.print("Reproduced " + cr.data->lifeparams->gen + " of species " + cr.data->lifeparams->species + " energy: " + cr.energy); } function foramReproduce(cr) { var properEnergy = cr.energy >= energyFromVolume(max_chamber_volume[cr.data->lifeparams->gen][getGene(cr, "min_repro_energies",0)[cr.data->lifeparams->gen]],0); var reproduced = 0; //if creature has proper energy if ( properEnergy && cr.signals.size == 0) { //reproduce with probability repro_prob if (Math.rnd01 <= ExpProperties.repro_prob) //TODO env trigger { reproduced = readyToRepro(cr); } else if (cr.signals.receive("repro"+cr.data->lifeparams->species) > 0) { reproduced = readyToRepro(cr); } if (reproduced == 1) return 1; } else if (!properEnergy) { cr.signals.clear(); cr.data->lifeparams->reproduce = 0; } return 0; } function crossover(parent, gene) { var tmp = parent.data->genes[0][gene]; parent.data->genes[0][gene] = parent.data->genes[1][gene]; parent.data->genes[1][gene] = tmp; } function createOffspring(geno, energy, parent_genes, parent_lifeparams) { var cr = Populations[0].add(geno); cr.energy0 = energy; cr.energy = cr.energy0; setGenotype({"cr" : cr, "parent_genes" : parent_genes, "parent_lifeparams" : parent_lifeparams, "opt" : 1, "energy0" : cr.energy0}); placeRandomlyNotColliding(cr); }