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

Last change on this file since 421 was 421, checked in by oriona, 9 years ago

refactoring, removed unused params, creatures and food chanfe to forams and nutirents

File size: 13.7 KB
Line 
1expdef:
2name:Reproduction of benthic foraminifera
3info:~
4Genes and parameter values which control reproduction are stored in user1 and user2 fields.
5
6user1:
7genes which are not encoded in Ff genotype:
8minenergy - Minimum stored energy necessary for reproduction
9minage - minimal age for reproduction
10
11user2:
12Physiological parameters of foraminifera:
13Va - amount of the stored energy
14gen - generation: 0 haploid, 1 diploid
15~
16code:~
17
18/*
19changes 2015-06-24:
20- xxx.get(...) changed to xxx[...]
21- xxx.set(...,...) changed to xxx[...]=...
22- function placeRandomlyNotColliding(cr) explicitly called when adding a new creature, and removed collision checking from onForamsBorn() which is also called when "growing" (since "growing" is implemented as creating a new creature in place of the old one, so onForamsBorn() is also called)
23- use creature's center (not the bbox corner) when growing
24- added "S" receptor to visualize the difference between diplo and haplo generations
25- signal.value is a MechPart (a reference) so it does not have to be updated after changing the object location
26*/
27
28global nutrientenergywaiting;
29global reprocounter;
30
31@include "foraminifera.inc"
32
33// -------------------------------- experiment begin --------------------------------
34
35function onExpDefLoad()
36{
37        // define genotype and creature groups
38        GenePools.clear();
39        Populations.clear();
40        GenePools[0].name = "Unused";
41
42        SignalView.mode = 1;
43
44        var pop = Populations[0];
45        pop.name = "Forams";
46        pop.en_assim = 0;
47        pop.nnsim = 0;
48        pop.enableperf = 1;
49        pop.death = 1;
50        pop.energy = 1;
51        pop.selfmask = 0x10001;
52        pop.othermask = 0x20001;
53        //pop.selfmask = 0x20002; pop.othermask = 0x10002;
54        pop.perfperiod = 25;
55
56        pop = Populations.addGroup("Nutrients");
57        pop.nnsim = 0;
58        pop.enableperf = 0;
59        pop.death = 1;
60        pop.energy = 1;
61        pop.selfmask = 0x20002;
62        pop.othermask = 0x10000;
63
64        //radius of the chamber
65        ExpParams.rads = [1.2, 0.6];
66        //inital genotypes
67        ExpParams.genh = createForamGenotype(ExpParams.rads[0]);
68        ExpParams.gend = createForamGenotype(ExpParams.rads[1])+"\nn:p=0,d=\"S\"";
69        ExpParams.creath = -0.99; //just above the bottom
70        ExpParams.e_meta = 0.1;
71        ExpParams.feedrate = 0.5;
72        ExpParams.feede0 = 100;
73        ExpParams.feedtrans = 3;
74        ExpParams.nutrientsize = 0.1;
75        ExpParams.nutrientgen = "//0\np:sh=2,sx="+ExpParams.nutrientsize+",sy="+ExpParams.nutrientsize+",sz="+ExpParams.nutrientsize+"\nn:d=T,p=0";
76        ExpParams.autorestart = 0;
77        ExpParams.popsize = 10;
78        //ExpParams.logging = 1; //uncomment to enable logging simulation parameters to log files
79
80        //number of offspring
81        ExpParams.energy0h = 40;
82        ExpParams.energy0d = 25;
83        //minial volume for reproduction
84        ExpParams.minenerg = [300, 300];
85        //minimal age for reproduction
86        ExpParams.minage = [100, 100];
87        //crossover probability
88        ExpParams.crossprob = 0.4;
89        //mutation probability
90        ExpParams.mutationprob = 0.2;
91        ExpParams.repro_time = 45;
92
93        //grwoth speed in simulation steps
94        ExpParams.growth_step = 50;
95
96        ExpState.totaltestedcr = 0;
97        ExpState.nutrient = "";
98        nutrientenergywaiting = ExpParams.feede0;
99        reprocounter = 0;
100
101        ExpParams.worldsize = 50;
102        World.wrldwat = 50;
103        World.wrldsiz = ExpParams.worldsize;
104        World.wrldbnd = 1;
105}
106
107@include "standard_placement.inc"
108
109function onExpInit()
110{
111        Populations[0].clear();
112        Populations[1].clear();
113
114        for (var i = 0; i < ExpParams.popsize; i++)
115        {
116                var cr = Populations[0].add(ExpParams.genh);
117                cr.name = "Initial creature" + i;
118                placeCreatureRandomly(cr, 0, 0);
119                cr.energy0 = ExpParams.energy0h;
120                cr.energy = cr.energy0;
121                cr.user1 = {"minenergy" : ExpParams.minenerg[0], "minage": ExpParams.minage[0]};
122                cr.user2 = {"Va" : ExpParams.energy0h, "gen" : 0, "growth_step" : ExpParams.growth_step, "rsize" : ExpParams.rads[0], "vinit" : ExpParams.energy0h};
123        }
124        ExpState.totaltestedcr = 0;
125        nutrientenergywaiting = ExpParams.feede0;
126}
127
128function onExpLoad()
129{
130        for (var pop in Populations)
131                pop.clear();
132
133        Loader.addClass(sim_params.*);
134        Loader.setBreakLabel(Loader.BeforeUnknown, "onExpLoad_Unknown");
135        Loader.run();
136
137        Simulator.print("Loaded " + Populations[0].size + " Forams and " + Populations[1].size + " nutrient objects");
138}
139
140function onExpLoad_Unknown()
141{
142        if (Loader.objectName == "org") // saved by the old expdef
143        {
144                var g = Genotype.newFromString("");
145                Loader.currentObject = g;
146                Interface.makeFrom(g).setAllDefault();
147                Loader.loadObject();
148                var cr = Populations[0].add(g);
149                if (cr != null)
150                {
151                        //cr.rotate(0,0,Math.rnd01*Math.twopi);
152                        if ((typeof(g.user1) == "Vector") && (g.user1.size >= 3))
153                        {
154                                // [x,y,energy]
155                                cr.move(g.user1[0] - cr.center_x, g.user1[1] - cr.center_y, 0);
156                                cr.energy = g.user1[2];
157                        }
158                        else
159                        {
160                                cr.move(Math.rnd01 * World.wrldsiz - cr.center_x, Math.rnd01 * World.wrldsiz - cr.center_y, 0);
161                        }
162                }
163        }
164        else if (Loader.objectName == "Creature")
165        {
166                Loader.currentObject = CreatureSnapshot.new();
167                Loader.loadObject();
168                Populations[0].add(Loader.currentObject);
169        }
170}
171
172function onExpSave()
173{
174        File.writeComment("saved by '%s.expdef'" % Simulator.expdef);
175
176        var tmpvec = [], i;
177
178        for(var cr in Populations[1])
179                tmpvec.add([cr.center_x, cr.center_y, cr.energy]);
180
181        ExpState.nutrient = tmpvec;
182        File.writeObject(sim_params.*);
183        ExpState.nutrient = null; //vectors are only created for saving and then discarded
184
185        for (var cr in Populations[0])
186                File.writeObject(cr);
187}
188
189// -------------------------------- experiment end --------------------------------
190
191// -------------------------------- foram begin -----------------------------------
192
193function createForamGenotype(radius)
194{
195        return "//0\np:sh=1,sx=" + radius + ",sy=" + radius + ",sz=" + radius + ", rz=3.14159265358979";
196}
197
198function onForamsBorn(cr)
199{
200        cr.idleen = ExpParams.e_meta;
201}
202
203function placeRandomlyNotColliding(cr)
204{
205        var retry = 100; //try 100 times
206        while (retry--)
207        {
208                placeCreatureRandomly(cr, 0, 0);
209                if (!cr.boundingBoxCollisions(0))
210                        return cr;
211        }
212
213        Populations[0].delete(cr);
214}
215
216function readyToRepro(cr)
217{
218        cr.signals.add("repro");
219        cr.signals[0].power = 1;
220}
221
222function foramMove(cr)
223{
224        //TODO moving inside sediment?
225        cr.moveAbs(cr.pos_x, cr.pos_y, 0); //adjustment in z axis
226
227        var p = cr.getMechPart(0);
228        var n = cr.signals.receiveSet("nutrient", ExpParams.nutrient_range);
229
230        //if signals are received find the source of the nearest
231        if (n.size > 0)
232        {
233
234                var i;
235                var mp;
236                var distvec = XYZ.new(0, 0, 0);
237                var dist;
238                var mindist = 100000000000;
239                var mindistvec = null;
240
241                for (i = 0; i < n.size; i++)
242                {
243                        mp = n[i].value;
244                        distvec.set(mp.pos);
245                        distvec.sub(p.pos);
246                        dist = distvec.length;
247                        if (dist < mindist)
248                        {
249                                mindist = dist;
250                                mindistvec = distvec.clone();
251                        }
252                }
253
254                mindistvec.normalize();
255                mindistvec.scale(-0.08);
256                cr.localDrive = mindistvec;
257        }
258
259        else
260        {
261                cr.localDrive = (0.1 * Math.rnd01, 0.1 * Math.rnd01, 0);
262        }
263}
264
265function foramGrow(cr)
266{
267                //TODO how size is related to the energy?
268                cr.user2["rsize"] = ExpParams.rads[cr.user2["gen"]] * Math.min(Math.max(float(cr.user2["Va"] / cr.user2["vinit"]) * 0.5, 1.0), 2.5);
269                var geno = createForamGenotype(cr.user2["rsize"]);
270                if (cr.user2["gen"] == 1)
271                {
272                        geno += "\nn:p=0,d=\"S\""; //TODO why initial genotypes are not used as defined in ExpParams?
273                        //TODO maybe it would be nice if they rotated so the "S" would show where they are going (direction/intention)
274                }
275                var cr2 = Populations[0].add(geno);
276                cr2.energy0 = cr.energy;
277                cr2.energy = cr2.energy0;
278                setGenotype(cr2, cr.user1, cr.user2);
279                cr2.moveAbs(cr.center_x - cr2.size_x / 2, cr.center_y - cr2.size_y / 2, cr.pos_z);
280
281                Populations[0].delete(cr);
282}
283
284function onForamsStep(cr)
285{
286        foramMove(cr);
287
288        //energy costs depend on size
289        if (cr.energy > 100)
290        {
291                //TODO energy costs dependent on size
292                // cr.energy_m = cr.user2["Va"]/cr.user2["vinit"];
293        }
294
295        //TODO lifespan should not be used, it is set to 0 with every growth_step
296        if (cr.lifespan >= ExpParams.max_age)
297        {
298                //TODO what is max age value? should there be one
299                //Populations[0].kill(cr);
300                //return;
301        }
302
303        //foram growth
304        if (cr.lifespan == cr.user2["growth_step"])
305        {
306                foramGrow(cr);
307        }
308        else
309        {
310                var properSize = 0;
311
312                if (cr.user2["gen"] == 0)
313                {
314                        properSize = cr.user2["Va"] >= cr.user1["minenergy"];
315                }
316                else
317                {
318                        properSize = cr.user2["Va"] >= cr.user1[0]["minenergy"]; //TODO gene selection
319                }
320
321                //if creature has proper age and cytoplasm amount
322                if ( properSize )
323                {
324                        //reproduce with probability repro_prob
325                        if (Math.rnd01 <= ExpParams.repro_prob)
326                        {
327                                readyToRepro(cr);
328                        }
329                }
330                if ( properSize && (cr.signals.receive("repro") > 0))
331                {
332                        readyToRepro(cr);
333                }
334        }
335}
336
337function onForamsDied(cr)
338{
339        //fossilization
340        var geno = GenePools[0].add(cr.genotype);
341        geno.user1 = cr.user1;
342        geno.user2 = cr.user2;
343        if (ExpParams.logging == 1) Simulator.print("\"" + cr.name + "\" died...");
344        ExpState.totaltestedcr++;
345}
346
347function setGenotype(cr, new_user1, new_user2)
348{
349        cr.user2 = {"Va" : new_user2["Va"], "gen" : new_user2["gen"], "growth_step" : new_user2["growth_step"], "rsize" : new_user2["rsize"], "vinit": new_user2["vinit"]};
350        if (cr.user2["gen"] == 0)
351        {
352                cr.user1 = {"minenergy" : new_user1["minenergy"], "minage": new_user1["minage"] };
353        }
354        else if (cr.user2["gen"] == 1)
355        {
356                cr.user1 = [ {"minenergy" : new_user1[0]["minenergy"], "minage": new_user1[0]["minage"] }, {"minenergy" : new_user1[1]["minenergy"], "minage": new_user1[1]["minage"] }];
357        }
358
359}
360
361// --------------------------------foram end -------------------------------------
362
363// -------------------------------- nutrient begin --------------------------------
364
365function onNutrientsStep(cr)
366{
367        cr.moveAbs(cr.pos_x % ExpParams.worldsize, cr.pos_y % ExpParams.worldsize, 0.5);
368}
369
370function addNutrient()
371{
372        var cr = Populations[1].add(ExpParams.nutrientgen);
373
374        cr.name = "Nutrients";
375        cr.idleen = 0;
376        cr.energy0 = ExpParams.feede0;
377        cr.energy = cr.energy0;
378        cr.signals.add("nutrient");
379
380        cr.signals[0].value = cr.getMechPart(0);
381
382        placeRandomlyNotColliding(cr);
383}
384
385function onNutrientsCollision()
386{
387        if (Collision.Creature2.user2 != null)
388        {
389                var e = Collision.Part2.ing * ExpParams.feedtrans;
390                //Simulator.print("transferring "+e+" from "+Collision.Creature1.name+" to "+Collision.Creature2.name+" ("+Collision.Creature2.energy+")");
391                Collision.Creature1.energy_m = Collision.Creature1.energy_m + e;
392                Collision.Creature2.energy_p = Collision.Creature2.energy_p + e;
393                Collision.Creature2.user2["Va"] = float(Collision.Creature2.user2["Va"]) + float(e);
394        }
395}
396
397// -------------------------------- nutrient end --------------------------------
398
399
400function log(tolog, fname)
401{
402        var f = File.appendDirect(fname, "forams data");
403        f.writeString("" + Simulator.stepNumber);
404        for (var  i = 0; i < tolog.size; i++)
405        {
406                f.writeString(";" + tolog[i]);
407        }
408        f.writeString("\n");
409        f.close();
410}
411
412
413
414
415@include "standard_events.inc"
416
417~
418
419prop:
420id:max_age
421name:Maximal age
422type:d 100 1000 500
423group:Foraminifera
424
425prop:
426id:worldsize
427name:World size
428type:d 10 1000 20
429
430prop:
431id:growth_step
432name:Growth step
433type:d -1 10000 1000
434group:Foraminifera
435help:You can turn off growth by setting this param to -1
436
437prop:
438id:rads
439name:Haploid and diploid radius
440type:x
441group:Foraminifera
442
443prop:
444id:minage
445name:Min reproduction age of forams
446type:x
447group:Foraminifera
448
449prop:
450id:minenerg
451name:Min reproduction energy of forams
452type:x
453group:Foraminifera
454
455prop:
456id:nutrient_range
457name:Range of nutrient smell
458type:d 0 10000 10000
459
460prop:
461id:repro_time
462name:Time before reproduction
463type:d 0 1000
464
465prop:
466id:popsize
467name:Initial forams population size
468type:d 1 1000 100
469group:Foraminifera
470
471prop:
472id:energy0h
473name:Number of offspring from haploid forams
474type:d
475group:Foraminifera
476
477prop:
478id:energy0d
479name:Number of offspring from diploid forams
480type:d
481group:Foraminifera
482
483prop:
484id:repro_prob
485name:Probability of reproduction
486type:f 0 1 0.9
487group:Foraminifera
488
489prop:
490id:crossprob
491name:Crossover probability
492type:f 0 1 0
493group:Foraminifera
494
495prop:
496id:mutationprob
497name:Mutation probability
498type:f 0 1 0
499group:Foraminifera
500
501prop:
502id:genh
503name:Initial genotype of haploid forams
504type:s 1
505group:Foraminifera
506
507prop:
508id:gend
509name:Initial genotype of diploid forams
510type:s 1
511group:Foraminifera
512
513prop:
514id:creath
515name:Creation height
516type:f -1 50
517help:~
518Vertical position (above the surface) where new Forams are revived.
519Negative values are only used in the water area:
520  0   = at the surface
521-0.5 = half depth
522-1   = just above the bottom~
523
524prop:
525id:e_meta
526name:Idle metabolism
527type:f 0 1
528group:Energy
529help:Each stick consumes this amount of energy in one time step
530
531prop:
532id:feedrate
533name:Feeding rate
534type:f 0 100
535group:Energy
536help:How fast energy is created in the world
537
538prop:
539id:feede0
540name:Nutrients's energy
541group:Energy
542type:f 0 1000
543
544prop:
545id:feedtrans
546name:Ingestion multiplier
547group:Energy
548type:f 0 100
549
550prop:
551id:nutrientgen
552name:Nutrients's genotype
553group:Energy
554type:s 1
555
556prop:
557id:nutrientsize
558name:Nutrients's size
559group:Energy
560type:f 0.1
561
562prop:
563id:nutrientPop
564name:Nutrients population size
565group:Energy
566type:d 1 1000 10
567
568state:
569id:nutrient
570name:Nutrients locations
571help:vector of vectors [x,y,energy]
572type:x
573flags:32
574
575prop:
576id:autorestart
577name:Restart after extinction
578help:Restart automatically this experiment after the last creature has died?
579type:d 0 1
580
581state:
582id:notes
583name:Notes
584type:s 1
585help:~
586You can write anything here
587(it will be saved to the experiment file)~
588
589state:
590id:totaltestedcr
591name:Evaluated Forams
592help:Total number of the Forams evaluated in the experiment
593type:d
594flags:16
595
596prop:
597id:logging
598name:Log statistics to file
599type:d 0 1 0
Note: See TracBrowser for help on using the repository browser.