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

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

Food seasonality added.

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