// This file is a part of Framsticks SDK. http://www.framsticks.com/ // Copyright (C) 1999-2023 Maciej Komosinski and Szymon Ulatowski. // See LICENSE.txt for details. #ifndef _GENEPROPS_H #define _GENEPROPS_H #include #include #define F14_MODIFIERS_VISUAL "DdGgBb" #define F14_MODIFIERS_RARE "EeWwSsAaIi" //An expdef would need to handle many of these properly/specifically to ensure reasonable behavior, and hardly any expdef does. Modifying initial energy of a creature as a result of its genes (Ee) is in general not a good idea, but may make sense in some specific competitive biological simulations. Weight (Ww) works only in water, and in water sinking/going up should usually be caused by real "intentional" activity of a creature, not by its inherited weight. Stamina (Ss) is no longer needed as destructive collisions are not supported, and even if they were, some expdef would need to impose reasonable restrictions on the value of this parameter (e.g. similar to normalizeBiol4()) so there is some cost associated with it, and the specific consequences of destructions should be defined as needed. For assimilation (Aa), there is a dedicated parameter in CreaturesGroup. Ingestion (Ii) influences how fast energy is transferred to Parts of a creature, and optimizing this property may make sense in experiments where energy is present in the environment and can be ingested - if needed, this modifier should be enabled for mutation. #define F14_MODIFIERS "LlRrCcQqFfMm" F14_MODIFIERS_RARE F14_MODIFIERS_VISUAL class GenePropsOp { public: virtual ~GenePropsOp() {} virtual double increase(double value) const = 0; virtual double decrease(double value) const = 0; void apply(double &value, char modif) const; }; class GenePropsOp_Legacy : public GenePropsOp { double minvalue, maxvalue, defvalue, change, revchange; public: GenePropsOp_Legacy(double minvalue, double maxvalue, double defvalue, double change, double revchange = -1); double increase(double value) const; double decrease(double value) const; friend class GenePropsOps_AllChange05; }; class GenePropsOp_NormalizedAndScaled : public GenePropsOp { GenePropsOp_Legacy normalized; public: GenePropsOp_NormalizedAndScaled(double change) :normalized(-1, 1, 0, change) {} virtual double scale(double value) const { return value; } virtual double scaleInv(double value) const { return value; } double increase(double value) const { return scale(normalized.increase(scaleInv(value))); } double decrease(double value) const { return scale(normalized.decrease(scaleInv(value))); } }; class GenePropsOp_Exponential : public GenePropsOp_NormalizedAndScaled { double a, b, c; double log_a; bool linear; public: GenePropsOp_Exponential(double minvalue, double maxvalue, double defvalue, double change = 0.5); double scale(double) const; double scaleInv(double) const; }; class GenePropsOps { public: ~GenePropsOps(); GenePropsOp* length; GenePropsOp* curvedness; GenePropsOp* weight; GenePropsOp* friction; GenePropsOp* muscle_power; GenePropsOp* assimilation; GenePropsOp* stamina; GenePropsOp* ingestion; GenePropsOp* twist; GenePropsOp* energy; GenePropsOp* cred, *cgreen, *cblue; bool use_normalizebiol4; }; class GenePropsOps_Legacy : public GenePropsOps { public: GenePropsOps_Legacy(); }; /** * Just as legacy (before 2023-06), but the influence of each modifier is uniform and simpler (no normalizeBiol4()). * This is what is currently used in Framsticks. */ class GenePropsOps_AllChange05 : public GenePropsOps_Legacy { public: GenePropsOps_AllChange05(); }; /** * Just an experiment with a different scaling of the influence of individual modifier characters to cover * the entire range of parameter values. After investigations we decided that it does not * provide any advantages over "AllChange05". */ class GenePropsOps_Exponential : public GenePropsOps { public: GenePropsOps_Exponential(); }; /** * Contains physical, biological and other properties of a Part and a Joint (as handled * by the f1 and f4 encodings), except for rotation. The constructor initializes properties with * default values. In order to change a property, the executeModifier() method * should be called. Modification of length, curvedness and twist properties * usually affects further sticks, so new sticks should have properties of * parents (prop) modified with the prop.propagateAlong() method. * "Biological" properties (assimilation, stamina, muscle strength and * ingestion) can be normalized after modification with normalizeBiol4(). * See also geneprops_test.cpp */ struct GeneProps { public: double length; ///