2.50: svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r18677...
[blender.git] / source / gameengine / GameLogic / SCA_RandomActuator.cpp
1 /**
2  * Set random/camera stuff
3  *
4  * $Id$
5  *
6  * ***** BEGIN GPL LICENSE BLOCK *****
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL LICENSE BLOCK *****
30  */
31
32 #include "BoolValue.h"
33 #include "IntValue.h"
34 #include "FloatValue.h"
35 #include "SCA_IActuator.h"
36 #include "SCA_RandomActuator.h"
37 #include "math.h"
38 #include "MT_Transform.h"
39
40 #ifdef HAVE_CONFIG_H
41 #include <config.h>
42 #endif
43
44 /* ------------------------------------------------------------------------- */
45 /* Native functions                                                          */
46 /* ------------------------------------------------------------------------- */
47
48 SCA_RandomActuator::SCA_RandomActuator(SCA_IObject *gameobj, 
49                                                                          long seed,
50                                                                          SCA_RandomActuator::KX_RANDOMACT_MODE mode,
51                                                                          float para1,
52                                                                          float para2,
53                                                                          const STR_String &propName,
54                                                                          PyTypeObject* T)
55         : SCA_IActuator(gameobj, T),
56           m_propname(propName),
57           m_parameter1(para1),
58           m_parameter2(para2),
59           m_distribution(mode)
60 {
61         // m_base is never deleted, probably a memory leak!
62         m_base = new SCA_RandomNumberGenerator(seed);
63         m_counter = 0;
64         enforceConstraints();
65
66
67
68
69 SCA_RandomActuator::~SCA_RandomActuator()
70 {
71         /* intentionally empty */ 
72
73
74
75
76 CValue* SCA_RandomActuator::GetReplica()
77 {
78         SCA_RandomActuator* replica = new SCA_RandomActuator(*this);
79         // replication just copy the m_base pointer => common random generator
80         replica->ProcessReplica();
81         CValue::AddDataToReplica(replica);
82
83         return replica;
84 }
85
86
87
88 bool SCA_RandomActuator::Update()
89 {
90         //bool result = false;  /*unused*/
91         bool bNegativeEvent = IsNegativeEvent();
92
93         RemoveAllEvents();
94
95
96         CValue *tmpval = NULL;
97
98         if (bNegativeEvent)
99                 return false; // do nothing on negative events
100
101         switch (m_distribution) {
102         case KX_RANDOMACT_BOOL_CONST: {
103                 /* un petit peu filthy */
104                 bool res = !(m_parameter1 < 0.5);
105                 tmpval = new CBoolValue(res);
106         }
107         break;
108         case KX_RANDOMACT_BOOL_UNIFORM: {
109                 /* flip a coin */
110                 bool res; 
111                 if (m_counter > 31) {
112                         m_previous = m_base->Draw();
113                         res = ((m_previous & 0x1) == 0);
114                         m_counter = 1;
115                 } else {
116                         res = (((m_previous >> m_counter) & 0x1) == 0);
117                         m_counter++;
118                 }
119                 tmpval = new CBoolValue(res);
120         }
121         break;
122         case KX_RANDOMACT_BOOL_BERNOUILLI: {
123                 /* 'percentage' */
124                 bool res;
125                 res = (m_base->DrawFloat() < m_parameter1);
126                 tmpval = new CBoolValue(res);
127         }
128         break;
129         case KX_RANDOMACT_INT_CONST: {
130                 /* constant */
131                 tmpval = new CIntValue((int) floor(m_parameter1));
132         }
133         break;
134         case KX_RANDOMACT_INT_UNIFORM: {
135                 /* uniform (toss a die) */
136                 int res; 
137                 /* The [0, 1] interval is projected onto the [min, max+1] domain,    */
138                 /* and then rounded.                                                 */
139                 res = (int) floor( ((m_parameter2 - m_parameter1 + 1) * m_base->DrawFloat())
140                                                    + m_parameter1);
141                 tmpval = new CIntValue(res);
142         }
143         break;
144         case KX_RANDOMACT_INT_POISSON: {
145                 /* poisson (queues) */
146                 /* If x_1, x_2, ... is a sequence of random numbers with uniform     */
147                 /* distribution between zero and one, k is the first integer for     */
148                 /* which the product x_1*x_2*...*x_k < exp(-\lamba).                 */
149                 float a = 0.0, b = 0.0;
150                 int res = 0;
151                 /* The - sign is important here! The number to test for, a, must be  */
152                 /* between 0 and 1.                                                  */
153                 a = exp(-m_parameter1);
154                 /* a quickly reaches 0.... so we guard explicitly for that.          */
155                 if (a < FLT_MIN) a = FLT_MIN;
156                 b = m_base->DrawFloat();
157                 while (b >= a) {
158                         b = b * m_base->DrawFloat();
159                         res++;
160                 };      
161                 tmpval = new CIntValue(res);
162         }
163         break;
164         case KX_RANDOMACT_FLOAT_CONST: {
165                 /* constant */
166                 tmpval = new CFloatValue(m_parameter1);
167         }
168         break;
169         case KX_RANDOMACT_FLOAT_UNIFORM: {
170                 float res = ((m_parameter2 - m_parameter1) * m_base->DrawFloat())
171                         + m_parameter1;
172                 tmpval = new CFloatValue(res);
173         }
174         break;
175         case KX_RANDOMACT_FLOAT_NORMAL: {
176                 /* normal (big numbers): para1 = mean, para2 = std dev               */
177
178                 /* 
179
180                    070301 - nzc - Changed the termination condition. I think I 
181                    made a small mistake here, but it only affects distro's where
182                    the seed equals 0. In that case, the algorithm locks. Let's
183                    just guard that case separately.
184
185                 */
186
187                 float x = 0.0, y = 0.0, s = 0.0, t = 0.0;
188                 if (m_base->GetSeed() == 0) {
189                         /*
190
191                           070301 - nzc 
192                           Just taking the mean here seems reasonable.
193
194                          */
195                         tmpval = new CFloatValue(m_parameter1);
196                 } else {
197                         /*
198
199                           070301 - nzc 
200                           Now, with seed != 0, we will most assuredly get some
201                           sensible values. The termination condition states two 
202                           things: 
203                           1. s >= 0 is not allowed: to prevent the distro from 
204                              getting a bias towards high values. This is a small 
205                                  correction, really, and might also be left out.
206                           2. s == 0 is not allowed: to prevent a division by zero
207                              when renormalising the drawn value to the desired 
208                                  distribution shape. As a side effect, the distro will
209                                  never yield the exact mean. 
210                           I am not sure whether this is consistent, since the error 
211                           cause by #2 is of the same magnitude as the one 
212                           prevented by #1. The error introduced into the SD will be 
213                           improved, though. By how much? Hard to say... If you like
214                           the maths, feel free to analyse. Be aware that this is 
215                           one of the really old standard algorithms. I think the 
216                           original came in Fortran, was translated to Pascal, and 
217                           then someone came up with the C code. My guess it that
218                           this will be quite sufficient here.
219
220                          */
221                         do 
222                         {
223                                 x = 2.0 * m_base->DrawFloat() - 1.0;
224                                 y = 2.0 * m_base->DrawFloat() - 1.0;
225                                 s = x*x + y*y;
226                         } while ( (s >= 1.0) || (s == 0.0) );
227                         t = x * sqrt( (-2.0 * log(s)) / s);
228                         tmpval = new CFloatValue(m_parameter1 + m_parameter2 * t);
229                 }
230         }
231         break;
232         case KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL: {
233                 /* 1st order fall-off. I am very partial to using the half-life as    */
234                 /* controlling parameter. Using the 'normal' exponent is not very     */
235                 /* intuitive...                                                       */
236                 /* tmpval = new CFloatValue( (1.0 / m_parameter1)                     */
237                 tmpval = new CFloatValue( (m_parameter1) 
238                                                                   * (-log(1.0 - m_base->DrawFloat())) );
239
240         }
241         break;
242         default:
243         {
244                 /* unknown distribution... */
245                 static bool randomWarning = false;
246                 if (!randomWarning) {
247                         randomWarning = true;
248                         std::cout << "RandomActuator '" << GetName() << "' has an unknown distribution." << std::endl;
249                 }
250                 return false;
251         }
252         }
253
254         /* Round up: assign it */
255         CValue *prop = GetParent()->GetProperty(m_propname);
256         if (prop) {
257                 prop->SetValue(tmpval);
258         }
259         tmpval->Release();
260
261         return false;
262 }
263
264 void SCA_RandomActuator::enforceConstraints() {
265         /* The constraints that are checked here are the ones fundamental to     */
266         /* the various distributions. Limitations of the algorithms are checked  */
267         /* elsewhere (or they should be... ).                                    */
268         switch (m_distribution) {
269         case KX_RANDOMACT_BOOL_CONST:
270         case KX_RANDOMACT_BOOL_UNIFORM:
271         case KX_RANDOMACT_INT_CONST:
272         case KX_RANDOMACT_INT_UNIFORM:
273         case KX_RANDOMACT_FLOAT_UNIFORM:
274         case KX_RANDOMACT_FLOAT_CONST:
275                 ; /* Nothing to be done here. We allow uniform distro's to have      */
276                 /* 'funny' domains, i.e. max < min. This does not give problems.     */
277                 break;
278         case KX_RANDOMACT_BOOL_BERNOUILLI: 
279                 /* clamp to [0, 1] */
280                 if (m_parameter1 < 0.0) {
281                         m_parameter1 = 0.0;
282                 } else if (m_parameter1 > 1.0) {
283                         m_parameter1 = 1.0;
284                 }
285                 break;
286         case KX_RANDOMACT_INT_POISSON: 
287                 /* non-negative */
288                 if (m_parameter1 < 0.0) {
289                         m_parameter1 = 0.0;
290                 }
291                 break;
292         case KX_RANDOMACT_FLOAT_NORMAL: 
293                 /* standard dev. is non-negative */
294                 if (m_parameter2 < 0.0) {
295                         m_parameter2 = 0.0;
296                 }
297                 break;
298         case KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL: 
299                 /* halflife must be non-negative */
300                 if (m_parameter1 < 0.0) {
301                         m_parameter1 = 0.0;
302                 }
303                 break;
304         default:
305                 ; /* unknown distribution... */
306         }
307 }
308
309 /* ------------------------------------------------------------------------- */
310 /* Python functions                                                          */
311 /* ------------------------------------------------------------------------- */
312
313 /* Integration hooks ------------------------------------------------------- */
314 PyTypeObject SCA_RandomActuator::Type = {
315         PyObject_HEAD_INIT(&PyType_Type)
316         0,
317         "SCA_RandomActuator",
318         sizeof(SCA_RandomActuator),
319         0,
320         PyDestructor,
321         0,
322         __getattr,
323         __setattr,
324         0, //&MyPyCompare,
325         __repr,
326         0, //&cvalue_as_number,
327         0,
328         0,
329         0,
330         0
331 };
332
333 PyParentObject SCA_RandomActuator::Parents[] = {
334         &SCA_RandomActuator::Type,
335         &SCA_IActuator::Type,
336         &SCA_ILogicBrick::Type,
337         &CValue::Type,
338         NULL
339 };
340
341 PyMethodDef SCA_RandomActuator::Methods[] = {
342         //Deprecated functions ------>
343         {"setSeed",         (PyCFunction) SCA_RandomActuator::sPySetSeed, METH_VARARGS, (PY_METHODCHAR)SetSeed_doc},
344         {"getSeed",         (PyCFunction) SCA_RandomActuator::sPyGetSeed, METH_VARARGS, (PY_METHODCHAR)GetSeed_doc},
345         {"getPara1",        (PyCFunction) SCA_RandomActuator::sPyGetPara1, METH_VARARGS, (PY_METHODCHAR)GetPara1_doc},
346         {"getPara2",        (PyCFunction) SCA_RandomActuator::sPyGetPara2, METH_VARARGS, (PY_METHODCHAR)GetPara2_doc},
347         {"getDistribution", (PyCFunction) SCA_RandomActuator::sPyGetDistribution, METH_VARARGS, (PY_METHODCHAR)GetDistribution_doc},
348         {"setProperty",     (PyCFunction) SCA_RandomActuator::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc},
349         {"getProperty",     (PyCFunction) SCA_RandomActuator::sPyGetProperty, METH_VARARGS, (PY_METHODCHAR)GetProperty_doc},
350         //<----- Deprecated
351         {"setBoolConst",    (PyCFunction) SCA_RandomActuator::sPySetBoolConst, METH_VARARGS, (PY_METHODCHAR)SetBoolConst_doc},
352         {"setBoolUniform",  (PyCFunction) SCA_RandomActuator::sPySetBoolUniform, METH_VARARGS, (PY_METHODCHAR)SetBoolUniform_doc},
353         {"setBoolBernouilli",(PyCFunction) SCA_RandomActuator::sPySetBoolBernouilli, METH_VARARGS, (PY_METHODCHAR)SetBoolBernouilli_doc},
354         {"setIntConst",     (PyCFunction) SCA_RandomActuator::sPySetIntConst, METH_VARARGS, (PY_METHODCHAR)SetIntConst_doc},
355         {"setIntUniform",   (PyCFunction) SCA_RandomActuator::sPySetIntUniform, METH_VARARGS, (PY_METHODCHAR)SetIntUniform_doc},
356         {"setIntPoisson",   (PyCFunction) SCA_RandomActuator::sPySetIntPoisson, METH_VARARGS, (PY_METHODCHAR)SetIntPoisson_doc},
357         {"setFloatConst",   (PyCFunction) SCA_RandomActuator::sPySetFloatConst, METH_VARARGS, (PY_METHODCHAR)SetFloatConst_doc},
358         {"setFloatUniform", (PyCFunction) SCA_RandomActuator::sPySetFloatUniform, METH_VARARGS, (PY_METHODCHAR)SetFloatUniform_doc},
359         {"setFloatNormal",  (PyCFunction) SCA_RandomActuator::sPySetFloatNormal, METH_VARARGS, (PY_METHODCHAR)SetFloatNormal_doc},
360         {"setFloatNegativeExponential", (PyCFunction) SCA_RandomActuator::sPySetFloatNegativeExponential, METH_VARARGS, (PY_METHODCHAR)SetFloatNegativeExponential_doc},
361         {NULL,NULL} //Sentinel
362 };
363
364 PyAttributeDef SCA_RandomActuator::Attributes[] = {
365         KX_PYATTRIBUTE_FLOAT_RO("para1",SCA_RandomActuator,m_parameter1),
366         KX_PYATTRIBUTE_FLOAT_RO("para2",SCA_RandomActuator,m_parameter2),
367         KX_PYATTRIBUTE_ENUM_RO("distribution",SCA_RandomActuator,m_distribution),
368         KX_PYATTRIBUTE_STRING_RW_CHECK("property",0,100,false,SCA_RandomActuator,m_propname,CheckProperty),
369         { NULL }        //Sentinel
370 };      
371
372 PyObject* SCA_RandomActuator::_getattr(const char *attr) {
373         PyObject* object = _getattr_self(Attributes, this, attr);
374         if (object != NULL)
375                 return object;
376         if (!strcmp(attr, "seed")) {
377                 return PyInt_FromLong(m_base->GetSeed());
378         }
379         _getattr_up(SCA_IActuator);
380 }
381
382 int SCA_RandomActuator::_setattr(const char *attr, PyObject *value)
383 {
384         int ret = _setattr_self(Attributes, this, attr, value);
385         if (ret >= 0)
386                 return ret;
387         if (!strcmp(attr, "seed")) {
388                 if (PyInt_Check(value)) {
389                         int ival = PyInt_AsLong(value);
390                         m_base->SetSeed(ival);
391                         return 0;
392                 } else {
393                         PyErr_SetString(PyExc_TypeError, "expected an integer");
394                         return 1;
395                 }
396         }
397         return SCA_IActuator::_setattr(attr, value);
398 }
399
400 /* 1. setSeed                                                            */
401 const char SCA_RandomActuator::SetSeed_doc[] = 
402 "setSeed(seed)\n"
403 "\t- seed: integer\n"
404 "\tSet the initial seed of the generator. Equal seeds produce\n"
405 "\tequal series. If the seed is 0, the generator will produce\n"
406 "\tthe same value on every call.\n";
407 PyObject* SCA_RandomActuator::PySetSeed(PyObject* self, PyObject* args, PyObject* kwds) {
408         ShowDeprecationWarning("setSeed()", "the seed property");
409         long seedArg;
410         if(!PyArg_ParseTuple(args, "i", &seedArg)) {
411                 return NULL;
412         }
413         
414         m_base->SetSeed(seedArg);
415         
416         Py_RETURN_NONE;
417 }
418 /* 2. getSeed                                                            */
419 const char SCA_RandomActuator::GetSeed_doc[] = 
420 "getSeed()\n"
421 "\tReturns the initial seed of the generator. Equal seeds produce\n"
422 "\tequal series.\n";
423 PyObject* SCA_RandomActuator::PyGetSeed(PyObject* self, PyObject* args, PyObject* kwds) {
424         ShowDeprecationWarning("getSeed()", "the seed property");
425         return PyInt_FromLong(m_base->GetSeed());
426 }
427
428 /* 4. getPara1                                                           */
429 const char SCA_RandomActuator::GetPara1_doc[] = 
430 "getPara1()\n"
431 "\tReturns the first parameter of the active distribution. Refer\n"
432 "\tto the documentation of the generator types for the meaning\n"
433 "\tof this value.";
434 PyObject* SCA_RandomActuator::PyGetPara1(PyObject* self, PyObject* args, PyObject* kwds) {
435         ShowDeprecationWarning("getPara1()", "the para1 property");
436         return PyFloat_FromDouble(m_parameter1);
437 }
438
439 /* 6. getPara2                                                           */
440 const char SCA_RandomActuator::GetPara2_doc[] = 
441 "getPara2()\n"
442 "\tReturns the first parameter of the active distribution. Refer\n"
443 "\tto the documentation of the generator types for the meaning\n"
444 "\tof this value.";
445 PyObject* SCA_RandomActuator::PyGetPara2(PyObject* self, PyObject* args, PyObject* kwds) {
446         ShowDeprecationWarning("getPara2()", "the para2 property");
447         return PyFloat_FromDouble(m_parameter2);
448 }
449
450 /* 8. getDistribution                                                    */
451 const char SCA_RandomActuator::GetDistribution_doc[] = 
452 "getDistribution()\n"
453 "\tReturns the type of the active distribution.\n";
454 PyObject* SCA_RandomActuator::PyGetDistribution(PyObject* self, PyObject* args, PyObject* kwds) {
455         ShowDeprecationWarning("getDistribution()", "the distribution property");
456         return PyInt_FromLong(m_distribution);
457 }
458
459 /* 9. setProperty                                                        */
460 const char SCA_RandomActuator::SetProperty_doc[] = 
461 "setProperty(name)\n"
462 "\t- name: string\n"
463 "\tSet the property to which the random value is assigned. If the \n"
464 "\tgenerator and property types do not match, the assignment is ignored.\n";
465 PyObject* SCA_RandomActuator::PySetProperty(PyObject* self, PyObject* args, PyObject* kwds) {
466         ShowDeprecationWarning("setProperty()", "the 'property' property");
467         char *nameArg;
468         if (!PyArg_ParseTuple(args, "s", &nameArg)) {
469                 return NULL;
470         }
471
472         CValue* prop = GetParent()->FindIdentifier(nameArg);
473
474         if (!prop->IsError()) {
475                 m_propname = nameArg;
476         } else {
477                 ; /* not found ... */
478         }
479         prop->Release();
480         
481         Py_RETURN_NONE;
482 }
483 /* 10. getProperty                                                       */
484 const char SCA_RandomActuator::GetProperty_doc[] = 
485 "getProperty(name)\n"
486 "\tReturn the property to which the random value is assigned. If the \n"
487 "\tgenerator and property types do not match, the assignment is ignored.\n";
488 PyObject* SCA_RandomActuator::PyGetProperty(PyObject* self, PyObject* args, PyObject* kwds) {
489         ShowDeprecationWarning("getProperty()", "the 'property' property");
490         return PyString_FromString(m_propname);
491 }
492
493 /* 11. setBoolConst */
494 const char SCA_RandomActuator::SetBoolConst_doc[] = 
495 "setBoolConst(value)\n"
496 "\t- value: 0 or 1\n"
497 "\tSet this generator to produce a constant boolean value.\n";
498 PyObject* SCA_RandomActuator::PySetBoolConst(PyObject* self, 
499                                                                                         PyObject* args, 
500                                                                                         PyObject* kwds) {
501         int paraArg;
502         if(!PyArg_ParseTuple(args, "i", &paraArg)) {
503                 return NULL;
504         }
505         
506         m_distribution = KX_RANDOMACT_BOOL_CONST;
507         m_parameter1 = (paraArg) ? 1.0 : 0.0;
508         
509         Py_RETURN_NONE;
510 }
511 /* 12. setBoolUniform, */
512 const char SCA_RandomActuator::SetBoolUniform_doc[] = 
513 "setBoolUniform()\n"
514 "\tSet this generator to produce true and false, each with 50%% chance of occuring\n";
515 PyObject* SCA_RandomActuator::PySetBoolUniform(PyObject* self, 
516                                                                                           PyObject* args, 
517                                                                                           PyObject* kwds) {
518         /* no args */
519         m_distribution = KX_RANDOMACT_BOOL_UNIFORM;
520         enforceConstraints();
521         Py_RETURN_NONE;
522 }
523 /* 13. setBoolBernouilli,  */
524 const char SCA_RandomActuator::SetBoolBernouilli_doc[] = 
525 "setBoolBernouilli(value)\n"
526 "\t- value: a float between 0 and 1\n"
527 "\tReturn false value * 100%% of the time.\n";
528 PyObject* SCA_RandomActuator::PySetBoolBernouilli(PyObject* self, 
529                                                                                                  PyObject* args, 
530                                                                                                  PyObject* kwds) {
531         float paraArg;
532         if(!PyArg_ParseTuple(args, "f", &paraArg)) {
533                 return NULL;
534         }
535         
536         m_distribution = KX_RANDOMACT_BOOL_BERNOUILLI;
537         m_parameter1 = paraArg; 
538         enforceConstraints();
539         Py_RETURN_NONE;
540 }
541 /* 14. setIntConst,*/
542 const char SCA_RandomActuator::SetIntConst_doc[] = 
543 "setIntConst(value)\n"
544 "\t- value: integer\n"
545 "\tAlways return value\n";
546 PyObject* SCA_RandomActuator::PySetIntConst(PyObject* self, 
547                                                                                    PyObject* args, 
548                                                                                    PyObject* kwds) {
549         int paraArg;
550         if(!PyArg_ParseTuple(args, "i", &paraArg)) {
551                 return NULL;
552         }
553         
554         m_distribution = KX_RANDOMACT_INT_CONST;
555         m_parameter1 = paraArg;
556         enforceConstraints();
557         Py_RETURN_NONE;
558 }
559 /* 15. setIntUniform,*/
560 const char SCA_RandomActuator::SetIntUniform_doc[] = 
561 "setIntUniform(lower_bound, upper_bound)\n"
562 "\t- lower_bound: integer\n"
563 "\t- upper_bound: integer\n"
564 "\tReturn a random integer between lower_bound and\n"
565 "\tupper_bound. The boundaries are included.\n";
566 PyObject* SCA_RandomActuator::PySetIntUniform(PyObject* self, 
567                                                                                          PyObject* args, 
568                                                                                          PyObject* kwds) {
569         int paraArg1, paraArg2;
570         if(!PyArg_ParseTuple(args, "ii", &paraArg1, &paraArg2)) {
571                 return NULL;
572         }
573         
574         m_distribution = KX_RANDOMACT_INT_UNIFORM;
575         m_parameter1 = paraArg1;
576         m_parameter2 = paraArg2;
577         enforceConstraints();
578         Py_RETURN_NONE;
579 }
580 /* 16. setIntPoisson,           */
581 const char SCA_RandomActuator::SetIntPoisson_doc[] = 
582 "setIntPoisson(value)\n"
583 "\t- value: float\n"
584 "\tReturn a Poisson-distributed number. This performs a series\n"
585 "\tof Bernouilli tests with parameter value. It returns the\n"
586 "\tnumber of tries needed to achieve succes.\n";
587 PyObject* SCA_RandomActuator::PySetIntPoisson(PyObject* self, 
588                                                                                          PyObject* args, 
589                                                                                          PyObject* kwds) {
590         float paraArg;
591         if(!PyArg_ParseTuple(args, "f", &paraArg)) {
592                 return NULL;
593         }
594         
595         m_distribution = KX_RANDOMACT_INT_POISSON;
596         m_parameter1 = paraArg; 
597         enforceConstraints();
598         Py_RETURN_NONE;
599 }
600 /* 17. setFloatConst,*/
601 const char SCA_RandomActuator::SetFloatConst_doc[] = 
602 "setFloatConst(value)\n"
603 "\t- value: float\n"
604 "\tAlways return value\n";
605 PyObject* SCA_RandomActuator::PySetFloatConst(PyObject* self, 
606                                                                                          PyObject* args, 
607                                                                                          PyObject* kwds) {
608         float paraArg;
609         if(!PyArg_ParseTuple(args, "f", &paraArg)) {
610                 return NULL;
611         }
612         
613         m_distribution = KX_RANDOMACT_FLOAT_CONST;
614         m_parameter1 = paraArg; 
615         enforceConstraints();
616         Py_RETURN_NONE;
617 }
618 /* 18. setFloatUniform, */
619 const char SCA_RandomActuator::SetFloatUniform_doc[] = 
620 "setFloatUniform(lower_bound, upper_bound)\n"
621 "\t- lower_bound: float\n"
622 "\t- upper_bound: float\n"
623 "\tReturn a random integer between lower_bound and\n"
624 "\tupper_bound.\n";
625 PyObject* SCA_RandomActuator::PySetFloatUniform(PyObject* self, 
626                                                                                            PyObject* args, 
627                                                                                            PyObject* kwds) {
628         float paraArg1, paraArg2;
629         if(!PyArg_ParseTuple(args, "ff", &paraArg1, &paraArg2)) {
630                 return NULL;
631         }
632         
633         m_distribution = KX_RANDOMACT_FLOAT_UNIFORM;
634         m_parameter1 = paraArg1;
635         m_parameter2 = paraArg2;
636         enforceConstraints();
637         Py_RETURN_NONE;
638 }
639 /* 19. setFloatNormal, */
640 const char SCA_RandomActuator::SetFloatNormal_doc[] = 
641 "setFloatNormal(mean, standard_deviation)\n"
642 "\t- mean: float\n"
643 "\t- standard_deviation: float\n"
644 "\tReturn normal-distributed numbers. The average is mean, and the\n"
645 "\tdeviation from the mean is characterized by standard_deviation.\n";
646 PyObject* SCA_RandomActuator::PySetFloatNormal(PyObject* self, 
647                                                                                           PyObject* args, 
648                                                                                           PyObject* kwds) {
649         float paraArg1, paraArg2;
650         if(!PyArg_ParseTuple(args, "ff", &paraArg1, &paraArg2)) {
651                 return NULL;
652         }
653         
654         m_distribution = KX_RANDOMACT_FLOAT_NORMAL;
655         m_parameter1 = paraArg1;
656         m_parameter2 = paraArg2;
657         enforceConstraints();
658         Py_RETURN_NONE;
659 }
660 /* 20. setFloatNegativeExponential, */
661 const char SCA_RandomActuator::SetFloatNegativeExponential_doc[] = 
662 "setFloatNegativeExponential(half_life)\n"
663 "\t- half_life: float\n"
664 "\tReturn negative-exponentially distributed numbers. The half-life 'time'\n"
665 "\tis characterized by half_life.\n";
666 PyObject* SCA_RandomActuator::PySetFloatNegativeExponential(PyObject* self, 
667                                                                                                                    PyObject* args, 
668                                                                                                                    PyObject* kwds) {
669         float paraArg;
670         if(!PyArg_ParseTuple(args, "f", &paraArg)) {
671                 return NULL;
672         }
673         
674         m_distribution = KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL;
675         m_parameter1 = paraArg; 
676         enforceConstraints();
677         Py_RETURN_NONE;
678 }
679         
680 /* eof */