diff options
Diffstat (limited to 'source/gameengine/GameLogic/SCA_RandomActuator.cpp')
-rw-r--r-- | source/gameengine/GameLogic/SCA_RandomActuator.cpp | 543 |
1 files changed, 0 insertions, 543 deletions
diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp deleted file mode 100644 index 121be5f003e..00000000000 --- a/source/gameengine/GameLogic/SCA_RandomActuator.cpp +++ /dev/null @@ -1,543 +0,0 @@ -/* - * Set random/camera stuff - * - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file gameengine/GameLogic/SCA_RandomActuator.cpp - * \ingroup gamelogic - */ - - -#include <stddef.h> -#include <math.h> - -#include "EXP_BoolValue.h" -#include "EXP_IntValue.h" -#include "EXP_FloatValue.h" -#include "SCA_IActuator.h" -#include "SCA_RandomActuator.h" -#include "MT_Transform.h" - -/* ------------------------------------------------------------------------- */ -/* Native functions */ -/* ------------------------------------------------------------------------- */ - -SCA_RandomActuator::SCA_RandomActuator(SCA_IObject *gameobj, - long seed, - SCA_RandomActuator::KX_RANDOMACT_MODE mode, - float para1, - float para2, - const STR_String &propName) - : SCA_IActuator(gameobj, KX_ACT_RANDOM), - m_propname(propName), - m_parameter1(para1), - m_parameter2(para2), - m_distribution(mode) -{ - m_base = new SCA_RandomNumberGenerator(seed); - m_counter = 0; - enforceConstraints(); -} - - - -SCA_RandomActuator::~SCA_RandomActuator() -{ - m_base->Release(); -} - - - -CValue* SCA_RandomActuator::GetReplica() -{ - SCA_RandomActuator* replica = new SCA_RandomActuator(*this); - // replication just copy the m_base pointer => common random generator - replica->ProcessReplica(); - return replica; -} - -void SCA_RandomActuator::ProcessReplica() -{ - SCA_IActuator::ProcessReplica(); - // increment reference count so that we can release the generator at the end - m_base->AddRef(); -} - - - -bool SCA_RandomActuator::Update() -{ - //bool result = false; /*unused*/ - bool bNegativeEvent = IsNegativeEvent(); - - RemoveAllEvents(); - - - CValue *tmpval = NULL; - - if (bNegativeEvent) - return false; // do nothing on negative events - - switch (m_distribution) { - case KX_RANDOMACT_BOOL_CONST: { - /* un petit peu filthy */ - bool res = !(m_parameter1 < 0.5); - tmpval = new CBoolValue(res); - } - break; - case KX_RANDOMACT_BOOL_UNIFORM: { - /* flip a coin */ - bool res; - if (m_counter > 31) { - m_previous = m_base->Draw(); - res = ((m_previous & 0x1) == 0); - m_counter = 1; - } else { - res = (((m_previous >> m_counter) & 0x1) == 0); - m_counter++; - } - tmpval = new CBoolValue(res); - } - break; - case KX_RANDOMACT_BOOL_BERNOUILLI: { - /* 'percentage' */ - bool res; - res = (m_base->DrawFloat() < m_parameter1); - tmpval = new CBoolValue(res); - } - break; - case KX_RANDOMACT_INT_CONST: { - /* constant */ - tmpval = new CIntValue((int) floor(m_parameter1)); - } - break; - case KX_RANDOMACT_INT_UNIFORM: { - /* uniform (toss a die) */ - int res; - /* The [0, 1] interval is projected onto the [min, max+1] domain, */ - /* and then rounded. */ - res = (int)floor( ((m_parameter2 - m_parameter1 + 1) * m_base->DrawFloat()) + m_parameter1); - tmpval = new CIntValue(res); - } - break; - case KX_RANDOMACT_INT_POISSON: { - /* poisson (queues) */ - /* If x_1, x_2, ... is a sequence of random numbers with uniform */ - /* distribution between zero and one, k is the first integer for */ - /* which the product x_1*x_2*...*x_k < exp(-\lamba). */ - float a, b; - int res = 0; - /* The - sign is important here! The number to test for, a, must be */ - /* between 0 and 1. */ - a = exp(-m_parameter1); - /* a quickly reaches 0.... so we guard explicitly for that. */ - if (a < FLT_MIN) a = FLT_MIN; - b = m_base->DrawFloat(); - while (b >= a) { - b = b * m_base->DrawFloat(); - res++; - }; - tmpval = new CIntValue(res); - } - break; - case KX_RANDOMACT_FLOAT_CONST: { - /* constant */ - tmpval = new CFloatValue(m_parameter1); - } - break; - case KX_RANDOMACT_FLOAT_UNIFORM: { - float res = ((m_parameter2 - m_parameter1) * m_base->DrawFloat()) + m_parameter1; - tmpval = new CFloatValue(res); - } - break; - case KX_RANDOMACT_FLOAT_NORMAL: { - /* normal (big numbers): para1 = mean, para2 = std dev */ - - /* 070301 - nzc: Changed the termination condition. I think I - * made a small mistake here, but it only affects distro's where - * the seed equals 0. In that case, the algorithm locks. Let's - * just guard that case separately. - */ - - float x = 0.0, y = 0.0, s = 0.0, t = 0.0; - if (m_base->GetSeed() == 0) { - /* 070301 - nzc: Just taking the mean here seems reasonable. */ - tmpval = new CFloatValue(m_parameter1); - } - else { - /* 070301 - nzc - * Now, with seed != 0, we will most assuredly get some - * sensible values. The termination condition states two - * things: - * 1. s >= 0 is not allowed: to prevent the distro from - * getting a bias towards high values. This is a small - * correction, really, and might also be left out. - * 2. s == 0 is not allowed: to prevent a division by zero - * when renormalising the drawn value to the desired - * distribution shape. As a side effect, the distro will - * never yield the exact mean. - * I am not sure whether this is consistent, since the error - * cause by #2 is of the same magnitude as the one - * prevented by #1. The error introduced into the SD will be - * improved, though. By how much? Hard to say... If you like - * the maths, feel free to analyse. Be aware that this is - * one of the really old standard algorithms. I think the - * original came in Fortran, was translated to Pascal, and - * then someone came up with the C code. My guess it that - * this will be quite sufficient here. - */ - do { - x = 2.0f * m_base->DrawFloat() - 1.0f; - y = 2.0f * m_base->DrawFloat() - 1.0f; - s = x * x + y * y; - } while ((s >= 1.0f) || (s == 0.0f)); - t = x * sqrtf((-2.0 * log(s)) / s); - tmpval = new CFloatValue(m_parameter1 + m_parameter2 * t); - } - } - break; - case KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL: { - /* 1st order fall-off. I am very partial to using the half-life as */ - /* controlling parameter. Using the 'normal' exponent is not very */ - /* intuitive... */ - /* tmpval = new CFloatValue( (1.0 / m_parameter1) */ - tmpval = new CFloatValue((m_parameter1) * (-log(1.0 - m_base->DrawFloat()))); - - } - break; - default: - { - /* unknown distribution... */ - static bool randomWarning = false; - if (!randomWarning) { - randomWarning = true; - std::cout << "RandomActuator '" << GetName() << "' has an unknown distribution." << std::endl; - } - return false; - } - } - - /* Round up: assign it */ - CValue *prop = GetParent()->GetProperty(m_propname); - if (prop) { - prop->SetValue(tmpval); - } - tmpval->Release(); - - return false; -} - -void SCA_RandomActuator::enforceConstraints() -{ - /* The constraints that are checked here are the ones fundamental to */ - /* the various distributions. Limitations of the algorithms are checked */ - /* elsewhere (or they should be... ). */ - switch (m_distribution) { - case KX_RANDOMACT_BOOL_CONST: - case KX_RANDOMACT_BOOL_UNIFORM: - case KX_RANDOMACT_INT_CONST: - case KX_RANDOMACT_INT_UNIFORM: - case KX_RANDOMACT_FLOAT_UNIFORM: - case KX_RANDOMACT_FLOAT_CONST: - ; /* Nothing to be done here. We allow uniform distro's to have */ - /* 'funny' domains, i.e. max < min. This does not give problems. */ - break; - case KX_RANDOMACT_BOOL_BERNOUILLI: - /* clamp to [0, 1] */ - if (m_parameter1 < 0.0) { - m_parameter1 = 0.0; - } else if (m_parameter1 > 1.0) { - m_parameter1 = 1.0; - } - break; - case KX_RANDOMACT_INT_POISSON: - /* non-negative */ - if (m_parameter1 < 0.0) { - m_parameter1 = 0.0; - } - break; - case KX_RANDOMACT_FLOAT_NORMAL: - /* standard dev. is non-negative */ - if (m_parameter2 < 0.0) { - m_parameter2 = 0.0; - } - break; - case KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL: - /* halflife must be non-negative */ - if (m_parameter1 < 0.0) { - m_parameter1 = 0.0; - } - break; - default: - ; /* unknown distribution... */ - } -} - -#ifdef WITH_PYTHON - -/* ------------------------------------------------------------------------- */ -/* Python functions */ -/* ------------------------------------------------------------------------- */ - -/* Integration hooks ------------------------------------------------------- */ -PyTypeObject SCA_RandomActuator::Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "SCA_RandomActuator", - sizeof(PyObjectPlus_Proxy), - 0, - py_base_dealloc, - 0, - 0, - 0, - 0, - py_base_repr, - 0,0,0,0,0,0,0,0,0, - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - 0,0,0,0,0,0,0, - Methods, - 0, - 0, - &SCA_IActuator::Type, - 0,0,0,0,0,0, - py_base_new -}; - -PyMethodDef SCA_RandomActuator::Methods[] = { - KX_PYMETHODTABLE(SCA_RandomActuator, setBoolConst), - KX_PYMETHODTABLE_NOARGS(SCA_RandomActuator, setBoolUniform), - KX_PYMETHODTABLE(SCA_RandomActuator, setBoolBernouilli), - - KX_PYMETHODTABLE(SCA_RandomActuator, setIntConst), - KX_PYMETHODTABLE(SCA_RandomActuator, setIntUniform), - KX_PYMETHODTABLE(SCA_RandomActuator, setIntPoisson), - - KX_PYMETHODTABLE(SCA_RandomActuator, setFloatConst), - KX_PYMETHODTABLE(SCA_RandomActuator, setFloatUniform), - KX_PYMETHODTABLE(SCA_RandomActuator, setFloatNormal), - KX_PYMETHODTABLE(SCA_RandomActuator, setFloatNegativeExponential), - {NULL,NULL} //Sentinel -}; - -PyAttributeDef SCA_RandomActuator::Attributes[] = { - KX_PYATTRIBUTE_FLOAT_RO("para1",SCA_RandomActuator,m_parameter1), - KX_PYATTRIBUTE_FLOAT_RO("para2",SCA_RandomActuator,m_parameter2), - KX_PYATTRIBUTE_ENUM_RO("distribution",SCA_RandomActuator,m_distribution), - KX_PYATTRIBUTE_STRING_RW_CHECK("propName",0,MAX_PROP_NAME,false,SCA_RandomActuator,m_propname,CheckProperty), - KX_PYATTRIBUTE_RW_FUNCTION("seed",SCA_RandomActuator,pyattr_get_seed,pyattr_set_seed), - { NULL } //Sentinel -}; - -PyObject *SCA_RandomActuator::pyattr_get_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) -{ - SCA_RandomActuator* act = static_cast<SCA_RandomActuator*>(self); - return PyLong_FromLong(act->m_base->GetSeed()); -} - -int SCA_RandomActuator::pyattr_set_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) -{ - SCA_RandomActuator* act = static_cast<SCA_RandomActuator*>(self); - if (PyLong_Check(value)) { - act->m_base->SetSeed(PyLong_AsLong(value)); - return PY_SET_ATTR_SUCCESS; - } - else { - PyErr_SetString(PyExc_TypeError, "actuator.seed = int: Random Actuator, expected an integer"); - return PY_SET_ATTR_FAIL; - } -} - -/* 11. setBoolConst */ -KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setBoolConst, -"setBoolConst(value)\n" -"\t- value: 0 or 1\n" -"\tSet this generator to produce a constant boolean value.\n") -{ - int paraArg; - if (!PyArg_ParseTuple(args, "i:setBoolConst", ¶Arg)) { - return NULL; - } - - m_distribution = KX_RANDOMACT_BOOL_CONST; - m_parameter1 = (paraArg) ? 1.0 : 0.0; - - Py_RETURN_NONE; -} -/* 12. setBoolUniform, */ -KX_PYMETHODDEF_DOC_NOARGS(SCA_RandomActuator, setBoolUniform, -"setBoolUniform()\n" -"\tSet this generator to produce true and false, each with 50%% chance of occurring\n") -{ - /* no args */ - m_distribution = KX_RANDOMACT_BOOL_UNIFORM; - enforceConstraints(); - Py_RETURN_NONE; -} -/* 13. setBoolBernouilli, */ -KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setBoolBernouilli, -"setBoolBernouilli(value)\n" -"\t- value: a float between 0 and 1\n" -"\tReturn false value * 100%% of the time.\n") -{ - float paraArg; - if (!PyArg_ParseTuple(args, "f:setBoolBernouilli", ¶Arg)) { - return NULL; - } - - m_distribution = KX_RANDOMACT_BOOL_BERNOUILLI; - m_parameter1 = paraArg; - enforceConstraints(); - Py_RETURN_NONE; -} -/* 14. setIntConst,*/ -KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setIntConst, -"setIntConst(value)\n" -"\t- value: integer\n" -"\tAlways return value\n") -{ - int paraArg; - if (!PyArg_ParseTuple(args, "i:setIntConst", ¶Arg)) { - return NULL; - } - - m_distribution = KX_RANDOMACT_INT_CONST; - m_parameter1 = paraArg; - enforceConstraints(); - Py_RETURN_NONE; -} -/* 15. setIntUniform,*/ -KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setIntUniform, -"setIntUniform(lower_bound, upper_bound)\n" -"\t- lower_bound: integer\n" -"\t- upper_bound: integer\n" -"\tReturn a random integer between lower_bound and\n" -"\tupper_bound. The boundaries are included.\n") -{ - int paraArg1, paraArg2; - if (!PyArg_ParseTuple(args, "ii:setIntUniform", ¶Arg1, ¶Arg2)) { - return NULL; - } - - m_distribution = KX_RANDOMACT_INT_UNIFORM; - m_parameter1 = paraArg1; - m_parameter2 = paraArg2; - enforceConstraints(); - Py_RETURN_NONE; -} -/* 16. setIntPoisson, */ -KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setIntPoisson, -"setIntPoisson(value)\n" -"\t- value: float\n" -"\tReturn a Poisson-distributed number. This performs a series\n" -"\tof Bernouilli tests with parameter value. It returns the\n" -"\tnumber of tries needed to achieve succes.\n") -{ - float paraArg; - if (!PyArg_ParseTuple(args, "f:setIntPoisson", ¶Arg)) { - return NULL; - } - - m_distribution = KX_RANDOMACT_INT_POISSON; - m_parameter1 = paraArg; - enforceConstraints(); - Py_RETURN_NONE; -} -/* 17. setFloatConst */ -KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setFloatConst, -"setFloatConst(value)\n" -"\t- value: float\n" -"\tAlways return value\n") -{ - float paraArg; - if (!PyArg_ParseTuple(args, "f:setFloatConst", ¶Arg)) { - return NULL; - } - - m_distribution = KX_RANDOMACT_FLOAT_CONST; - m_parameter1 = paraArg; - enforceConstraints(); - Py_RETURN_NONE; -} -/* 18. setFloatUniform, */ -KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setFloatUniform, -"setFloatUniform(lower_bound, upper_bound)\n" -"\t- lower_bound: float\n" -"\t- upper_bound: float\n" -"\tReturn a random integer between lower_bound and\n" -"\tupper_bound.\n") -{ - float paraArg1, paraArg2; - if (!PyArg_ParseTuple(args, "ff:setFloatUniform", ¶Arg1, ¶Arg2)) { - return NULL; - } - - m_distribution = KX_RANDOMACT_FLOAT_UNIFORM; - m_parameter1 = paraArg1; - m_parameter2 = paraArg2; - enforceConstraints(); - Py_RETURN_NONE; -} -/* 19. setFloatNormal, */ -KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setFloatNormal, -"setFloatNormal(mean, standard_deviation)\n" -"\t- mean: float\n" -"\t- standard_deviation: float\n" -"\tReturn normal-distributed numbers. The average is mean, and the\n" -"\tdeviation from the mean is characterized by standard_deviation.\n") -{ - float paraArg1, paraArg2; - if (!PyArg_ParseTuple(args, "ff:setFloatNormal", ¶Arg1, ¶Arg2)) { - return NULL; - } - - m_distribution = KX_RANDOMACT_FLOAT_NORMAL; - m_parameter1 = paraArg1; - m_parameter2 = paraArg2; - enforceConstraints(); - Py_RETURN_NONE; -} -/* 20. setFloatNegativeExponential, */ -KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setFloatNegativeExponential, -"setFloatNegativeExponential(half_life)\n" -"\t- half_life: float\n" -"\tReturn negative-exponentially distributed numbers. The half-life 'time'\n" -"\tis characterized by half_life.\n") -{ - float paraArg; - if (!PyArg_ParseTuple(args, "f:setFloatNegativeExponential", ¶Arg)) { - return NULL; - } - - m_distribution = KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL; - m_parameter1 = paraArg; - enforceConstraints(); - Py_RETURN_NONE; -} - -#endif - -/* eof */ |