source: experiments/frams/foraminifera/data/scripts/forams_benthic.expdef @ 405

Last change on this file since 405 was 405, checked in by Maciej Komosinski, 7 years ago

Fixed typos, prop:name extra space, and formatting

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