7199ee6cf22fc781d0e3cc3bc79ac67a61e06a02
[blender.git] / source / gameengine / GameLogic / SCA_RandomSensor.cpp
1 /*
2  * Generate random pulses
3  *
4  *
5  * ***** BEGIN GPL LICENSE BLOCK *****
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
22  * All rights reserved.
23  *
24  * The Original Code is: all of this file.
25  *
26  * Contributor(s): none yet.
27  *
28  * ***** END GPL LICENSE BLOCK *****
29  */
30
31 /** \file gameengine/GameLogic/SCA_RandomSensor.cpp
32  *  \ingroup gamelogic
33  */
34
35
36 #include <stddef.h>
37
38 #include "SCA_RandomSensor.h"
39 #include "SCA_EventManager.h"
40 #include "SCA_RandomEventManager.h"
41 #include "SCA_LogicManager.h"
42 #include "ConstExpr.h"
43 #include <iostream>
44
45 /* ------------------------------------------------------------------------- */
46 /* Native functions                                                          */
47 /* ------------------------------------------------------------------------- */
48
49 SCA_RandomSensor::SCA_RandomSensor(SCA_EventManager* eventmgr, 
50                                    SCA_IObject* gameobj,
51                                    int startseed)
52     : SCA_ISensor(gameobj,eventmgr)
53 {
54         m_basegenerator = new SCA_RandomNumberGenerator(startseed);
55         Init();
56 }
57
58
59
60 SCA_RandomSensor::~SCA_RandomSensor() 
61 {
62         m_basegenerator->Release();
63 }
64
65 void SCA_RandomSensor::Init()
66 {
67         m_iteration  = 0;
68         m_interval = 0;
69         m_lastdraw   = false;
70         m_currentDraw = m_basegenerator->Draw();
71 }
72
73
74 CValue* SCA_RandomSensor::GetReplica()
75 {
76         CValue* replica = new SCA_RandomSensor(*this);
77         // this will copy properties and so on...
78         replica->ProcessReplica();
79
80         return replica;
81 }
82
83 void SCA_RandomSensor::ProcessReplica()
84 {
85         SCA_ISensor::ProcessReplica();
86         // increment reference count so that we can release the generator at this end
87         m_basegenerator->AddRef();
88 }
89
90
91 bool SCA_RandomSensor::IsPositiveTrigger()
92
93         return (m_invert !=m_lastdraw);
94 }
95
96
97 bool SCA_RandomSensor::Evaluate()
98 {
99         /* Random generator is the generator from Line 25 of Table 1 in          */
100         /* [KNUTH 1981, The Art of Computer Programming Vol. 2                   */
101         /* (2nd Ed.), pp102]                                                     */
102         /* It's a very simple max. length sequence generator. We can             */
103         /* draw 32 bool values before having to generate the next                */
104         /* sequence value. There are some theorems that will tell you            */
105         /* this is a reasonable way of generating bools. Check Knuth.            */
106         /* Furthermore, we only draw each <delay>-eth frame.                     */
107
108         bool evaluateResult = false;
109
110         if (++m_interval > m_pulse_frequency) {
111                 bool drawResult = false;
112                 m_interval = 0;
113                 if (m_iteration > 31) {
114                         m_currentDraw = m_basegenerator->Draw();
115                         drawResult = (m_currentDraw & 0x1) == 0;
116                         m_iteration = 1;
117                 } else {
118                         drawResult = ((m_currentDraw >> m_iteration) & 0x1) == 0;
119                         m_iteration++;
120                 }
121                 evaluateResult = drawResult != m_lastdraw;
122                 m_lastdraw = drawResult;
123         }
124
125         /* now pass this result to some controller */
126         return evaluateResult;
127 }
128
129 #ifdef WITH_PYTHON
130
131 /* ------------------------------------------------------------------------- */
132 /* Python functions                                                          */
133 /* ------------------------------------------------------------------------- */
134
135 /* Integration hooks ------------------------------------------------------- */
136 PyTypeObject SCA_RandomSensor::Type = {
137         PyVarObject_HEAD_INIT(NULL, 0)
138         "SCA_RandomSensor",
139         sizeof(PyObjectPlus_Proxy),
140         0,
141         py_base_dealloc,
142         0,
143         0,
144         0,
145         0,
146         py_base_repr,
147         0,0,0,0,0,0,0,0,0,
148         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
149         0,0,0,0,0,0,0,
150         Methods,
151         0,
152         0,
153         &SCA_ISensor::Type,
154         0,0,0,0,0,0,
155         py_base_new
156 };
157
158 PyMethodDef SCA_RandomSensor::Methods[] = {
159         {NULL,NULL} //Sentinel
160 };
161
162 PyAttributeDef SCA_RandomSensor::Attributes[] = {
163         KX_PYATTRIBUTE_BOOL_RO("lastDraw",SCA_RandomSensor,m_lastdraw),
164         KX_PYATTRIBUTE_RW_FUNCTION("seed", SCA_RandomSensor, pyattr_get_seed, pyattr_set_seed),
165         {NULL} //Sentinel
166 };
167
168 PyObject *SCA_RandomSensor::pyattr_get_seed(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
169 {
170         SCA_RandomSensor* self = static_cast<SCA_RandomSensor*>(self_v);
171         return PyLong_FromSsize_t(self->m_basegenerator->GetSeed());
172 }
173
174 int SCA_RandomSensor::pyattr_set_seed(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
175 {
176         SCA_RandomSensor* self = static_cast<SCA_RandomSensor*>(self_v);
177         if (!PyLong_Check(value)) {
178                 PyErr_SetString(PyExc_TypeError, "sensor.seed = int: Random Sensor, expected an integer");
179                 return PY_SET_ATTR_FAIL;
180         }
181         self->m_basegenerator->SetSeed(PyLong_AsSsize_t(value));
182         return PY_SET_ATTR_SUCCESS;
183 }
184
185 #endif // WITH_PYTHON
186
187 /* eof */