source: experiments/frams/foraminifera/data/scripts/foraminifera.expdef @ 554

Last change on this file since 554 was 554, checked in by oriona, 8 years ago

Refactoring, change of foraminifera direction at world boundary added.

File size: 26.8 KB
RevLine 
[380]1expdef:
[406]2name:Reproduction of benthic foraminifera
[380]3info:~
[434]4Basic information about this simulation:
5www.framsticks.com/foraminifera
6
7Technical information:
[476]8Genes and parameter values which control reproduction are stored in data->genes and data->lifeparams fields.
[380]9
[476]10genes:
[402]11genes which are not encoded in Ff genotype:
[422]12min_repro_energy - Minimum energy necessary for reproduction
13hibernation - Defines foram behavior in the case of no nutrients
[380]14
[476]15lifeparams:
[380]16Physiological parameters of foraminifera:
[422]17max_energy_level - maximum energy level reached so far
[380]18gen - generation: 0 haploid, 1 diploid
[432]19species - species: 0 not hibernating 1 hibernating
20hibernated - 0/1 foram is/isn't hibernated
[422]21reproduce - 0/1 foram isn't/is ready for reproduction
[380]22~
23code:~
24
[479]25global chambers;
[422]26global colors;
[493]27global retColors;
28global curColor;
[479]29global max_chamber_volume;
[474]30global movePerStep;
[479]31global nutrientenergywaiting;
32global o;
33global reprocounter;
[481]34global changePeriod;
35global phase;
[493]36global nutrientSqrCm;
[487]37global species_genes;
[380]38
[406]39@include "foraminifera.inc"
[401]40
[380]41// -------------------------------- experiment begin --------------------------------
42
43function onExpDefLoad()
44{
45        // define genotype and creature groups
46        GenePools.clear();
47        Populations.clear();
48        GenePools[0].name = "Unused";
49
50        var pop = Populations[0];
[421]51        pop.name = "Forams";
[380]52        pop.en_assim = 0;
[404]53        pop.nnsim = 0;
[380]54        pop.enableperf = 1;
55        pop.death = 1;
56        pop.energy = 1;
[487]57        pop.selfmask = 0;
58        pop.othermask = 0;
[401]59        //pop.selfmask = 0x20002; pop.othermask = 0x10002;
[422]60        pop.perfperiod = 25;
[487]61        pop.bodysim = 0;
[380]62
[421]63        pop = Populations.addGroup("Nutrients");
[380]64        pop.nnsim = 0;
65        pop.enableperf = 0;
66        pop.death = 1;
67        pop.energy = 1;
[487]68        pop.selfmask = 0;
69        pop.othermask = 0;
[422]70        //pop.othermask = 0x10002;
[487]71        pop.bodysim = 0;
[380]72
[444]73        pop = Populations.addGroup("ReticulopodiaNutrients");
[430]74        pop.nnsim = 0;
75        pop.enableperf = 0;
76        pop.death = 0;
77        pop.energy = 0;
[487]78        pop.selfmask = 0;
79        pop.othermask = 0;
80        pop.bodysim = 0;
[444]81
[422]82        //world
83        SignalView.mode = 1;
[496]84        World.wrldwat = 200;
[493]85        World.wrldsiz = micronsToFrams(100000);
[422]86        World.wrldbnd = 1;
87
[474]88        movePerStep = getMovePerStep();
89
[486]90        //ExpProperties.visualize = 1; //uncomment to visualize reticulopodia and indicate nutrients positions
[444]91
[487]92        //ExpProperties.logging = 1; //uncomment to enable logging simulation parameters to log files   
[493]93        ExpProperties.logPref = "";
[401]94
[487]95        species_genes = [];
96
[554]97        //morphology
[479]98        init_chambers();
[493]99        curColor = retColors[0];
[486]100        ExpProperties.zone1_range = micronsToFrams(1000);
101        ExpProperties.zone2_range = micronsToFrams(3000);
102        ExpProperties.chamber_proculus_haplo = micronsToFrams(50);
103        ExpProperties.chamber_difference_haplo = 0.0;
104        ExpProperties.chamber_proculus_diplo = micronsToFrams(20);
105        ExpProperties.chamber_difference_diplo = micronsToFrams(8);
[479]106
107        max_chamber_volume = [Vector.new(), Vector.new()];
[422]108        for (var j = 0; j < 2; j++)
109        {
110                for (var i = 0; i < chambers[0].size; i++)
111                {
[479]112                        max_chamber_volume[j].add(((volumeInMicrons(getProperty(j, "chamber_proculus")) + volumeInMicrons(getProperty(j, "chamber_proculus") + (i) * getProperty(j, "chamber_difference")))*(i+1))/2); 
[422]113                }                                 
114        }
115
116        //nutrients
[486]117        ExpProperties.nutrientradius = micronsToFrams(10);
[552]118        ExpProperties.energy_nut = 200 * energyFromVolume(ExpProperties.nutrientradius,1);
[554]119        nutrientSqrCm = 10;
[493]120        ExpProperties.nutrient_pop = Math.pow(framsToMicrons(World.wrldsiz)*0.0001,2)/nutrientSqrCm;
[554]121
[380]122        ExpState.totaltestedcr = 0;
[421]123        ExpState.nutrient = "";
[488]124       
[493]125        //addSpecies({"min_repro_energies" : [4,6]});
126        //addSpecies({"min_repro_energies" : [4,8]});
[380]127}
128
129@include "standard_placement.inc"
130
[554]131function secToSimSteps(value_in_sec){
132        return value_in_sec/ExpProperties.secPerStep;
133}
134
[479]135function volumeInMicrons(radiusInFrams)
[475]136{
[479]137        return 4.0/3.0*Math.pi*Math.pow(framsToMicrons(radiusInFrams),3);
[475]138}
139
[479]140function energyFromVolume(base, isRadiusInFrams)
141{
142        if (isRadiusInFrams == 1) //radius in frams
143        {
[486]144                return ExpProperties.picoCarbonPerMikro*volumeInMicrons(base);
[479]145        }
146        else //volume in microns
147        {
[486]148                return ExpProperties.picoCarbonPerMikro * base;
[479]149        }
150}
151
[474]152function getMovePerStep()
153{
[486]154        return micronsToFrams((ExpProperties.foramSpeedMmPerMin/60)*1000)*ExpProperties.secPerStep;
[474]155}
156
[447]157function micronsToFrams(micrometers)
[422]158{
[493]159        return micrometers*0.01;
[422]160}
161
[447]162function framsToMicrons(framsworldunits)
[445]163{
[493]164        return framsworldunits/0.01;
[445]165}
166
[422]167function getProperty(gen, prop_id)
168{
169        var ploid = "haplo";
170        if (gen == 1) ploid = "diplo";
[486]171        return ExpProperties.[prop_id + "_" + ploid];
[422]172}
173
[487]174function getGene(cr, gen_id, gen_set)
175{
176        if (cr.data->lifeparams->gen == 0)
177                return cr.data->genes[gen_id];
178        else
179                return cr.data->genes[gen_set][gen_id];
180}
181
[479]182function addForam(species, iter, chambernum, ploid)
[422]183{
[496]184        var geno = createForamMorphology(ploid, ploid, chambernum);
[493]185        curColor = retColors[ploid];
[422]186        var cr = Populations[0].add(geno);
[479]187        cr.name = "Initial creature" + species + "_" + iter;
[422]188        placeCreatureRandomly(cr, 0, 0);
[479]189        cr.energy0 = energyFromVolume(max_chamber_volume[ploid][chambernum],0);
[422]190        cr.energy = cr.energy0;
[554]191        setGenotype({"opt" : "birth", "cr" : cr, "gen" : ploid, "species" : species, "energy0" : cr.energy0, "genes" : species_genes[species]});
[479]192        if (ploid == 1)
193        {
194                cr.data->genes = [cr.data->genes, cr.data->genes]; //TODO two different genes sets
195        }
[525]196        moveReticulopodia(cr);
[422]197}
198
[479]199function addInitialForam(species, iter)
200{
201        var ploid = 0;
202        if (Math.rnd01 > 0.5)
203        {
204                ploid = 1;
205        }       
[493]206        //add new foram with random energy bewtween starting energy and reproduction threshold
[488]207        addForam(species, iter, int(Math.rndUni(0,species_genes[species]->min_repro_energies[ploid])),ploid);
[479]208}
209
[487]210//new species can be added as a dictionary with parameter values that are different than default values
211function addSpecies(new_genes)
212{
[493]213        species_genes.add({"min_repro_energies" : [ExpProperties.min_repro_energ_haplo,ExpProperties.min_repro_energ_diplo], "energies0" : [ExpProperties.energies0_haplo, ExpProperties.energies0_diplo], "hibernation" : 0, "morphotype" : 0});
[487]214        for (var i = 0; i < new_genes.size; i++)
215        {
216                var key = new_genes.getKey(i);
217                species_genes[species_genes.size-1][key] = new_genes[key];
218        }
219}
220
[380]221function onExpInit()
222{
223        Populations[0].clear();
224        Populations[1].clear();
[444]225        Populations[2].clear(); //reticulopodia and nutrients
[380]226
[487]227        if (species_genes.size == 0)
[380]228        {
[487]229                addSpecies({}); //default
[380]230        }
[487]231
232        for (var spec = 0; spec < species_genes.size; spec++)
233        {
234                for (var i = 0; i < ExpProperties.foramPop; i++)
235                {
236                        addInitialForam(spec, i);       
237                }
238        }
[422]239        o = Populations[0][0].getMechPart(0).orient.clone();
[380]240        ExpState.totaltestedcr = 0;
[554]241
242        reprocounter = 0;
243        nutrientenergywaiting = 0;
244        changePeriod = 0;
245        phase = "low";
[380]246}
247
248function onExpLoad()
249{
250        for (var pop in Populations)
251                pop.clear();
252
253        Loader.addClass(sim_params.*);
254        Loader.setBreakLabel(Loader.BeforeUnknown, "onExpLoad_Unknown");
255        Loader.run();
256
[421]257        Simulator.print("Loaded " + Populations[0].size + " Forams and " + Populations[1].size + " nutrient objects");
[380]258}
259
260function onExpLoad_Unknown()
261{
262        if (Loader.objectName == "org") // saved by the old expdef
263        {
264                var g = Genotype.newFromString("");
265                Loader.currentObject = g;
266                Interface.makeFrom(g).setAllDefault();
267                Loader.loadObject();
268                var cr = Populations[0].add(g);
269                if (cr != null)
270                {
[401]271                        //cr.rotate(0,0,Math.rnd01*Math.twopi);
[476]272                        if ((typeof(g.data->genes) == "Vector") && (g.data->genes.size >= 3))
[401]273                        {
274                                // [x,y,energy]
[476]275                                cr.move(g.data->genes[0] - cr.center_x, g.data->genes[1] - cr.center_y, 0);
276                                cr.energy = g.data->genes[2];
[380]277                        }
278                        else
279                        {
[401]280                                cr.move(Math.rnd01 * World.wrldsiz - cr.center_x, Math.rnd01 * World.wrldsiz - cr.center_y, 0);
[380]281                        }
282                }
283        }
284        else if (Loader.objectName == "Creature")
285        {
286                Loader.currentObject = CreatureSnapshot.new();
287                Loader.loadObject();
288                Populations[0].add(Loader.currentObject);
289        }
290}
291
292function onExpSave()
293{
294        File.writeComment("saved by '%s.expdef'" % Simulator.expdef);
295
[401]296        var tmpvec = [], i;
[380]297
[401]298        for(var cr in Populations[1])
[380]299                tmpvec.add([cr.center_x, cr.center_y, cr.energy]);
300
[421]301        ExpState.nutrient = tmpvec;
[380]302        File.writeObject(sim_params.*);
[432]303        ExpState.nutrient = null; //vectors are only created for saving and then discarded
[380]304
305        for (var cr in Populations[0])
306                File.writeObject(cr);
307}
308
309// -------------------------------- experiment end --------------------------------
310
[421]311// -------------------------------- foram begin -----------------------------------
[380]312
[479]313function setForamMeta(cr)
[430]314{
[479]315        //percent of current energy
[486]316        cr.idleen = (ExpProperties.e_meta * cr.energy)*ExpProperties.secPerStep;
[430]317}
318
319function lastChamberNum(cr)
320{
321        return cr.numparts-1;
322}
323
[479]324function getZoneRange(cr, zone_num)
325{
[486]326        return ExpProperties.["zone"+zone_num+"_range"];
[479]327}
328
[421]329function onForamsBorn(cr)
330{
[479]331        setForamMeta(cr);
[486]332        if (ExpProperties.visualize == 1)
[430]333        {
[506]334                var ret = Populations[2].add("//0\nm:Vstyle=reticulopodia\np:sh=1,sx=0.001,sy=0.001,sz=0.001\np:sh=3,sx=0.01,sy="+getZoneRange(cr,1)+",sz="+getZoneRange(cr,1)+",ry=1.57079633,vr="+curColor+"\nj:0, 1, sh=1");
[476]335                cr.data->reticulopodiacreature = ret;
[506]336                ret.getMechPart(0).orient.set(cr.getMechPart(0).orient);
[496]337                ret.moveAbs(cr.center_x-getZoneRange(cr,1), cr.center_y-getZoneRange(cr,1), cr.center_z-getZoneRange(cr,1));
[430]338        }
[380]339}
340
[401]341function placeRandomlyNotColliding(cr)
342{
343        var retry = 100; //try 100 times
344        while (retry--)
345        {
346                placeCreatureRandomly(cr, 0, 0);
347                if (!cr.boundingBoxCollisions(0))
348                        return cr;
349        }
350
351        Populations[0].delete(cr);
352}
353
[444]354function visualization(cr)
355{
356        var has_ret = 0;
357
[476]358        if (cr.data->reticulopodiacreature != null)
[444]359        {
[476]360                if (Populations[2].findUID(cr.data->reticulopodiacreature.uid) != null)
[444]361                {
362                        has_ret = 1;
363                }
364        }
365
366        return has_ret;
367}
368
[422]369function foramGrow(cr, chamber_num)
[380]370{
[476]371        if ((chamber_num+1) < chambers[cr.data->lifeparams->species].size)
[474]372        {
[493]373                curColor = retColors[cr.data->lifeparams->gen];
[496]374                var geno = createForamMorphology(cr.data->lifeparams->gen, cr.data->lifeparams->gen, chamber_num+1);
[474]375                var cr2 = Populations[0].add(geno);
[422]376
[474]377                cr2.energy0 = cr.energy;
378                cr2.energy = cr2.energy0;
[422]379
[554]380                setGenotype({"cr" : cr2, "parent_genes" : cr.data->genes, "parent_lifeparams" : cr.data->lifeparams, "opt" : "growth", "energy0" : cr.energy0});
[474]381                cr2.moveAbs(cr.center_x - cr2.size_x / 2, cr.center_y - cr2.size_y / 2, cr.pos_z);
[479]382                setForamMeta(cr2);
[422]383
[474]384                if (visualization(cr))
385                {
[476]386                        Populations[2].delete(cr.data->reticulopodiacreature);
[474]387                }
388                Populations[0].delete(cr);
[430]389        }
[380]390}
391
[435]392function stepToNearest(cr)
[380]393{
394        var p = cr.getMechPart(0);
[479]395        var n = cr.signals.receiveSet("nutrient", getZoneRange(cr,2));
[380]396
[401]397        //if signals are received find the source of the nearest
[380]398        if (n.size > 0)
399        {
400                var i;
401                var mp;
402                var distvec = XYZ.new(0, 0, 0);
403                var dist;
[470]404                var mindist = 100000000000.0;
[380]405                var mindistvec = null;
[430]406                var eating = 0;
[380]407
[401]408                for (i = 0; i < n.size; i++)
[380]409                {
[430]410                        mp = n[i].value.getMechPart(0);
[401]411                        distvec.set(mp.pos);
412                        distvec.sub(p.pos);
413                        dist = distvec.length;
[479]414                        if (dist < getZoneRange(cr,1))
[380]415                        {
[430]416                                if (n[i].value != null)
417                                {
418                                        energyTransfer(cr, n[i].value);
419                                        eating = 1;
420                                }
421                        }
[476]422                        else if (eating == 0 && cr.data->lifeparams->hibernated == 0 && dist < mindist)
[430]423                        {
[401]424                                mindist = dist;
425                                mindistvec = distvec.clone();
[380]426                        }
427                }
428
[476]429                if (!eating && cr.data->lifeparams->hibernated == 0)
[430]430                {
431                        mindistvec.normalize();
[474]432                        mindistvec.scale(-1*movePerStep);
[430]433                        cr.localDrive = mindistvec;
434                        moveEnergyDec(cr);
435                }
436
[422]437                return 1;
[380]438        }
[422]439       
440        else
[474]441        {
[422]442                return 0;
[474]443        }
[422]444}
[401]445
[422]446function moveEnergyDec(cr)
447{
[476]448        if (cr.data->lifeparams->hibernated == 0)
[422]449        {
[479]450                //percent of maximal energy
[504]451                cr.energy -= (ExpProperties.energy_move * cr.data->lifeparams->max_energy_level)*ExpProperties.secPerStep;
[422]452        }
[421]453}
[380]454
[493]455function fence(pos, zone)
[487]456{
[496]457        return Math.min(Math.max(0,pos),World.wrldsiz);
[487]458}
459
[422]460function foramMove(cr)
[421]461{
[422]462        //TODO moving inside sediment?
[421]463
[422]464        //adjustment in z axis
[554]465        var change_direction = 0;
466        var new_x = fence(cr.pos_x, getZoneRange(cr, 1));
467        var new_y = fence(cr.pos_y,getZoneRange(cr, 1));
[421]468
[554]469        if ((new_x != cr.pos_x) || (new_y != cr.pos_y) || (cr.data->lifeparams->dir_counter >= int(secToSimSteps(ExpProperties.dir_change_sec))))
470        {
471                change_direction = 1;
472        }
473
474        cr.moveAbs(new_x, new_y, 0);
475
[430]476        //are there any nutrients in zone 1 or 2?
[401]477        {
[435]478                var moved = stepToNearest(cr); //TODO weighted sum of distance and energy
[422]479                if (moved==1)
[430]480                {
[502]481                        moveReticulopodia(cr);
[422]482                        return;
483                }
[401]484        }
485
[422]486        //no nutrients in zone 2
[487]487        if (getGene(cr, "hibernation",0) == 1)
[401]488        {
[430]489                reverseHib(cr);
[422]490                cr.localDrive = XYZ.new(0,0,0);
[380]491        }
[422]492        //random move
[554]493        else if (change_direction == 1)
[380]494        {
[476]495                cr.data->lifeparams->dir = randomDir();
[552]496                cr.data->lifeparams->dir_counter = 0;
[476]497                cr.localDrive = cr.data->lifeparams->dir;
[422]498                moveEnergyDec(cr);
499        }
[474]500        else
501        {
[476]502                cr.localDrive = cr.data->lifeparams->dir;
[474]503        }
[502]504        moveReticulopodia(cr);
[422]505}
[401]506
[502]507function moveReticulopodia(cr)
508{
509        if (visualization(cr))
510        {
511                cr.data->reticulopodiacreature.moveAbs(cr.center_x-getZoneRange(cr,1), cr.center_y-getZoneRange(cr,1), cr.center_z-getZoneRange(cr,1));
512                cr.data->reticulopodiacreature.localDrive = cr.localDrive;
513        }
514}
515
[474]516function randomDir()
517{
[486]518        var dir = (Math.rndUni(-ExpProperties.zone2_range, ExpProperties.zone2_range), Math.rndUni(-ExpProperties.zone2_range, ExpProperties.zone2_range), 0); 
[474]519        dir.normalize();
520        dir.scale(-1*movePerStep);
521        return dir;
522}
523
[430]524function energyTransfer(cr1, cr2)
[422]525{
[430]526        cr1.localDrive = XYZ.new(0,0,0);
[510]527        var e =  ExpProperties.feedtrans*cr1.energy*ExpProperties.secPerStep; //TODO efficiency dependent on age
[502]528        //Simulator.print("transferring "+e +"("+e*ExpProperties.ingestion+")"+" to "+cr1.name +" ("+ cr1.energy+") " +" from "+cr2.uid+" ("+cr2.energy+") "+ e/ExpProperties.secPerStep+ " per sec");
[510]529        var transferred = cr2.transferEnergyTo(cr1, e);
530        cr1.energy -= transferred*(1-ExpProperties.ingestion);
[476]531        if (cr1.data->lifeparams->hibernated == 1)
[422]532        {
[430]533                reverseHib(cr1);
[422]534        }
535}
[401]536
[430]537function reverseHib(cr)
538{
[476]539        if (cr.data->lifeparams->hibernated == 1)
[430]540        {
[479]541                setForamMeta(cr); //unhibernate
[430]542        }
543        else
544        {
[486]545                cr.idleen = (ExpProperties.energy_hib * cr.energy)*ExpProperties.secPerStep; //hibernate
[430]546        }
[476]547        cr.data->lifeparams->hibernated = 1 - cr.data->lifeparams->hibernated;
[430]548}
549
[493]550function createLogVector(cr, value)
551{
552        var vec = Vector.new();
553        for (var i = 0; i < species_genes.size; i++)
554        {
555                for (var j = 0; j < 2; j++)
556                {
557                        vec.add(0);
558                }
559                if (cr.data->lifeparams->species == i)
560                {
561                        vec[i*2+cr.data->lifeparams->gen] = value;             
562                }
563        }
564        return vec;
565}
[479]566
[422]567function onForamsStep(cr)
568{
[479]569        //checking for gametogenesis process
570        if (cr.data->lifeparams->division_time > 0)
[444]571        {
[479]572                cr.data->lifeparams->division_time = Math.max(cr.data->lifeparams->division_time-1,0);
[444]573        }
[479]574        //checking for end of gametogenesis
575        else if (cr.data->lifeparams->division_time == 0)
[422]576        {
[479]577                //waiting for gamets fusion
[422]578        }
[479]579        //checking for chamber growth process
580        else if (cr.data->lifeparams->chamber_growth > 0)
581        {
582                cr.data->lifeparams->chamber_growth = Math.max(cr.data->lifeparams->chamber_growth-1,0);
[486]583                //Simulator.print("chamber growing, time left = " + cr.data->lifeparams->chamber_growth*ExpProperties.secPerStep);
[504]584                cr.energy -= ExpProperties.chamberCostPerSec * cr.energy * ExpProperties.secPerStep;
[422]585
[479]586                //Simulator.print("energy " + cr2.energy + " subtracting " + growth_cost);
587        }
588        //checking for end of chamber growth process
589        else if (cr.data->lifeparams->chamber_growth == 0)
[430]590        {
[479]591                foramGrow(cr, lastChamberNum(cr));
592                cr.data->lifeparams->chamber_growth = -1;
593                //Simulator.print("chamber "+ (lastChamberNum(cr) + 1) +" complete");
[430]594        }
[479]595        else
[422]596        {
[479]597                //update of metabolism rate
598                if (cr.data->lifeparams->hibernated == 0)
[401]599                {
[479]600                        setForamMeta(cr);
601                }
602
603                cr.getMechPart(0).orient.set(o);
604
605                if (deathConditions(cr) == 1)
606                {
[493]607                        if (ExpProperties.logging == 1)
608                        {
609                                log(createLogVector(cr, cr.data->lifeparams->max_energy_level),ExpProperties.logPref+"fossil_log.txt");
[552]610                                log(createLogVector(cr, cr.lifespan),ExpProperties.logPref+"lifespan_log.txt");
[493]611                        }                       
[479]612                        Populations[0].kill(cr);
613                        return;
614                }
615
[552]616                //update direction change counter
617                cr.data->lifeparams->dir_counter += 1;
618
[479]619                foramMove(cr);
620
621                var repro = foramReproduce(cr);
622                if (repro == 1)
623                {
624                        return;
625                }
626
627                cr.data->lifeparams->max_energy_level = Math.max(cr.energy, cr.data->lifeparams->max_energy_level);
628
629                //cheking conditions of chamber growth process start
630                if  (lastChamberNum(cr) != chambers[0].size-1)
631                {
632                        if ((cr.data->lifeparams->max_energy_level >= energyFromVolume(max_chamber_volume[cr.data->lifeparams->gen][lastChamberNum(cr)],0)))   
633                        {
[554]634                                cr.data->lifeparams->chamber_growth = int(secToSimSteps(ExpProperties.chamberGrowthSec));
[479]635                        }       
636                }
[430]637        }       
[380]638}
639
[422]640function deathConditions(cr)
641{
[486]642        if ((cr.energy <= getProperty(cr.data->lifeparams->gen,"e_death_level")*cr.data->lifeparams->max_energy_level) || (Math.rnd01 < ExpProperties.hunted_prob))
[479]643        {
[422]644                return 1;
[479]645        }
[422]646        else
647                return 0;
648}
649
[421]650function onForamsDied(cr)
[380]651{
[444]652        if (visualization(cr))
[430]653        {
[476]654                Populations[2].delete(cr.data->reticulopodiacreature);
[430]655        }
[380]656        //fossilization
657        var geno = GenePools[0].add(cr.genotype);
[476]658        geno.data->genes = cr.data->genes;
659        geno.data->lifeparams = cr.data->lifeparams;
[486]660        if (ExpProperties.logging == 1) Simulator.print("\"" + cr.name + "\" died...");
[380]661        ExpState.totaltestedcr++;
662}
663
[421]664// --------------------------------foram end -------------------------------------
[380]665
[421]666// -------------------------------- nutrient begin --------------------------------
[380]667
[479]668function createNutrientGenotype(nutrientradius)
[422]669{
[524]670        return "//0\nm:Vstyle=nutrient\np:sh=3,sx="+nutrientradius+",sy="+nutrientradius+",sz="+nutrientradius+",ry=1.57,vr=0.0,1.0,0.0";
[422]671}
672
[421]673function onNutrientsStep(cr)
[380]674{
[444]675        cr.moveAbs(cr.pos_x % World.wrldsiz, cr.pos_y % World.wrldsiz, 0.5);
[380]676}
677
[421]678function addNutrient()
[380]679{
[486]680        var cr = Populations[1].add(createNutrientGenotype(ExpProperties.nutrientradius));
[380]681
[421]682        cr.name = "Nutrients";
[380]683        cr.idleen = 0;
[486]684        cr.energy0 = ExpProperties.energy_nut;
[416]685        cr.energy = cr.energy0;
[421]686        cr.signals.add("nutrient");
[380]687
[430]688        cr.signals[0].value = cr;
[380]689
[422]690        placeCreatureRandomly(cr, 0, 0);
[486]691        if (ExpProperties.visualize == 1)
[444]692        {
[486]693                var nutsize = ExpProperties.nutrientradius*10;
[554]694                var nut = Populations[2].add("//0\np:sh=2,sx="+nutsize+",sy="+nutsize+",sz="+nutsize+",ry=1.5,vr=0.0,1.0,0.0");
[476]695                cr.data->reticulopodiacreature = nut;
[444]696                nut.moveAbs(cr.pos_x-1.5*nutsize, cr.pos_y-1.5*nutsize, 0.5);
697        }
[380]698}
699
[444]700function onNutrientsDied(cr)
701{
702        if (visualization(cr))
703        {
[476]704                Populations[2].delete(cr.data->reticulopodiacreature);
[444]705        }
706}
707
[422]708function nutrientGrowth()
[380]709{
[486]710        if (ExpProperties.foodPeriodChange > 0)
[481]711        {
712                        changePeriod += 1;
[554]713                        if (phase=="low" && changePeriod >= secToSimSteps(23328000)) //9 months
[481]714                        {
[486]715                                ExpProperties.foodperiod = ExpProperties.foodperiod/ExpProperties.foodPeriodChange;
[481]716                                phase = "high";
717                                changePeriod = 0;
718                        }
719               
[554]720                        else if (phase == "high" && changePeriod >= secToSimSteps(7776000)) //3 months
[481]721                        {
[486]722                                ExpProperties.foodperiod = ExpProperties.foodperiod*ExpProperties.foodPeriodChange;
[481]723                                phase = "low";
724                                changePeriod = 0;
725                        }
726        }
[474]727        nutrientenergywaiting = nutrientenergywaiting + 1;
[554]728        if (nutrientenergywaiting >= secToSimSteps(ExpProperties.foodperiod))
[380]729        {
[493]730                for (var i = 0; i < ExpProperties.nutrient_pop; i++)
[432]731                {   
[422]732                        addNutrient();
733                }
734
735                nutrientenergywaiting = 0.0;
736                Simulator.checkpoint();
[493]737
738                if (ExpProperties.logging == 1)
739                {
740                        log([ExpProperties.nutrient_pop],ExpProperties.logPref+"nutrients_log.txt");
741                }
[380]742        }
[493]743
[380]744}
745
[421]746// -------------------------------- nutrient end --------------------------------
[380]747
[422]748// -------------------------------- step begin --------------------------------
[380]749
[422]750function onStep()
751{
[432]752
753        nutrientGrowth();
[486]754        if (ExpProperties.logging == 1)
[422]755        {
756                createStatistics();
757        }
758
759        //reproduction --------------------------------------------
760        reprocounter += 1;
[554]761        if (reprocounter > secToSimSteps(ExpProperties.reproTimeSec))
[422]762        {
763                reprocounter = 0;
764                reproduce_parents(0);
765                reproduce_parents(1);
766        }
767
768        //check for extinction -----------------------------------------------
769        if (Populations[0].size == 0)
770        {
[486]771                if (ExpProperties.autorestart)
[422]772                {
773                        Simulator.print("no more creatures, restarting...");
774                        onExpInit();
775                }
776                else
777                {
778                        Simulator.print("no more creatures, stopped.");
779                        Simulator.stop();
780                }
781        }
[486]782        if (ExpProperties.maxSteps > 0)
[432]783        {
[486]784                if (Simulator.stepNumber >= ExpProperties.maxSteps)
[432]785                        Simulator.stop();
786        }
[422]787}
788
789function createStatistics()
790{       
[487]791        var number = [];
792        var e_inc = [];
[422]793        var e_nut = 0.0;
794
[487]795        for (var s = 0; s < species_genes.size; s++)
796        {
797                number.add([0,0]);// [haplo][diplo]
798                e_inc.add([0,0]);
799        }
800
[422]801        for (var i = 0; i < Populations[0].size; i++)
802        {
803                var cr = Populations[0].get(i);
[476]804                var gen = cr.data->lifeparams->gen;
805                var species = cr.data->lifeparams->species;
[430]806
807                number[species][gen] = number[species][gen] + 1;
808                e_inc[species][gen] = e_inc[species][gen] + cr.energy;
[422]809        }
810
811        for (var i = 0; i < Populations[1].size; i++)
812        {
813                var cr = Populations[1].get(i);
814                e_nut += cr.energy;
815        }
816
[487]817        var log_numbers = [];
818        var log_energies = [];
[422]819
[487]820        for (var s = 0; s < species_genes.size; s++)
821        {
822                for (var p = 0; p < 2; p++)
823                {
824                        log_numbers.add(number[s][p]);
825                        log_energies.add(e_inc[s][p]);
826                }
827        }
828       
829        log_numbers.add(Populations[1].size);
830        log_energies.add(e_nut);
831
[493]832        log(log_numbers, ExpProperties.logPref+"forams_log.txt");
833    log(log_energies,  ExpProperties.logPref+"energies_log.txt");
[422]834}
835
[380]836function log(tolog, fname)
837{
[430]838        var f = File.appendDirect(fname, "forams data");
[380]839        f.writeString("" + Simulator.stepNumber);
[401]840        for (var  i = 0; i < tolog.size; i++)
[380]841        {
842                f.writeString(";" + tolog[i]);
843        }
844        f.writeString("\n");
845        f.close();
846}
847
[422]848// -------------------------------- step end --------------------------------
[479]849//TODO default params values in frams instead of microns/seconds
[380]850
[401]851@include "standard_events.inc"
[380]852
[401]853~
[380]854
[486]855property:
[444]856id:visualize
857name:Show reticulopodia and nutrients
[430]858type:d 0 1 0
[554]859group:
[430]860
[486]861property:
[434]862id:maxSteps
[554]863name:Maximum number of steps
[552]864type:d 0 10000000 0
[554]865group:
[432]866
[486]867property:
[554]868id:logging
869name:Log statistics to file
870type:d 0 1 0
871group:
872
873property:
[493]874id:logPref
875name:Log prefix
876type:s
877
878property:
[554]879id:secPerStep
880name:Seconds per simulation step
881help:Number of seconds of foraminifera time per simulation step
882type:f 1 480 300
883flags: 16
884group:
885
886property:
[474]887id:foramSpeedMmPerMin
888name:Speed of foraminfera in mm/min
[554]889type:f 0.01 0.1 0.05
[474]890flags: 16
891group:Foraminifera
892
[486]893property:
[554]894id:dir_change_sec
895name:Number of seconds before direction change
896type:d 300 300000 6000
[479]897group:Foraminifera
898
[486]899property:
[554]900id:foramPop
901name:Initial forams population size
902type:d 1 1000 20
[552]903group:Foraminifera
904
905property:
[554]906id:gametoPeriodSec
[479]907name:Time of gametogenesis
[554]908type:f 300 300000 21600
909group:Reproduction
[479]910
[486]911property:
[554]912id:gametSuccessRate
913name:Ratio of successful gamets
914type:f 0.0001 0.01 0.001
915group:Reproduction
[479]916
[486]917property:
[554]918id:divisionCost
919name:Cost of division in pG
920type:f 15 25 20
921group:Reproduction
[474]922
[486]923property:
[554]924id:min_repro_energ_haplo
925name:Min reproduction energy of haploid
926type:f 0 -1 4
927group:Energy
[380]928
[486]929property:
[554]930id:min_repro_energ_diplo
931name:Min reproduction energy of diploid
932type:f 0 -1 6
933group:Energy
[479]934
[486]935property:
[554]936id:repro_prob
937name:Probability of reproduction
938type:f 0 1 0.8
939group:Reproduction
[380]940
[486]941property:
[554]942id:energies0_haplo
943name:Energy of offspring from diploid forams
944type:f 0 -1 20
945group:Energy
[479]946
[486]947property:
[554]948id:energies0_diplo
949name:Energy of offspring from diploid forams
950type:f 0 -1 1.25
951group:Energy
952
953property:
954id:crossprob
955name:Crossover probability
956type:f 0 1 0
957group:Reproduction
958
959property:
960id:mutationprob
961name:Mutation probability
962type:f 0 1 0
963group:Reproduction
964
965property:
966id:reproTimeSec
967name:Time before reproduction
968type:d 0 10000 720
969group:Reproduction
970
971property:
972id:chamberGrowthSec
973name:Time of the chamber growth in seconds
974type:f 360 1440 720
[479]975group:Foraminifera
976
[486]977property:
[422]978id:chamber_proculus_haplo
[423]979name:Size of proculus
[422]980type:f
[421]981group:Foraminifera
[380]982
[486]983property:
[422]984id:chamber_proculus_diplo
[423]985name:Size of proculus
[422]986type:f
[380]987group:Foraminifera
988
[486]989property:
[422]990id:chamber_difference_haplo
[423]991name:Difference in size between subsequent chambers
[554]992type:f 0 -1 0
[380]993group:Foraminifera
994
[486]995property:
[422]996id:chamber_difference_diplo
[423]997name:Difference in size between subsequent chambers
[554]998type:f 0 -1 0.08
[380]999group:Foraminifera
1000
[486]1001property:
[422]1002id:hunted_prob
1003name:Probability of being hunted
1004type:f 0 1 0
[554]1005group:Foraminifera
[380]1006
[486]1007property:
[422]1008id:zone1_range
1009name:Zone 1 range
[554]1010type:f 0 200 10
[422]1011group:Foraminifera
[380]1012
[486]1013property:
[422]1014id:zone2_range
1015name:Zone 2 range
[554]1016type:f 0 3000 30
[421]1017group:Foraminifera
[380]1018
[486]1019property:
[554]1020id:chamberCostPerSec
1021name:Cost of growning chamber per second
1022type:f 0 1 0.000001
1023group:Energy
[380]1024
[486]1025property:
[475]1026id:e_death_level_haplo
1027name:Minimal level of energy to sustain life of haploid
[554]1028type:f 0 1 0.5
1029group:Energy
[475]1030
[486]1031property:
[475]1032id:e_death_level_diplo
1033name:Minimal level of energy to sustain life of diploid
[554]1034type:f 0 1 0.5
1035group:Energy
[475]1036
[486]1037property:
[422]1038id:energy_hib
1039name:Energy used for hibernation during one step
[554]1040type:f 0 1 0.0000001
1041group:Energy
[422]1042
[486]1043property:
[422]1044id:energy_move
1045name:Energy used for movement during one step
[554]1046type:f 0 1 0.0000005
1047group:Energy
[422]1048
[486]1049property:
[380]1050id:e_meta
1051name:Idle metabolism
[554]1052type:f 0 1 0.0000005
[380]1053group:Energy
1054help:Each stick consumes this amount of energy in one time step
1055
[486]1056property:
[554]1057id:ingestion
1058name:Ingestion rate
1059type:f 0 -1 0.25
1060group:Energy
1061
1062property:
[493]1063id:nutrient_pop
[554]1064name:Nutrient population
[474]1065type:f 0 1000000
[380]1066group:Energy
1067help:How fast energy is created in the world
1068
[486]1069property:
[554]1070id:energy_nut
1071name:Nutrient energy
1072type:f 0 10000000
[481]1073group:Energy
1074
[486]1075property:
[554]1076id:nutrientradius
1077name:Nutrient size
1078type:f 0.001 0.9 0.1
[479]1079group:Energy
1080
[486]1081property:
[554]1082id:picoCarbonPerMikro
1083name:Picograms of carbon in cubed micrometer
1084type:f 0 -1 0.13
[380]1085group:Energy
1086
[486]1087property:
[380]1088id:feedtrans
[479]1089name:Energy transfer per second
[554]1090type:f 0 1 0.001
[380]1091group:Energy
[422]1092
[486]1093property:
[479]1094id:foodperiod
1095name:Time between food occurrences
[554]1096type:f 0 1000000 14400
[422]1097group:Energy
1098
[486]1099property:
[554]1100id:foodPeriodChange
1101name:Set variable feed rate
1102type:f 0 -1 0
[421]1103group:Energy
1104
[486]1105property:
[422]1106id:stress
1107name:Environmental stress
1108type:d 0 1 1
[554]1109group:
[422]1110
[486]1111property:
[422]1112id:repro_trigger
1113name:Reproduction trigger
1114type:d 0 1 1
[554]1115group:Reproduction
[422]1116
[486]1117property:
[422]1118id:creath
1119name:Creation height
[554]1120type:f -1 50 -0.99
[422]1121help:~
1122Vertical position (above the surface) where new Forams are revived.
1123Negative values are only used in the water area:
1124  0   = at the surface
1125-0.5 = half depth
1126-1   = just above the bottom~
1127
[554]1128property:
1129id:autorestart
1130name:Restart after extinction
1131help:Restart automatically this experiment after the last creature has died?
1132type:d 0 1 0
1133
[421]1134state:
1135id:nutrient
[428]1136name:Nutrient locations
[421]1137help:vector of vectors [x,y,energy]
1138type:x
1139flags:32
1140
[380]1141state:
1142id:notes
1143name:Notes
1144type:s 1
1145help:~
1146You can write anything here
1147(it will be saved to the experiment file)~
1148
1149state:
1150id:totaltestedcr
[421]1151name:Evaluated Forams
1152help:Total number of the Forams evaluated in the experiment
[380]1153type:d
1154flags:16
Note: See TracBrowser for help on using the repository browser.