1 #include "cController.h"
2
3 #include "cObject.h"
4 #include "cWorld.h"
5
6 #include <cstdlib>
7 #include <cassert>
8 #include <iostream>
9
10 using std::cout;
11 using std::endl;
12 using std::string;
13
14 #define debug_state !true
15 #define debug_transitions !true
16 #define debug_step !true
17
18 // -------------------------------------------------------------
19
cController(cObject * entity,bool enabled)20 cController::cController(cObject* entity, bool enabled) {
21 mDevice = entity;
22 mEnabled = enabled;
23 }
24
~cController()25 cController::~cController() {
26 while (!mStack.empty()) mStack.pop_back();
27 }
28
printState()29 void cController::printState() {
30 int framesize = getFrameSize();
31 string framename = getFrameName();
32 cout << "CtrlSt of " << mDevice->nameable->name.c_str() << "#" << mDevice->base->oid << " Frame: " << framename << " Framesize:" << framesize << " Stack: " << mStack.size() << endl;
33 }
34
getFrameName()35 string cController::getFrameName() {
36 //cout << "getFrameName()\n";
37 const char* names[] = {
38 "WAIT", "ATTACK", "FOLLOW", "GOTO", "REPEAT",
39 "NOSTATENAME"
40 };
41 unsigned int i = mStack.back();
42 i = (i < OPCODE_MAX) ? i : OPCODE_MAX - 1;
43 string s = string(names[i]);
44 return s;
45 };
46
getFrameSizeOf(int opcode)47 unsigned int cController::getFrameSizeOf(int opcode) {
48 switch (opcode) {
49 case WAIT: return 3;
50 case ATTACK: return 2;
51 case FOLLOW: return 3;
52 case GOTO: return 5;
53 case REPEAT : return 2;
54 default: return 2;
55 }
56 }
57
getFrameSize()58 unsigned int cController::getFrameSize() {
59 return getFrameSizeOf(mStack.back());
60 }
61
getParameter(int offset)62 OID cController::getParameter(int offset) {
63 return mStack[mStack.size() - offset - 1];
64 }
65
setParameter(int offset,OID value)66 void cController::setParameter(int offset, OID value) {
67 mStack[mStack.size() - offset - 1] = value;
68 }
69
push(OID value)70 void cController::push(OID value) {
71 mStack.push_back(value);
72 }
73
pop()74 void cController::pop() {
75 if (debug_transitions) {
76 cout << mDevice->nameable->name.c_str() << "#" << mDevice->base->oid << ".pop()\n";
77 }
78 int size = getFrameSize(); // Important: eval outside loop-condition!
79 loopi(size) mStack.pop_back();
80 if (debug_transitions) {
81 printState();
82 }
83 }
84
process(float spf)85 void cController::process(float spf) {
86 if (debug_state) cout << "cController::process()\n";
87
88 if (!mEnabled) return;
89 if (mDevice == NULL) return;
90
91 if (mStack.empty()) pushWaitEvent();
92
93 if (debug_step) printState();
94
95 switch (mStack.back()) {
96 case WAIT: waitEvent();
97 break;
98 case ATTACK: attackEnemy();
99 break;
100 case FOLLOW: followLeader();
101 break;
102 case GOTO: gotoDestination();
103 break;
104 case REPEAT: repeatInstructions();
105 break;
106 default: cout << "Invalid Instruction Request!\n";
107 break;
108 }
109 if (debug_step) {
110 cout << "=> ";
111 printState();
112 }
113 }
114
115
116 // -------------------------------------------------------------
117
pushWaitEvent(long mseconds,bool patrol)118 void cController::pushWaitEvent(long mseconds, bool patrol) {
119 push(patrol);
120 push(mseconds);
121 push(WAIT);
122 }
123
waitEvent()124 void cController::waitEvent() {
125 //OID opcode = getParameter(0);
126 long mseconds = getParameter(1);
127 bool patrol = getParameter(2);
128
129 {
130 mDevice->do_idle();
131 }
132
133 if (patrol) {
134 OID enemy = 0;
135 if (enemy == 0) enemy = mDevice->disturbedBy();
136 if (enemy == 0) enemy = mDevice->enemyNearby();
137 if (enemy) {
138 {
139 OID self = mDevice->base->oid;
140 cWorld::instance->sendMessage(0, 0, "#%llu: Intruder!\n", self);
141 }
142 pushAttackEnemy(enemy);
143 }
144 }
145
146 if (mseconds > 0) {
147 mseconds -= 1000/40;
148 setParameter(1, mseconds);
149 if (mseconds <= 0) {
150 pop();
151 return;
152 }
153 }
154 }
155
156 // -------------------------------------------------------------
157
pushAttackEnemy(OID entity)158 void cController::pushAttackEnemy(OID entity) {
159 if (debug_transitions) {
160 cout << mDevice->nameable->name.c_str() << "#" << mDevice->base->oid << ".pushAttackEnemy( " << entity << " )\n";
161 }
162 {
163 //OID self = mDevice->mSerial;
164 //cWorld::instance->sendMessage("@%llu: All ur base belongs to us.\n", entity);
165 }
166 push(entity);
167 push(ATTACK);
168 }
169
attackEnemy()170 void cController::attackEnemy() {
171 //OID opcode = getParameter(0);
172 OID entity = getParameter(1);
173
174 {
175 mDevice->do_moveFor(NULL);
176 mDevice->do_aimFor(entity);
177 mDevice->do_moveNear();
178 mDevice->do_aimAt();
179 if (mDevice->inWeaponRange() > 0.5) mDevice->do_fireAt();
180 //((cMech*)mDevice)->Pattern(tf, "nrnlln");
181 }
182
183 cObject* target = cWorld::instance->mIndex[entity];
184 if (mDevice->inTargetRange() < 0.01) {
185 mDevice->do_aimFor(0);
186 pop();
187 return;
188 }
189 if (target == NULL) { // Target disappeared
190 mDevice->do_aimFor(0);
191 pop();
192 return;
193 } else if (target->hasRole(DEAD)) {
194 mDevice->do_aimFor(0);
195 pop();
196 return;
197 }
198
199 }
200
201 // -------------------------------------------------------------
202
pushFollowLeader(OID entity,bool patrol)203 void cController::pushFollowLeader(OID entity, bool patrol) {
204 if (debug_transitions) {
205 cout << mDevice->nameable->name.c_str() << "#" << mDevice->base->oid << ".pushFollowLeader( " << entity << ", " << patrol << " )\n";
206 }
207 push(patrol ? 1 : 0);
208 push(entity);
209 push(FOLLOW);
210 }
211
followLeader()212 void cController::followLeader() {
213 //OID opcode = getParameter(0);
214 OID entity = getParameter(1);
215 OID patrol = getParameter(2);
216
217 {
218 mDevice->do_aimFor(entity);
219 mDevice->do_moveFor(NULL);
220 mDevice->do_moveNear();
221 mDevice->do_aimAt();
222 }
223
224 if (patrol) {
225 OID nearby = mDevice->enemyNearby();
226 if (nearby) {
227 pushAttackEnemy(nearby);
228 return;
229 }
230 }
231 }
232
233 // -------------------------------------------------------------
234
pushGotoDestination(float * v,bool patrol)235 void cController::pushGotoDestination(float* v, bool patrol) {
236 if (v == NULL) return;
237 if (debug_transitions) {
238 cout << mDevice->nameable->name.c_str() << "#" << mDevice->base->oid << ".pushGotoDestination( <" << v[0] << "," << v[1] << "," << v[2] << ">, " << patrol << " )\n";
239 }
240 unsigned long *p = (unsigned long*) v;
241 push(patrol ? !0 : 0);
242 push(p[2]);
243 push(p[1]);
244 push(p[0]);
245 push(GOTO);
246 }
247
gotoDestination()248 void cController::gotoDestination() {
249 //OID opcode = getParameter(0);
250 OID v0 = getParameter(1);
251 OID v1 = getParameter(2);
252 OID v2 = getParameter(3);
253 OID patrol = getParameter(4);
254 unsigned long p[] = {
255 v0, v1, v2
256 };
257 float* v = (float*) p;
258
259 {
260 if (debug_state) cout << "going " << ((patrol > 0) ? "patrolling" : "directly") << " to <" << v[0] << "," << v[1] << "," << v[2] << " >\n";
261 mDevice->do_moveFor(v);
262 //mDevice->do_aimFor(0);
263 mDevice->do_aimAt();
264 mDevice->do_moveTowards();
265 }
266
267 float range = mDevice->inDestinationRange();
268 if (debug_state) cout << "DestinationRange " << range << endl;
269 if (range > 0.0f) {
270 pop();
271 return;
272 }
273
274 if (patrol) {
275 OID nearby = mDevice->enemyNearby();
276 if (nearby) {
277 pushAttackEnemy(nearby);
278 return;
279 }
280 }
281 }
282
283 // -------------------------------------------------------------
284
pushRepeatInstructions(int n)285 void cController::pushRepeatInstructions(int n) {
286 if (debug_transitions) {
287 cout << mDevice->nameable->name.c_str() << "#" << mDevice->base->oid << ".pushRepeatInstructions( " << n << " )\n";
288 }
289 push(n);
290 push(REPEAT);
291 }
292
repeatInstructions()293 void cController::repeatInstructions() {
294 OID opcode = getParameter(0);
295 OID n = getParameter(1);
296
297 if (debug_state) {
298 printState();
299 }
300
301 unsigned int first = getFrameSize();
302 if (debug_state) cout << "first " << first << " -> opcode " << opcode << endl;
303 unsigned int last = first;
304 loopi(n) {
305 int opcode = getParameter(last);
306 last += getFrameSizeOf(opcode);
307 if (debug_state) cout << "last " << last << " -> opcode " << opcode << endl;
308 }
309
310 int size = last - first;
311 if (debug_state) cout << size << " = " << last << " - " << first << endl;
312
313 loopi(size) {
314 push(getParameter(last - 1));
315 }
316 }
317
318
319