First batch of GE API cleanup.
[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 PyObject* SCA_RandomActuator::_getattr(const STR_String& attr) {
365         if (attr == "seed") {
366                 return PyInt_FromLong(m_base->GetSeed());
367         }
368         if (attr == "para1") {
369                 return PyFloat_FromDouble(m_parameter1);
370         }
371         if (attr == "para2") {
372                 return PyFloat_FromDouble(m_parameter2);
373         }
374         if (attr == "distribution") {
375                 return PyInt_FromLong(m_distribution);
376         }
377         if (attr == "property") {
378                 return PyString_FromString(m_propname);
379         }
380         _getattr_up(SCA_IActuator);
381 }
382
383 int SCA_RandomActuator::_setattr(const STR_String& attr, PyObject *value)
384 {
385         if (attr == "para1") {
386                 PyErr_SetString(PyExc_AttributeError, "para1 is read only");
387         }
388         if (attr == "para2") {
389                 PyErr_SetString(PyExc_AttributeError, "para2 is read only");
390         }
391         if (attr == "distribution") {
392                 PyErr_SetString(PyExc_AttributeError, "distribution is read only");
393         }
394         if (PyInt_Check(value)) {
395                 int ival = PyInt_AsLong(value);
396                 if (attr == "seed") {
397                         m_base->SetSeed(ival);
398                 }
399                 return 0;
400         }
401         if (PyString_Check(value)) {
402                 char* sval = PyString_AsString(value);
403                 if (attr == "property") {
404                         CValue* prop = GetParent()->FindIdentifier(sval);
405                         bool error = prop->IsError();
406                         prop->Release();
407                         if (!prop->IsError()) {
408                                 m_propname = sval;
409                                 return 0;
410                         } else {
411                                 PyErr_SetString(PyExc_ValueError, "string does not correspond to a property");
412                                 return 1;
413                         }
414                 } 
415         }
416         return SCA_IActuator::_setattr(attr, value);
417 }
418
419 /* 1. setSeed                                                            */
420 const char SCA_RandomActuator::SetSeed_doc[] = 
421 "setSeed(seed)\n"
422 "\t- seed: integer\n"
423 "\tSet the initial seed of the generator. Equal seeds produce\n"
424 "\tequal series. If the seed is 0, the generator will produce\n"
425 "\tthe same value on every call.\n";
426 PyObject* SCA_RandomActuator::PySetSeed(PyObject* self, PyObject* args, PyObject* kwds) {
427         ShowDeprecationWarning("setSeed()", "the seed property");
428         long seedArg;
429         if(!PyArg_ParseTuple(args, "i", &seedArg)) {
430                 return NULL;
431         }
432         
433         m_base->SetSeed(seedArg);
434         
435         Py_Return;
436 }
437 /* 2. getSeed                                                            */
438 const char SCA_RandomActuator::GetSeed_doc[] = 
439 "getSeed()\n"
440 "\tReturns the initial seed of the generator. Equal seeds produce\n"
441 "\tequal series.\n";
442 PyObject* SCA_RandomActuator::PyGetSeed(PyObject* self, PyObject* args, PyObject* kwds) {
443         ShowDeprecationWarning("getSeed()", "the seed property");
444         return PyInt_FromLong(m_base->GetSeed());
445 }
446
447 /* 4. getPara1                                                           */
448 const char SCA_RandomActuator::GetPara1_doc[] = 
449 "getPara1()\n"
450 "\tReturns the first parameter of the active distribution. Refer\n"
451 "\tto the documentation of the generator types for the meaning\n"
452 "\tof this value.";
453 PyObject* SCA_RandomActuator::PyGetPara1(PyObject* self, PyObject* args, PyObject* kwds) {
454         ShowDeprecationWarning("getPara1()", "the para1 property");
455         return PyFloat_FromDouble(m_parameter1);
456 }
457
458 /* 6. getPara2                                                           */
459 const char SCA_RandomActuator::GetPara2_doc[] = 
460 "getPara2()\n"
461 "\tReturns the first parameter of the active distribution. Refer\n"
462 "\tto the documentation of the generator types for the meaning\n"
463 "\tof this value.";
464 PyObject* SCA_RandomActuator::PyGetPara2(PyObject* self, PyObject* args, PyObject* kwds) {
465         ShowDeprecationWarning("getPara2()", "the para2 property");
466         return PyFloat_FromDouble(m_parameter2);
467 }
468
469 /* 8. getDistribution                                                    */
470 const char SCA_RandomActuator::GetDistribution_doc[] = 
471 "getDistribution()\n"
472 "\tReturns the type of the active distribution.\n";
473 PyObject* SCA_RandomActuator::PyGetDistribution(PyObject* self, PyObject* args, PyObject* kwds) {
474         ShowDeprecationWarning("getDistribution()", "the distribution property");
475         return PyInt_FromLong(m_distribution);
476 }
477
478 /* 9. setProperty                                                        */
479 const char SCA_RandomActuator::SetProperty_doc[] = 
480 "setProperty(name)\n"
481 "\t- name: string\n"
482 "\tSet the property to which the random value is assigned. If the \n"
483 "\tgenerator and property types do not match, the assignment is ignored.\n";
484 PyObject* SCA_RandomActuator::PySetProperty(PyObject* self, PyObject* args, PyObject* kwds) {
485         ShowDeprecationWarning("setProperty()", "the 'property' property");
486         char *nameArg;
487         if (!PyArg_ParseTuple(args, "s", &nameArg)) {
488                 return NULL;
489         }
490
491         CValue* prop = GetParent()->FindIdentifier(nameArg);
492
493         if (!prop->IsError()) {
494                 m_propname = nameArg;
495         } else {
496                 ; /* not found ... */
497         }
498         prop->Release();
499         
500         Py_Return;
501 }
502 /* 10. getProperty                                                       */
503 const char SCA_RandomActuator::GetProperty_doc[] = 
504 "getProperty(name)\n"
505 "\tReturn the property to which the random value is assigned. If the \n"
506 "\tgenerator and property types do not match, the assignment is ignored.\n";
507 PyObject* SCA_RandomActuator::PyGetProperty(PyObject* self, PyObject* args, PyObject* kwds) {
508         ShowDeprecationWarning("getProperty()", "the 'property' property");
509         return PyString_FromString(m_propname);
510 }
511
512 /* 11. setBoolConst */
513 const char SCA_RandomActuator::SetBoolConst_doc[] = 
514 "setBoolConst(value)\n"
515 "\t- value: 0 or 1\n"
516 "\tSet this generator to produce a constant boolean value.\n";
517 PyObject* SCA_RandomActuator::PySetBoolConst(PyObject* self, 
518                                                                                         PyObject* args, 
519                                                                                         PyObject* kwds) {
520         int paraArg;
521         if(!PyArg_ParseTuple(args, "i", &paraArg)) {
522                 return NULL;
523         }
524         
525         m_distribution = KX_RANDOMACT_BOOL_CONST;
526         m_parameter1 = (paraArg) ? 1.0 : 0.0;
527         
528         Py_Return;
529 }
530 /* 12. setBoolUniform, */
531 const char SCA_RandomActuator::SetBoolUniform_doc[] = 
532 "setBoolUniform()\n"
533 "\tSet this generator to produce true and false, each with 50%% chance of occuring\n";
534 PyObject* SCA_RandomActuator::PySetBoolUniform(PyObject* self, 
535                                                                                           PyObject* args, 
536                                                                                           PyObject* kwds) {
537         /* no args */
538         m_distribution = KX_RANDOMACT_BOOL_UNIFORM;
539         enforceConstraints();
540         Py_Return;
541 }
542 /* 13. setBoolBernouilli,  */
543 const char SCA_RandomActuator::SetBoolBernouilli_doc[] = 
544 "setBoolBernouilli(value)\n"
545 "\t- value: a float between 0 and 1\n"
546 "\tReturn false value * 100%% of the time.\n";
547 PyObject* SCA_RandomActuator::PySetBoolBernouilli(PyObject* self, 
548                                                                                                  PyObject* args, 
549                                                                                                  PyObject* kwds) {
550         float paraArg;
551         if(!PyArg_ParseTuple(args, "f", &paraArg)) {
552                 return NULL;
553         }
554         
555         m_distribution = KX_RANDOMACT_BOOL_BERNOUILLI;
556         m_parameter1 = paraArg; 
557         enforceConstraints();
558         Py_Return;
559 }
560 /* 14. setIntConst,*/
561 const char SCA_RandomActuator::SetIntConst_doc[] = 
562 "setIntConst(value)\n"
563 "\t- value: integer\n"
564 "\tAlways return value\n";
565 PyObject* SCA_RandomActuator::PySetIntConst(PyObject* self, 
566                                                                                    PyObject* args, 
567                                                                                    PyObject* kwds) {
568         int paraArg;
569         if(!PyArg_ParseTuple(args, "i", &paraArg)) {
570                 return NULL;
571         }
572         
573         m_distribution = KX_RANDOMACT_INT_CONST;
574         m_parameter1 = paraArg;
575         enforceConstraints();
576         Py_Return;
577 }
578 /* 15. setIntUniform,*/
579 const char SCA_RandomActuator::SetIntUniform_doc[] = 
580 "setIntUniform(lower_bound, upper_bound)\n"
581 "\t- lower_bound: integer\n"
582 "\t- upper_bound: integer\n"
583 "\tReturn a random integer between lower_bound and\n"
584 "\tupper_bound. The boundaries are included.\n";
585 PyObject* SCA_RandomActuator::PySetIntUniform(PyObject* self, 
586                                                                                          PyObject* args, 
587                                                                                          PyObject* kwds) {
588         int paraArg1, paraArg2;
589         if(!PyArg_ParseTuple(args, "ii", &paraArg1, &paraArg2)) {
590                 return NULL;
591         }
592         
593         m_distribution = KX_RANDOMACT_INT_UNIFORM;
594         m_parameter1 = paraArg1;
595         m_parameter2 = paraArg2;
596         enforceConstraints();
597         Py_Return;
598 }
599 /* 16. setIntPoisson,           */
600 const char SCA_RandomActuator::SetIntPoisson_doc[] = 
601 "setIntPoisson(value)\n"
602 "\t- value: float\n"
603 "\tReturn a Poisson-distributed number. This performs a series\n"
604 "\tof Bernouilli tests with parameter value. It returns the\n"
605 "\tnumber of tries needed to achieve succes.\n";
606 PyObject* SCA_RandomActuator::PySetIntPoisson(PyObject* self, 
607                                                                                          PyObject* args, 
608                                                                                          PyObject* kwds) {
609         float paraArg;
610         if(!PyArg_ParseTuple(args, "f", &paraArg)) {
611                 return NULL;
612         }
613         
614         m_distribution = KX_RANDOMACT_INT_POISSON;
615         m_parameter1 = paraArg; 
616         enforceConstraints();
617         Py_Return;
618 }
619 /* 17. setFloatConst,*/
620 const char SCA_RandomActuator::SetFloatConst_doc[] = 
621 "setFloatConst(value)\n"
622 "\t- value: float\n"
623 "\tAlways return value\n";
624 PyObject* SCA_RandomActuator::PySetFloatConst(PyObject* self, 
625                                                                                          PyObject* args, 
626                                                                                          PyObject* kwds) {
627         float paraArg;
628         if(!PyArg_ParseTuple(args, "f", &paraArg)) {
629                 return NULL;
630         }
631         
632         m_distribution = KX_RANDOMACT_FLOAT_CONST;
633         m_parameter1 = paraArg; 
634         enforceConstraints();
635         Py_Return;
636 }
637 /* 18. setFloatUniform, */
638 const char SCA_RandomActuator::SetFloatUniform_doc[] = 
639 "setFloatUniform(lower_bound, upper_bound)\n"
640 "\t- lower_bound: float\n"
641 "\t- upper_bound: float\n"
642 "\tReturn a random integer between lower_bound and\n"
643 "\tupper_bound.\n";
644 PyObject* SCA_RandomActuator::PySetFloatUniform(PyObject* self, 
645                                                                                            PyObject* args, 
646                                                                                            PyObject* kwds) {
647         float paraArg1, paraArg2;
648         if(!PyArg_ParseTuple(args, "ff", &paraArg1, &paraArg2)) {
649                 return NULL;
650         }
651         
652         m_distribution = KX_RANDOMACT_FLOAT_UNIFORM;
653         m_parameter1 = paraArg1;
654         m_parameter2 = paraArg2;
655         enforceConstraints();
656         Py_Return;
657 }
658 /* 19. setFloatNormal, */
659 const char SCA_RandomActuator::SetFloatNormal_doc[] = 
660 "setFloatNormal(mean, standard_deviation)\n"
661 "\t- mean: float\n"
662 "\t- standard_deviation: float\n"
663 "\tReturn normal-distributed numbers. The average is mean, and the\n"
664 "\tdeviation from the mean is characterized by standard_deviation.\n";
665 PyObject* SCA_RandomActuator::PySetFloatNormal(PyObject* self, 
666                                                                                           PyObject* args, 
667                                                                                           PyObject* kwds) {
668         float paraArg1, paraArg2;
669         if(!PyArg_ParseTuple(args, "ff", &paraArg1, &paraArg2)) {
670                 return NULL;
671         }
672         
673         m_distribution = KX_RANDOMACT_FLOAT_NORMAL;
674         m_parameter1 = paraArg1;
675         m_parameter2 = paraArg2;
676         enforceConstraints();
677         Py_Return;
678 }
679 /* 20. setFloatNegativeExponential, */
680 const char SCA_RandomActuator::SetFloatNegativeExponential_doc[] = 
681 "setFloatNegativeExponential(half_life)\n"
682 "\t- half_life: float\n"
683 "\tReturn negative-exponentially distributed numbers. The half-life 'time'\n"
684 "\tis characterized by half_life.\n";
685 PyObject* SCA_RandomActuator::PySetFloatNegativeExponential(PyObject* self, 
686                                                                                                                    PyObject* args, 
687                                                                                                                    PyObject* kwds) {
688         float paraArg;
689         if(!PyArg_ParseTuple(args, "f", &paraArg)) {
690                 return NULL;
691         }
692         
693         m_distribution = KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL;
694         m_parameter1 = paraArg; 
695         enforceConstraints();
696         Py_Return;
697 }
698         
699 /* eof */