source: cpp/frams/genetics/geneprops.cpp @ 1248

Last change on this file since 1248 was 1248, checked in by Maciej Komosinski, 11 months ago

Less duplicated constants (default values of Part and Joint properties)

File size: 10.0 KB
Line 
1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2023  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
4
5#include "geneprops.h"
6#include <algorithm>
7
8GeneProps GeneProps::standard_values;
9
10GeneProps::GeneProps()
11{
12        Part_MinMaxDef default_part = Model::getDefPart();
13        Joint default_joint = Model::getDefJoint();
14
15        length = 1.0;
16        weight = 1.0;
17        friction = default_part.friction;
18        curvedness = 0.0;
19        twist = 0.0;
20        energy = 1.0;
21
22        // before 2023-05, the four fields below were aggregated and normalized using normalizeBiol4(), but this normalization only worked for f1 and f4 - other genetic encodings do not perform such normalization. If at all, this should be handled by the expdef depending on the goal of the experiment (e.g., to encourage specialization).
23        muscle_power = 0.25; // "biological" property, same as findNeuroClass("BendMuscle or RotMuscle")->paraminterface->getDoubleById("power")
24        assimilation = default_part.assim; // "biological" property
25        stamina = default_joint.stamina; // "biological" property
26        ingestion = default_part.ingest; // "biological" property
27
28        muscle_bend_range = 1.0; // same as findNeuroClass("BendMuscle")->paraminterface->getDoubleById("range")
29        muscle_reset_range = true;
30
31        cred = default_part.vcolor.x;
32        cgreen = default_part.vcolor.y;
33        cblue = default_part.vcolor.z;
34}
35
36void GeneProps::normalizeBiol4()
37{
38        // make them sum to 1
39        double sum = muscle_power + assimilation + stamina + ingestion;
40        if (sum == 0)
41        {
42                muscle_power = assimilation = stamina = ingestion = 0.25;
43        }
44        else
45        {
46                muscle_power /= sum;
47                assimilation /= sum;
48                stamina /= sum;
49                ingestion /= sum;
50        }
51}
52
53int GeneProps::executeModifier_Legacy(char modif)
54{
55        switch (modif)
56        {
57#ifdef v1f1COMPATIBLE
58        case 'L': length += (3.0 - length) * 0.3;
59                length = std::min(length, Model::getMaxJoint().d.x); break;
60#else
61        case 'L': length += (2.0 - length) * 0.3; //2.0 is currently Model::getMaxJoint().d.x so min() does not limit the range
62                length = std::min(length, Model::getMaxJoint().d.x); break;
63#endif
64        case 'l': length += (0.33 - length) * 0.3;
65                length = std::max(length, Model::getMinJoint().d.x); break;
66
67        case 'W': weight += (2.0 - weight) * 0.3; break;
68        case 'w': weight += (0.5 - weight) * 0.3; break;
69        case 'F': friction += (4 - friction) * 0.2; break;
70        case 'f': friction -= friction * 0.2; break;
71        case 'C': curvedness += (2.0 - curvedness) * 0.25; break;
72        case 'c': curvedness += (-2.0 - curvedness) * 0.25; break;
73        case 'Q': twist += (M_PI_2 - twist) * 0.3; break;
74        case 'q': twist += (-M_PI_2 - twist) * 0.3; break;
75        case 'E': energy += (10.0 - energy) * 0.1; break;
76        case 'e': energy -= energy * 0.1;  break;
77
78        case 'A': assimilation += (1 - assimilation) * 0.8; normalizeBiol4(); break;
79        case 'a': assimilation -= assimilation * 0.4; normalizeBiol4(); break;
80        case 'I': ingestion += (1 - ingestion) * 0.8; normalizeBiol4(); break;
81        case 'i': ingestion -= ingestion * 0.4; normalizeBiol4(); break;
82        case 'S': stamina += (1 - stamina) * 0.8; normalizeBiol4(); break;
83        case 's': stamina -= stamina * 0.4; normalizeBiol4(); break;
84        case 'M': muscle_power += (1 - muscle_power) * 0.8; normalizeBiol4(); break;
85        case 'm': muscle_power -= muscle_power * 0.4; normalizeBiol4(); break;
86
87        case 'D': cred += (1.0 - cred) * 0.25; break;
88        case 'd': cred += (0.0 - cred) * 0.25; break;
89        case 'G': cgreen += (1.0 - cgreen) * 0.25; break;
90        case 'g': cgreen += (0.0 - cgreen) * 0.25; break;
91        case 'B': cblue += (1.0 - cblue) * 0.25; break;
92        case 'b': cblue += (0.0 - cblue) * 0.25; break;
93
94        default: return -1;
95        }
96        return 0;
97}
98
99int GeneProps::executeModifier(char modif, GenePropsOps* ops)
100{
101        if (ops == NULL)
102                ops = getStandardOps();
103
104#define APPLY(name) ops->name->apply(name, modif)
105#define APPLY_AND_MAYBE_NORMALIZEBIOL4(name) {APPLY(name); if (ops->use_normalizebiol4) normalizeBiol4();}
106
107        switch (toupper(modif))
108        {
109        case 'L': APPLY(length);
110                length = std::min(length, Model::getMaxJoint().d.x); break;
111                break;
112
113        case 'l': APPLY(length);
114                length = std::max(length, Model::getMinJoint().d.x); break;
115                break;
116
117        case 'W': APPLY(weight); break;
118        case 'F': APPLY(friction); break;
119        case 'C': APPLY(curvedness); break;
120        case 'Q': APPLY(twist); break;
121        case 'E': APPLY(energy); break;
122
123        case 'A': APPLY_AND_MAYBE_NORMALIZEBIOL4(assimilation); break;
124        case 'I': APPLY_AND_MAYBE_NORMALIZEBIOL4(ingestion); break;
125        case 'S': APPLY_AND_MAYBE_NORMALIZEBIOL4(stamina); break;
126        case 'M': APPLY_AND_MAYBE_NORMALIZEBIOL4(muscle_power); break;
127
128        case 'D': APPLY(cred); break;
129        case 'G': APPLY(cgreen); break;
130        case 'B': APPLY(cblue); break;
131
132        default: return -1;
133        }
134        return 0;
135
136#undef APPLY
137#undef APPLY_AND_MAYBE_NORMALIZEBIOL4
138}
139
140void GeneProps::propagateAlong(bool use_f1_muscle_reset_range, GenePropsOps* ops)
141{
142        length = 0.5 * length + 0.5 * standard_values.length;
143        weight += (standard_values.weight - weight) * 0.5;
144        friction = 0.8 * friction + 0.2 * standard_values.friction;
145        curvedness = 0.66 * curvedness;
146        twist = 0.66 * twist;
147
148        assimilation = 0.8 * assimilation + 0.2 * standard_values.assimilation;
149        ingestion = 0.8 * ingestion + 0.2 * standard_values.ingestion;
150        stamina = 0.8 * stamina + 0.2 * standard_values.stamina;
151        muscle_power = 0.8 * muscle_power + 0.2 * standard_values.muscle_power;
152
153        if (ops == NULL)
154                ops = getStandardOps();
155        if (ops->use_normalizebiol4) normalizeBiol4();
156
157        if (use_f1_muscle_reset_range)
158        {
159                if (muscle_reset_range) muscle_bend_range = 1.0; else muscle_reset_range = true;
160        }
161}
162
163////////////////////////////////////////////////////
164
165void GenePropsOp::apply(double &value, char modif) const
166{
167        if (isupper(modif))
168                value = increase(value);
169        else
170                value = decrease(value);
171}
172
173double GenePropsOp_Old::increase(double value) const
174{
175        return value + (maxvalue - value) * change;
176}
177
178double GenePropsOp_Old::decrease(double value) const
179{
180        return value + (minvalue - value) * revchange;
181}
182
183GenePropsOp_Old::GenePropsOp_Old(double minvalue, double maxvalue, double defvalue, double change, double revchange)
184{
185        this->minvalue = minvalue;
186        this->maxvalue = maxvalue;
187        this->defvalue = defvalue;
188        this->change = change;
189        this->revchange = (revchange < 0) ? change : revchange;
190}
191
192GenePropsOp_Exponential::GenePropsOp_Exponential(double minvalue, double maxvalue, double defvalue, double change)
193        :GenePropsOp_NormalizedAndScaled(change)
194{
195        double mid = (maxvalue + minvalue) / 2;
196        if (fabs(mid - defvalue) < 0.01)
197        {
198                linear = true;
199                a = (maxvalue - minvalue) / 2;
200                b = defvalue;
201        }
202        else
203        {
204                linear = false;
205                a = -(maxvalue - defvalue) / (minvalue - defvalue);
206                b = (minvalue * minvalue - 2 * defvalue * minvalue + defvalue * defvalue) / (minvalue + maxvalue - 2 * defvalue);
207                c = (maxvalue * minvalue - defvalue * defvalue) / (minvalue + maxvalue - 2 * defvalue);
208                log_a = log(a);
209        }
210}
211
212double GenePropsOp_Exponential::scale(double value) const
213{
214        if (linear)
215                return a * value + b;
216        else
217                return pow(a, (value + 1)) * b + c;
218}
219
220double GenePropsOp_Exponential::scaleInv(double value) const
221{
222        if (linear)
223                return (value - b) / a;
224        else
225                return -(log_a - log(value / b - c / b)) / log_a;
226}
227
228////////////////////////////////////////////////////////////////////
229
230
231GenePropsOps::~GenePropsOps()
232{
233        delete length;
234        delete curvedness;
235        delete weight;
236        delete friction;
237        delete muscle_power;
238        delete assimilation;
239        delete stamina;
240        delete ingestion;
241        delete twist;
242        delete energy;
243        delete cred;
244        delete cgreen;
245        delete cblue;
246}
247
248GenePropsOps_Old::GenePropsOps_Old()
249{
250        use_normalizebiol4 = true;
251
252        length = new GenePropsOp_Old(0.33, 2.0, GeneProps::standard_values.length, 0.3);
253        weight = new GenePropsOp_Old(0.5, 2.0, GeneProps::standard_values.weight, 0.3);
254        friction = new GenePropsOp_Old(0, 4.0, GeneProps::standard_values.friction, 0.2);
255        curvedness = new GenePropsOp_Old(-2, 2, GeneProps::standard_values.curvedness, 0.25);
256        twist = new GenePropsOp_Old(-M_PI_2, M_PI_2, GeneProps::standard_values.twist, 0.3);
257        energy = new GenePropsOp_Old(0, 10, GeneProps::standard_values.energy, 0.1);
258
259        assimilation = new GenePropsOp_Old(0, 1, GeneProps::standard_values.assimilation, 0.8, 0.4);
260        ingestion = new GenePropsOp_Old(0, 1, GeneProps::standard_values.ingestion, 0.8, 0.4);
261        stamina = new GenePropsOp_Old(0, 1, GeneProps::standard_values.stamina, 0.8, 0.4);
262        muscle_power = new GenePropsOp_Old(0, 1, GeneProps::standard_values.muscle_power, 0.8, 0.4);
263
264        cred = new GenePropsOp_Old(0, 1, GeneProps::standard_values.cred, 0.25);
265        cgreen = new GenePropsOp_Old(0, 1, GeneProps::standard_values.cgreen, 0.25);
266        cblue = new GenePropsOp_Old(0, 1, GeneProps::standard_values.cblue, 0.25);
267}
268
269GenePropsOps_New05::GenePropsOps_New05()
270{
271        use_normalizebiol4 = false;
272        auto fields = { length,curvedness,weight,friction,muscle_power,assimilation,stamina,ingestion,twist,energy,cred,cgreen,cblue };
273        for (auto f : fields)
274        {
275                auto f_gpo = dynamic_cast<GenePropsOp_Old*>(f);
276                if (f_gpo)
277                        f_gpo->change = f_gpo->revchange = 0.5;
278        }
279}
280
281GenePropsOps_Exponential::GenePropsOps_Exponential()
282{
283        length = new GenePropsOp_Exponential(0.33, 2.0, GeneProps::standard_values.length);
284        weight = new GenePropsOp_Exponential(0.5, 2.0, GeneProps::standard_values.weight);
285        friction = new GenePropsOp_Exponential(0, 4.0, GeneProps::standard_values.friction);
286        curvedness = new GenePropsOp_Exponential(-2, 2, GeneProps::standard_values.curvedness);
287        twist = new GenePropsOp_Exponential(-M_PI_2, M_PI_2, GeneProps::standard_values.twist);
288        energy = new GenePropsOp_Exponential(0, 10, GeneProps::standard_values.energy);
289
290        assimilation = new GenePropsOp_Exponential(0, 1, GeneProps::standard_values.assimilation);
291        ingestion = new GenePropsOp_Exponential(0, 1, GeneProps::standard_values.ingestion);
292        stamina = new GenePropsOp_Exponential(0, 1, GeneProps::standard_values.stamina);
293        muscle_power = new GenePropsOp_Exponential(0, 1, GeneProps::standard_values.muscle_power);
294
295        cred = new GenePropsOp_Exponential(0, 1, GeneProps::standard_values.cred);
296        cgreen = new GenePropsOp_Exponential(0, 1, GeneProps::standard_values.cgreen);
297        cblue = new GenePropsOp_Exponential(0, 1, GeneProps::standard_values.cblue);
298}
299
300
301GenePropsOps* GeneProps::standard_ops = NULL;
302GenePropsOps* GeneProps::getStandardOps()
303{
304        if (!standard_ops)
305                standard_ops = new GenePropsOps_New05();
306        return standard_ops;
307}
Note: See TracBrowser for help on using the repository browser.