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

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

Changed the default behavior of modifier genes in f1 and f4 to GenePropsOps_New05: the coefficient of change is set to 0.5 for all properties and for both increase and decrease, which ensures an equal distribution of target property values with a relatively fast convergence to minimal and maximal values; the four "biological" properties are no longer aggregated and normalized

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