00001
00006
00007 #include "BoolValue.h"
00008 #include "IntValue.h"
00009 #include "FloatValue.h"
00010 #include "SCA_IActuator.h"
00011 #include "SCA_RandomActuator.h"
00012 #include "math.h"
00013
00014 #include "MT_Transform.h"
00015
00016
00017
00018
00019 SCA_RandomActuator::SCA_RandomActuator(SCA_IObject *gameobj,
00020 long seed,
00021 SCA_RandomActuator::KX_RANDOMACT_MODE mode,
00022 float para1,
00023 float para2,
00024 const CCString &propName,
00025 PyTypeObject* T)
00026 : SCA_IActuator(gameobj, T),
00027 m_distribution(mode),
00028 m_propname(propName),
00029 m_parameter1(para1),
00030 m_parameter2(para2)
00031 {
00032 m_base = new SCA_RandomNumberGenerator(seed);
00033 m_counter = 0;
00034 enforceConstraints();
00035 }
00036
00037 SCA_RandomActuator::~SCA_RandomActuator() { }
00038
00039 bool SCA_RandomActuator::Update(double curtime,double deltatime)
00040 {
00041 bool result = false;
00042 bool bNegativeEvent = IsNegativeEvent();
00043 CValue *tmpval;
00044
00045 if (bNegativeEvent)
00046 return false;
00047
00048 switch (m_distribution) {
00049 case KX_RANDOMACT_BOOL_CONST: {
00050
00051 bool res = !(m_parameter1 < 0.5);
00052 tmpval = new CBoolValue(res);
00053 }
00054 break;
00055 case KX_RANDOMACT_BOOL_UNIFORM: {
00056
00057 bool res;
00058 if (m_counter > 31) {
00059 m_previous = m_base->Draw();
00060 res = ((m_previous & 0x1) == 0);
00061 m_counter = 1;
00062 } else {
00063 res = (((m_previous >> m_counter) & 0x1) == 0);
00064 m_counter++;
00065 }
00066 tmpval = new CBoolValue(res);
00067 }
00068 break;
00069 case KX_RANDOMACT_BOOL_BERNOUILLI: {
00070
00071 bool res;
00072 res = (m_base->DrawFloat() < m_parameter1);
00073 tmpval = new CBoolValue(res);
00074 }
00075 break;
00076 case KX_RANDOMACT_INT_CONST: {
00077
00078 tmpval = new CIntValue((int) floor(m_parameter1));
00079 }
00080 break;
00081 case KX_RANDOMACT_INT_UNIFORM: {
00082
00083 int res;
00084
00085
00086 res = (int) floor( ((m_parameter2 - m_parameter1 + 1) * m_base->DrawFloat())
00087 + m_parameter1);
00088 tmpval = new CIntValue(res);
00089 }
00090 break;
00091 case KX_RANDOMACT_INT_POISSON: {
00092
00093
00094
00095
00096 float a = 0.0, b = 0.0;
00097 int res = 0;
00098
00099
00100 a = exp(-m_parameter1);
00101
00102 if (a < FLT_MIN) a = FLT_MIN;
00103 b = m_base->DrawFloat();
00104 while (b >= a) {
00105 b = b * m_base->DrawFloat();
00106 res++;
00107 };
00108 tmpval = new CIntValue(res);
00109 }
00110 break;
00111 case KX_RANDOMACT_FLOAT_CONST: {
00112
00113 tmpval = new CFloatValue(m_parameter1);
00114 }
00115 break;
00116 case KX_RANDOMACT_FLOAT_UNIFORM: {
00117 float res = ((m_parameter2 - m_parameter1) * m_base->DrawFloat())
00118 + m_parameter1;
00119 tmpval = new CFloatValue(res);
00120 }
00121 break;
00122 case KX_RANDOMACT_FLOAT_NORMAL: {
00123
00124 float x = 0.0, y = 0.0, s = 0.0, t = 0.0;
00125 do {
00126 x = 2.0 * m_base->DrawFloat() - 1.0;
00127 y = 2.0 * m_base->DrawFloat() - 1.0;
00128 s = x*x + y*y;
00129 } while ( (s >= 1.0) || (s == 0.0) );
00130 t = x * sqrt( (-2.0 * log(s)) / s);
00131 tmpval = new CFloatValue(m_parameter1 + m_parameter2 * t);
00132 }
00133 break;
00134 case KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL: {
00135
00136
00137
00138
00139 tmpval = new CFloatValue( (m_parameter1)
00140 * (-log(1.0 - m_base->DrawFloat())) );
00141
00142 }
00143 break;
00144 default:
00145 ;
00146 }
00147
00148
00149 CValue *prop = GetParent()->GetProperty(m_propname);
00150 if (prop) {
00151 prop->SetValue(tmpval);
00152 }
00153 tmpval->Release();
00154
00155 return false;
00156 }
00157
00158 void SCA_RandomActuator::enforceConstraints() {
00159
00160
00161
00162 switch (m_distribution) {
00163 case KX_RANDOMACT_BOOL_CONST:
00164 case KX_RANDOMACT_BOOL_UNIFORM:
00165 case KX_RANDOMACT_INT_CONST:
00166 case KX_RANDOMACT_INT_UNIFORM:
00167 case KX_RANDOMACT_FLOAT_UNIFORM:
00168 case KX_RANDOMACT_FLOAT_CONST:
00169 ;
00170
00171 break;
00172 case KX_RANDOMACT_BOOL_BERNOUILLI:
00173
00174 if (m_parameter1 < 0.0) {
00175 m_parameter1 = 0.0;
00176 } else if (m_parameter1 > 1.0) {
00177 m_parameter1 = 1.0;
00178 }
00179 break;
00180 case KX_RANDOMACT_INT_POISSON:
00181
00182 if (m_parameter1 < 0.0) {
00183 m_parameter1 = 0.0;
00184 }
00185 break;
00186 case KX_RANDOMACT_FLOAT_NORMAL:
00187
00188 if (m_parameter2 < 0.0) {
00189 m_parameter2 = 0.0;
00190 }
00191 break;
00192 case KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL:
00193
00194 if (m_parameter1 < 0.0) {
00195 m_parameter1 = 0.0;
00196 }
00197 break;
00198 default:
00199 ;
00200 }
00201 }
00202
00203
00204
00205
00206
00207
00208 PyTypeObject SCA_RandomActuator::Type = {
00209 PyObject_HEAD_INIT(&PyType_Type)
00210 0,
00211 "SCA_RandomActuator",
00212 sizeof(SCA_RandomActuator),
00213 0,
00214 PyDestructor,
00215 0,
00216 __getattr,
00217 __setattr,
00218 0,
00219 __repr,
00220 0,
00221 0,
00222 0,
00223 0,
00224 0
00225 };
00226
00227 PyParentObject SCA_RandomActuator::Parents[] = {
00228 &SCA_RandomActuator::Type,
00229 &SCA_IActuator::Type,
00230 &SCA_ILogicBrick::Type,
00231 &CValue::Type,
00232 NULL
00233 };
00234
00235 PyMethodDef SCA_RandomActuator::Methods[] = {
00236 {"setSeed", (PyCFunction) SCA_RandomActuator::sPySetSeed, METH_VARARGS, SetSeed_doc},
00237 {"getSeed", (PyCFunction) SCA_RandomActuator::sPyGetSeed, METH_VARARGS, GetSeed_doc},
00238 {"getPara1", (PyCFunction) SCA_RandomActuator::sPyGetPara1, METH_VARARGS, GetPara1_doc},
00239 {"getPara2", (PyCFunction) SCA_RandomActuator::sPyGetPara2, METH_VARARGS, GetPara2_doc},
00240 {"getDistribution", (PyCFunction) SCA_RandomActuator::sPyGetDistribution, METH_VARARGS, GetDistribution_doc},
00241 {"setProperty", (PyCFunction) SCA_RandomActuator::sPySetProperty, METH_VARARGS, SetProperty_doc},
00242 {"getProperty", (PyCFunction) SCA_RandomActuator::sPyGetProperty, METH_VARARGS, GetProperty_doc},
00243 {"setBoolConst", (PyCFunction) SCA_RandomActuator::sPySetBoolConst, METH_VARARGS, SetBoolConst_doc},
00244 {"setBoolUniform", (PyCFunction) SCA_RandomActuator::sPySetBoolUniform, METH_VARARGS, SetBoolUniform_doc},
00245 {"setBoolBernouilli",(PyCFunction) SCA_RandomActuator::sPySetBoolBernouilli, METH_VARARGS, SetBoolBernouilli_doc},
00246 {"setIntConst", (PyCFunction) SCA_RandomActuator::sPySetIntConst, METH_VARARGS, SetIntConst_doc},
00247 {"setIntUniform", (PyCFunction) SCA_RandomActuator::sPySetIntUniform, METH_VARARGS, SetIntUniform_doc},
00248 {"setIntPoisson", (PyCFunction) SCA_RandomActuator::sPySetIntPoisson, METH_VARARGS, SetIntPoisson_doc},
00249 {"setFloatConst", (PyCFunction) SCA_RandomActuator::sPySetFloatConst, METH_VARARGS, SetFloatConst_doc},
00250 {"setFloatUniform", (PyCFunction) SCA_RandomActuator::sPySetFloatUniform, METH_VARARGS, SetFloatUniform_doc},
00251 {"setFloatNormal", (PyCFunction) SCA_RandomActuator::sPySetFloatNormal, METH_VARARGS, SetFloatNormal_doc},
00252 {"setFloatNegativeExponential", (PyCFunction) SCA_RandomActuator::sPySetFloatNegativeExponential, METH_VARARGS, SetFloatNegativeExponential_doc},
00253 {NULL,NULL}
00254 };
00255
00256 PyObject* SCA_RandomActuator::_getattr(char* attr) {
00257 _getattr_up(SCA_IActuator);
00258 }
00259
00260
00261 char SCA_RandomActuator::SetSeed_doc[] =
00262 "setSeed(seed)\n"
00263 "\t- seed: integer\n"
00264 "\tSet the initial seed of the generator. Equal seeds produce\n"
00265 "\tequal series. If the seed is 0, the generator will produce\n"
00266 "\tthe same value on every call.\n";
00267 PyObject* SCA_RandomActuator::PySetSeed(PyObject* self, PyObject* args, PyObject* kwds) {
00268 long seedArg;
00269 if(!PyArg_ParseTuple(args, "i", &seedArg)) {
00270 return NULL;
00271 }
00272
00273 m_base->SetSeed(seedArg);
00274
00275 Py_Return;
00276 }
00277
00278 char SCA_RandomActuator::GetSeed_doc[] =
00279 "getSeed()\n"
00280 "\tReturns the initial seed of the generator. Equal seeds produce\n"
00281 "\tequal series.\n";
00282 PyObject* SCA_RandomActuator::PyGetSeed(PyObject* self, PyObject* args, PyObject* kwds) {
00283 return PyInt_FromLong(m_base->GetSeed());
00284 }
00285
00286
00287 char SCA_RandomActuator::GetPara1_doc[] =
00288 "getPara1()\n"
00289 "\tReturns the first parameter of the active distribution. Refer\n"
00290 "\tto the documentation of the generator types for the meaning\n"
00291 "\tof this value.";
00292 PyObject* SCA_RandomActuator::PyGetPara1(PyObject* self, PyObject* args, PyObject* kwds) {
00293 return PyFloat_FromDouble(m_parameter1);
00294 }
00295
00296
00297 char SCA_RandomActuator::GetPara2_doc[] =
00298 "getPara2()\n"
00299 "\tReturns the first parameter of the active distribution. Refer\n"
00300 "\tto the documentation of the generator types for the meaning\n"
00301 "\tof this value.";
00302 PyObject* SCA_RandomActuator::PyGetPara2(PyObject* self, PyObject* args, PyObject* kwds) {
00303 return PyFloat_FromDouble(m_parameter2);
00304 }
00305
00306
00307 char SCA_RandomActuator::GetDistribution_doc[] =
00308 "getDistribution()\n"
00309 "\tReturns the type of the active distribution.\n";
00310 PyObject* SCA_RandomActuator::PyGetDistribution(PyObject* self, PyObject* args, PyObject* kwds) {
00311 return PyInt_FromLong(m_distribution);
00312 }
00313
00314
00315 char SCA_RandomActuator::SetProperty_doc[] =
00316 "setProperty(name)\n"
00317 "\t- name: string\n"
00318 "\tSet the property to which the random value is assigned. If the \n"
00319 "\tgenerator and property types do not match, the assignment is ignored.\n";
00320 PyObject* SCA_RandomActuator::PySetProperty(PyObject* self, PyObject* args, PyObject* kwds) {
00321 char *nameArg;
00322 if (!PyArg_ParseTuple(args, "s", &nameArg)) {
00323 return NULL;
00324 }
00325
00326 CValue* prop = GetParent()->FindIdentifier(nameArg);
00327
00328 if (prop) {
00329 m_propname = nameArg;
00330 } else {
00331 ;
00332 }
00333
00334 Py_Return;
00335 }
00336
00337 char SCA_RandomActuator::GetProperty_doc[] =
00338 "getProperty(name)\n"
00339 "\tReturn the property to which the random value is assigned. If the \n"
00340 "\tgenerator and property types do not match, the assignment is ignored.\n";
00341 PyObject* SCA_RandomActuator::PyGetProperty(PyObject* self, PyObject* args, PyObject* kwds) {
00342 return PyString_FromString(m_propname);
00343 }
00344
00345
00346 char SCA_RandomActuator::SetBoolConst_doc[] =
00347 "setBoolConst(value)\n"
00348 "\t- value: 0 or 1\n"
00349 "\tSet this generator to produce a constant boolean value.\n";
00350 PyObject* SCA_RandomActuator::PySetBoolConst(PyObject* self,
00351 PyObject* args,
00352 PyObject* kwds) {
00353 int paraArg;
00354 if(!PyArg_ParseTuple(args, "i", ¶Arg)) {
00355 return NULL;
00356 }
00357
00358 m_distribution = KX_RANDOMACT_BOOL_CONST;
00359 if (paraArg == KX_TRUE) {
00360 m_parameter1 = 1;
00361 }
00362
00363 Py_Return;
00364 }
00365
00366 char SCA_RandomActuator::SetBoolUniform_doc[] =
00367 "setBoolUniform()\n"
00368 "\tSet this generator to produce true and false, each with 50%% chance of occuring\n";
00369 PyObject* SCA_RandomActuator::PySetBoolUniform(PyObject* self,
00370 PyObject* args,
00371 PyObject* kwds) {
00372
00373 m_distribution = KX_RANDOMACT_BOOL_UNIFORM;
00374 enforceConstraints();
00375 Py_Return;
00376 }
00377
00378 char SCA_RandomActuator::SetBoolBernouilli_doc[] =
00379 "setBoolBernouilli(value)\n"
00380 "\t- value: a float between 0 and 1\n"
00381 "\tReturn false value * 100%% of the time.\n";
00382 PyObject* SCA_RandomActuator::PySetBoolBernouilli(PyObject* self,
00383 PyObject* args,
00384 PyObject* kwds) {
00385 float paraArg;
00386 if(!PyArg_ParseTuple(args, "f", ¶Arg)) {
00387 return NULL;
00388 }
00389
00390 m_distribution = KX_RANDOMACT_BOOL_CONST;
00391 m_parameter1 = paraArg;
00392 enforceConstraints();
00393 Py_Return;
00394 }
00395
00396 char SCA_RandomActuator::SetIntConst_doc[] =
00397 "setIntConst(value)\n"
00398 "\t- value: integer\n"
00399 "\tAlways return value\n";
00400 PyObject* SCA_RandomActuator::PySetIntConst(PyObject* self,
00401 PyObject* args,
00402 PyObject* kwds) {
00403 int paraArg;
00404 if(!PyArg_ParseTuple(args, "i", ¶Arg)) {
00405 return NULL;
00406 }
00407
00408 m_distribution = KX_RANDOMACT_INT_CONST;
00409 m_parameter1 = paraArg;
00410 enforceConstraints();
00411 Py_Return;
00412 }
00413
00414 char SCA_RandomActuator::SetIntUniform_doc[] =
00415 "setIntUniform(lower_bound, upper_bound)\n"
00416 "\t- lower_bound: integer\n"
00417 "\t- upper_bound: integer\n"
00418 "\tReturn a random integer between lower_bound and\n"
00419 "\tupper_bound. The boundaries are included.\n";
00420 PyObject* SCA_RandomActuator::PySetIntUniform(PyObject* self,
00421 PyObject* args,
00422 PyObject* kwds) {
00423 int paraArg1, paraArg2;
00424 if(!PyArg_ParseTuple(args, "ii", ¶Arg1, ¶Arg2)) {
00425 return NULL;
00426 }
00427
00428 m_distribution = KX_RANDOMACT_INT_UNIFORM;
00429 m_parameter1 = paraArg1;
00430 m_parameter2 = paraArg2;
00431 enforceConstraints();
00432 Py_Return;
00433 }
00434
00435 char SCA_RandomActuator::SetIntPoisson_doc[] =
00436 "setIntPoisson(value)\n"
00437 "\t- value: float\n"
00438 "\tReturn a Poisson-distributed number. This performs a series\n"
00439 "\tof Bernouilli tests with parameter value. It returns the\n"
00440 "\tnumber of tries needed to achieve succes.\n";
00441 PyObject* SCA_RandomActuator::PySetIntPoisson(PyObject* self,
00442 PyObject* args,
00443 PyObject* kwds) {
00444 float paraArg;
00445 if(!PyArg_ParseTuple(args, "f", ¶Arg)) {
00446 return NULL;
00447 }
00448
00449 m_distribution = KX_RANDOMACT_INT_POISSON;
00450 m_parameter1 = paraArg;
00451 enforceConstraints();
00452 Py_Return;
00453 }
00454
00455 char SCA_RandomActuator::SetFloatConst_doc[] =
00456 "setFloatConst(value)\n"
00457 "\t- value: float\n"
00458 "\tAlways return value\n";
00459 PyObject* SCA_RandomActuator::PySetFloatConst(PyObject* self,
00460 PyObject* args,
00461 PyObject* kwds) {
00462 float paraArg;
00463 if(!PyArg_ParseTuple(args, "f", ¶Arg)) {
00464 return NULL;
00465 }
00466
00467 m_distribution = KX_RANDOMACT_FLOAT_CONST;
00468 m_parameter1 = paraArg;
00469 enforceConstraints();
00470 Py_Return;
00471 }
00472
00473 char SCA_RandomActuator::SetFloatUniform_doc[] =
00474 "setFloatUniform(lower_bound, upper_bound)\n"
00475 "\t- lower_bound: float\n"
00476 "\t- upper_bound: float\n"
00477 "\tReturn a random integer between lower_bound and\n"
00478 "\tupper_bound.\n";
00479 PyObject* SCA_RandomActuator::PySetFloatUniform(PyObject* self,
00480 PyObject* args,
00481 PyObject* kwds) {
00482 float paraArg1, paraArg2;
00483 if(!PyArg_ParseTuple(args, "ff", ¶Arg1, ¶Arg2)) {
00484 return NULL;
00485 }
00486
00487 m_distribution = KX_RANDOMACT_FLOAT_UNIFORM;
00488 m_parameter1 = paraArg1;
00489 m_parameter2 = paraArg2;
00490 enforceConstraints();
00491 Py_Return;
00492 }
00493
00494 char SCA_RandomActuator::SetFloatNormal_doc[] =
00495 "setFloatNormal(mean, standard_deviation)\n"
00496 "\t- mean: float\n"
00497 "\t- standard_deviation: float\n"
00498 "\tReturn normal-distributed numbers. The average is mean, and the\n"
00499 "\tdeviation from the mean is characterized by standard_deviation.\n";
00500 PyObject* SCA_RandomActuator::PySetFloatNormal(PyObject* self,
00501 PyObject* args,
00502 PyObject* kwds) {
00503 float paraArg1, paraArg2;
00504 if(!PyArg_ParseTuple(args, "ff", ¶Arg1, ¶Arg2)) {
00505 return NULL;
00506 }
00507
00508 m_distribution = KX_RANDOMACT_FLOAT_NORMAL;
00509 m_parameter1 = paraArg1;
00510 m_parameter2 = paraArg2;
00511 enforceConstraints();
00512 Py_Return;
00513 }
00514
00515 char SCA_RandomActuator::SetFloatNegativeExponential_doc[] =
00516 "setFloatNegativeExponential(half_life)\n"
00517 "\t- half_life: float\n"
00518 "\tReturn negative-exponentially distributed numbers. The half-life 'time'\n"
00519 "\tis characterized by half_life.\n";
00520 PyObject* SCA_RandomActuator::PySetFloatNegativeExponential(PyObject* self,
00521 PyObject* args,
00522 PyObject* kwds) {
00523 float paraArg;
00524 if(!PyArg_ParseTuple(args, "f", ¶Arg)) {
00525 return NULL;
00526 }
00527
00528 m_distribution = KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL;
00529 m_parameter1 = paraArg;
00530 enforceConstraints();
00531 Py_Return;
00532 }
00533
00534