5 |
==================== |
==================== |
6 |
*/ |
*/ |
7 |
|
|
8 |
|
|
9 |
|
|
10 |
|
|
11 |
|
|
12 |
|
|
13 |
|
|
14 |
|
|
15 |
|
|
16 |
|
|
17 |
|
|
18 |
|
|
19 |
|
|
20 |
|
|
21 |
|
// ************* RENDERMAN LINKS FREAK OUT ***************** |
22 |
|
|
23 |
|
|
24 |
#include <string> |
#include <string> |
25 |
#include <time.h> |
#include <time.h> |
26 |
#include <iostream> |
#include <iostream> |
30 |
#include "../map/pathfinding/mapsearch_pod.h" |
#include "../map/pathfinding/mapsearch_pod.h" |
31 |
#include "../map/pathfinding/stlastar.h" |
#include "../map/pathfinding/stlastar.h" |
32 |
#include "../map/map.h" |
#include "../map/map.h" |
33 |
|
#include "msg_port.h" |
34 |
|
#include "../shapes/shape.h" |
35 |
|
#include "../visual/renderman.h" |
36 |
|
|
37 |
|
|
38 |
|
// constants |
39 |
|
const long TIMING_LOOP_DELAY = 80000; // ticks per re-display for *UNIX only* in shell debug output |
40 |
|
const int MAX_POD_SIZE = 500; // the number the combined size of all shapes in the pod must not exceed. |
41 |
|
const int MAX_NUM_SHAPES = 12; // even if the MAX_POD_SIZE should allow it, number of shapes in the pod should not exceed this. |
42 |
|
const int ROAD_TRAMPLE_DIVISOR = 15; // road trample = pod size / trample divisor |
43 |
|
|
|
const long TIMING_LOOP_DELAY =400000; |
|
44 |
|
|
45 |
|
|
46 |
// static variables: |
// static variables: |
47 |
Map* Pod::map; // a pointer to the map. |
//Map* Pod::map; // a pointer to the map. |
48 |
int Pod::id_counter = 0; // unique pod ID counter |
int Pod::id_counter = 0; // unique pod ID counter |
49 |
vector<Pod*> Pod::pod_index; // a vector of pointers to pods. now we can look them up by ID number |
vector<Pod*> Pod::pod_index; // a vector of pointers to pods. now we can look them up by ID number |
50 |
|
|
51 |
|
|
52 |
|
// declared elsewhere: |
53 |
|
//extern RenderMan* rm; |
54 |
|
|
55 |
|
|
56 |
// list of fun names: |
// list of fun names: |
57 |
|
// TODO: put these in a config file someday. someday.... |
58 |
string pod_names[] = { |
string pod_names[] = { |
59 |
"Fluffy", |
"Fluffy", |
60 |
"DiamondFire", |
"DiamondFire", |
64 |
"RogerWilco", |
"RogerWilco", |
65 |
"GooGoo", |
"GooGoo", |
66 |
"HoJu", |
"HoJu", |
67 |
"Cupcake Whooper" |
"Cupcake Whooper", |
68 |
|
"Wilbur", |
69 |
|
"Joey Jo-Jo", |
70 |
|
"Smurfette" |
71 |
}; |
}; |
72 |
|
|
73 |
|
|
81 |
|
|
82 |
path = NULL; |
path = NULL; |
83 |
|
|
84 |
name = pod_names[ rand() % 9 ]; |
name = pod_names[ rand() % 12 ]; |
85 |
|
|
86 |
// give the pod some generic dummy info for testing: |
// give the pod some generic dummy info for testing: |
87 |
// TODO: give me attributes based on shapes (?) |
// TODO: give me attributes based on shapes |
88 |
align = axis; |
align = axis; |
89 |
id = ++id_counter; |
id = ++id_counter; |
90 |
att = 75; |
att = 75; |
101 |
avoid = 1; |
avoid = 1; |
102 |
engage = 1; |
engage = 1; |
103 |
|
|
104 |
num_shapes = 0; |
msgport = new MsgPort(*this); |
105 |
|
|
106 |
AddMission(IDLE, -1); // idle is the default mission |
// idle is the default mission |
107 |
|
AddMission(IDLE, -1); |
108 |
|
|
109 |
// add to pod index |
// add to pod index |
110 |
AddPod(this); |
AddPod(this); |
112 |
|
|
113 |
|
|
114 |
Pod::~Pod(){ |
Pod::~Pod(){ |
115 |
|
|
116 |
|
// nuke message port |
117 |
|
delete msgport; |
118 |
|
msgport = NULL; |
119 |
|
|
120 |
// free up A* search if filled |
// free up A* search if filled |
121 |
if (path != NULL) { |
if (path != NULL) { |
122 |
path->FreeSolutionNodes(); |
path->FreeSolutionNodes(); |
142 |
|
|
143 |
// do not reduce id_counter - it just goes up to make new IDs. it's not a pod count. use pod_index.size() for that |
// do not reduce id_counter - it just goes up to make new IDs. it's not a pod count. use pod_index.size() for that |
144 |
|
|
145 |
// remove from vector |
// remove from pod vector |
146 |
max = pod_index.size(); |
max = pod_index.size(); |
147 |
for (int i = 0; i < max; i++) { |
for (int i = 0; i < max; i++) { |
148 |
if (pod_index[i]->id == this->id) { pod_index.erase( pod_index.begin()+i ); } |
if (pod_index[i]->id == this->id) { pod_index.erase( pod_index.begin()+i ); } |
149 |
} |
} |
150 |
|
|
151 |
|
// remove from map - unset occupation |
152 |
|
themap->UnsetOccu(x_pos, y_pos); |
153 |
|
|
154 |
|
// destroy all shapes inside (if any - there shouldn't really be any) |
155 |
} |
} |
156 |
|
|
157 |
|
|
162 |
// GENERAL POD FUNCTIONS |
// GENERAL POD FUNCTIONS |
163 |
// ================================== |
// ================================== |
164 |
// map pointer setter - used for all pods. |
// map pointer setter - used for all pods. |
165 |
void Pod::SetMapPointer(Map &incoming_map){ |
//void Pod::SetMapPointer(Map &incoming_map){ map = &incoming_map; } |
|
map = &incoming_map; |
|
|
} |
|
166 |
|
|
167 |
// adds a pod to the pod index |
// adds a pod to the pod index |
168 |
void Pod::AddPod(Pod* pod){ |
void Pod::AddPod(Pod* pod){ pod_index.push_back(pod); } |
|
pod_index.push_back(pod); |
|
|
} |
|
169 |
|
|
170 |
// get a pod pointer based on it's ID number |
// get a pod pointer based on it's ID number |
171 |
Pod* Pod::GetPod(int id){ |
Pod* Pod::GetPod(int id){ |
176 |
return NULL; |
return NULL; |
177 |
} |
} |
178 |
|
|
179 |
int Pod::GetNumPods() { |
int Pod::GetNumPods() { return pod_index.size(); } |
|
return pod_index.size(); |
|
|
} |
|
180 |
// ================================== |
// ================================== |
181 |
|
|
182 |
|
|
187 |
|
|
188 |
// GET FUNCTIONS |
// GET FUNCTIONS |
189 |
// ================================== |
// ================================== |
190 |
string Pod::GetName(){ |
string Pod::GetName() { return name; } |
191 |
return name; |
int Pod::GetAlign() { return align; } |
192 |
} |
int Pod::GetID() { return id; } |
193 |
|
int Pod::GetAtt() { return att; } |
194 |
|
int Pod::GetDef() { return def; } |
195 |
|
int Pod::GetOpac() { return opac; } |
196 |
|
int Pod::GetAcu() { return acu; } |
197 |
|
int Pod::GetSize() { return size; } |
198 |
|
int Pod::GetSpd() { return spd; } |
199 |
|
int Pod::GetXPos() { return x_pos; } |
200 |
|
int Pod::GetYPos() { return y_pos; } |
201 |
|
int Pod::GetAvoid() { return avoid; } |
202 |
|
int Pod::GetEngage() { return engage; } |
203 |
|
int Pod::GetXp(){ return xp; } |
204 |
|
|
205 |
int Pod::GetAlign(){ |
Mission* Pod::Misn(int x){ |
206 |
return align; |
if (x > int (misn.size()) || x < 0 ) {return NULL;} |
207 |
|
else { return misn[x]; } |
208 |
} |
} |
209 |
|
|
210 |
int Pod::GetID(){ |
posn* Pod::Moves(int x){ |
211 |
return id; |
if (x > int (moves.size()) || x < 0 ) {return NULL;} |
212 |
|
else { return moves[x]; } |
213 |
} |
} |
214 |
|
// ================================== |
215 |
|
|
216 |
|
|
|
int Pod::GetAtt(){ |
|
|
return att; |
|
|
} |
|
217 |
|
|
|
int Pod::GetDef(){ |
|
|
return def; |
|
|
} |
|
218 |
|
|
|
int Pod::GetOpac(){ |
|
|
return opac; |
|
|
} |
|
219 |
|
|
|
int Pod::GetAcu(){ |
|
|
return acu; |
|
|
} |
|
220 |
|
|
|
int Pod::GetSize(){ |
|
|
return size; |
|
|
} |
|
221 |
|
|
|
int Pod::GetSpd(){ |
|
|
return spd; |
|
|
} |
|
222 |
|
|
|
int Pod::GetXPos(){ |
|
|
return x_pos; |
|
|
} |
|
223 |
|
|
|
int Pod::GetYPos(){ |
|
|
return y_pos; |
|
|
} |
|
224 |
|
|
|
int Pod::GetAvoid(){ |
|
|
return avoid; |
|
|
} |
|
225 |
|
|
|
int Pod::GetEngage(){ |
|
|
return engage; |
|
|
} |
|
226 |
|
|
227 |
int Pod::GetXp(){ |
// SET FUNCTIONS |
228 |
return xp; |
// ================================== |
229 |
|
void Pod::SetEngage(int x) { |
230 |
|
engage = x; |
231 |
} |
} |
232 |
|
|
233 |
Mission* Pod::Misn(int x){ |
void Pod::SetAvoid(int x){ |
234 |
if (x > int (misn.size()) || x < 0 ) {return NULL;} |
avoid = x; |
|
else { return misn[x]; } |
|
235 |
} |
} |
236 |
|
|
237 |
posn* Pod::Moves(int x){ |
bool Pod::Place(int x, int y) { |
238 |
if (x > int (moves.size()) || x < 0 ) {return NULL;} |
x_pos = x; |
239 |
else { return moves[x]; } |
y_pos = y; |
240 |
|
bool bad = themap->SetOccu(x,y,*this); |
241 |
|
if (bad) {return 0;} |
242 |
|
else {return 1;} |
243 |
} |
} |
244 |
// ================================== |
// ================================== |
245 |
|
|
251 |
|
|
252 |
|
|
253 |
|
|
|
// SET FUNCTIONS |
|
|
// ================================== |
|
254 |
|
|
255 |
|
|
256 |
|
// MISSION QUEUE FUNCTIONS |
257 |
|
// ================================== |
258 |
bool Pod::AddMission(mission_type m, int p) { |
bool Pod::AddMission(mission_type m, int p) { |
259 |
// return 0 if can't add, 1 if success |
// return 0 if can't add, 1 if success |
260 |
|
|
299 |
misn.erase( misn.begin()+p ); |
misn.erase( misn.begin()+p ); |
300 |
return 1; |
return 1; |
301 |
} |
} |
302 |
|
// ================================== |
303 |
|
|
304 |
|
|
305 |
|
|
306 |
|
|
307 |
|
|
308 |
|
|
309 |
|
|
310 |
|
|
311 |
|
|
312 |
|
|
313 |
|
|
314 |
|
// SHAPE QUEUE FUNCTIONS |
315 |
|
// ================================== |
316 |
|
|
317 |
|
Shape* Pod::Shapes(int x) { |
318 |
|
if (x > int (shapes.size()) || x < 0 ) {return NULL;} |
319 |
|
else { return shapes[x]; } |
320 |
|
} |
321 |
|
|
322 |
|
|
323 |
|
bool Pod::AddShape(Shape &s) { |
324 |
|
// return 0 if can't add, 1 if success |
325 |
|
|
326 |
|
// if we already have 12 shapes |
327 |
|
if ( int(shapes.size()) >= MAX_NUM_SHAPES ) { return 0; } |
328 |
|
|
329 |
|
// if pod size is exceeded |
330 |
|
if ( ( size + s.GetSize() ) > MAX_POD_SIZE) { return 0; } |
331 |
|
|
332 |
|
// make the pod bigger: |
333 |
|
size += s.GetSize(); |
334 |
|
|
335 |
|
// TODO: change pod stats and bonuses |
336 |
|
|
337 |
|
shapes.insert( shapes.end(), &s); |
338 |
|
return 1; |
339 |
|
} |
340 |
|
|
341 |
|
|
342 |
|
bool Pod::RemoveShape(Shape* s) { |
343 |
|
// can't ask for a non-existant shape: |
344 |
|
if (shapes.size() == 0) { return 0; } |
345 |
|
|
346 |
|
for (int x = 0; x < int(shapes.size()); x++) { |
347 |
|
if ( shapes[x]->GetID() == s->GetID() ) { |
348 |
|
size -= shapes[x]->GetSize(); // reduce pod size |
349 |
|
delete shapes[x]; |
350 |
|
shapes.erase( shapes.begin()+x ); |
351 |
|
// TODO: PICK NEW SHAPE CAPTAIN |
352 |
|
return 1; |
353 |
|
} |
354 |
|
} |
355 |
|
|
356 |
|
return 0; // not found |
357 |
|
} |
358 |
|
|
359 |
|
|
360 |
|
bool Pod::RemoveShape(int id) { |
361 |
|
// can't ask for a non-existant shape: |
362 |
|
if (shapes.size() == 0) { return 0; } |
363 |
|
|
364 |
|
for (int x = 0; x < int(shapes.size()); x++) { |
365 |
|
if ( shapes[x]->GetID() == id ) { |
366 |
|
size -= shapes[x]->GetSize(); // reduce pod size |
367 |
|
delete shapes[x]; |
368 |
|
shapes.erase( shapes.begin()+x ); |
369 |
|
// TODO: PICK NEW SHAPE CAPTAIN |
370 |
|
return 1; |
371 |
|
} |
372 |
|
} |
373 |
|
|
374 |
|
return 0; // not found |
375 |
|
} |
376 |
|
// ================================== |
377 |
|
|
378 |
|
|
379 |
|
|
380 |
|
|
381 |
|
|
382 |
|
|
383 |
|
|
384 |
|
|
385 |
|
// MOVE QUEUE FUNCTIONS |
386 |
|
// ================================== |
387 |
bool Pod::AddMove(int x, int y, int p) { |
bool Pod::AddMove(int x, int y, int p) { |
388 |
// return 0 if can't add, 1 if success |
// return 0 if can't add, 1 if success |
389 |
|
|
414 |
moves.erase( moves.begin()+p ); |
moves.erase( moves.begin()+p ); |
415 |
return 1; |
return 1; |
416 |
} |
} |
|
|
|
|
void Pod::SetEngage(int x) { |
|
|
engage = x; |
|
|
} |
|
|
|
|
|
void Pod::SetAvoid(int x){ |
|
|
avoid = x; |
|
|
} |
|
|
|
|
|
bool Pod::Place(int x, int y) { |
|
|
x_pos = x; |
|
|
y_pos = y; |
|
|
bool bad = map->SetOccu(x,y,*this); |
|
|
if (bad) {return 0;} |
|
|
else {return 1;} |
|
|
} |
|
417 |
// ================================== |
// ================================== |
418 |
|
|
419 |
|
|
425 |
|
|
426 |
|
|
427 |
|
|
428 |
|
|
429 |
// MOVEMENT FUNCTIONS |
// MOVEMENT FUNCTIONS |
430 |
// ================================== |
// ================================== |
431 |
|
|
432 |
bool Pod::Move() { |
bool Pod::Move() { |
433 |
|
// returns zero if can't move, 1 if success |
434 |
if (moves.size() == 0) {return 0;} |
if (moves.size() == 0) {return 0;} |
435 |
if (CreatePath(x_pos, y_pos, Moves(0)->GetX(), Moves(0)->GetY()) == 0) { |
if (CreatePath(x_pos, y_pos, Moves(0)->GetX(), Moves(0)->GetY()) == 0) { |
436 |
cout << "[" << GetName() << "]: No Path - try again" << endl; |
cout << "[" << GetName() << "]: No Path - try again" << endl; |
449 |
bool Pod::CreatePath(int x1, int y1, int x2, int y2) { |
bool Pod::CreatePath(int x1, int y1, int x2, int y2) { |
450 |
// return 1 if path was made, 0 if path could not be found |
// return 1 if path was made, 0 if path could not be found |
451 |
|
|
452 |
// TODO: ERROR: checl perams |
// TODO: ERROR: check perams |
453 |
|
|
454 |
int timeout = ( ( map->GetCols() * map->GetRows() ) / 1 ); |
int timeout = ( ( themap->GetCols() * themap->GetRows() ) / 1 ); |
455 |
|
|
456 |
// set pod pointer for all mapsearch nodes |
// set pod pointer for all mapsearch nodes |
457 |
// do this every time we search because many other pods are searching too and they all override eachother |
// do this every time we search because many other pods are searching too and they all override eachother |
459 |
|
|
460 |
// set the pointer to the map if it hasn't already been |
// set the pointer to the map if it hasn't already been |
461 |
// FIXME - we dont need this here every time. just once at the beginning of program. remove and add error trap |
// FIXME - we dont need this here every time. just once at the beginning of program. remove and add error trap |
462 |
MapSearchNode_Pod::SetMapPointer(*map); |
//MapSearchNode_Pod::SetMapPointer(*themap); |
463 |
|
|
464 |
// if we are starting a new search, we are obviously done with the old one, so free the nodes up |
// if we are starting a new search, we are obviously done with the old one, so free the nodes up |
465 |
if (path != NULL) {path->FreeSolutionNodes();} |
if (path != NULL) {path->FreeSolutionNodes();} |
529 |
} |
} |
530 |
|
|
531 |
// can i afford to move there? |
// can i afford to move there? |
532 |
if (map->GetRoadQ(is->x, is->y) <= spd_allot) { |
if (themap->GetRoadQ(is->x, is->y) <= spd_allot) { |
533 |
spd_allot -= map->GetRoadQ(is->x, is->y); // subtract road cost from allotment |
spd_allot -= themap->GetRoadQ(is->x, is->y); // subtract road cost from allotment |
534 |
} |
} |
535 |
else {break; } // can't afford to move anymore |
else {break; } // can't afford to move anymore |
536 |
|
|
537 |
// if it's occupied and we were not ready for that, STOP |
// if it's occupied and we were not ready for that, STOP |
538 |
// this is here because the pathfinder will not figure in occupied tiles into the path |
// this is here because the pathfinder will not figure in occupied tiles into the path |
539 |
// *UNLESS* it's the goal state (enemy target intercept for instance) |
// *UNLESS* it's the goal state (enemy target intercept for instance) |
540 |
Pod* occupied = map->GetOccu(is->x, is->y); |
Pod* occupied = themap->GetOccu(is->x, is->y); |
541 |
if (occupied != NULL) { |
if (occupied != NULL) { |
542 |
path->FreeSolutionNodes(); |
path->FreeSolutionNodes(); |
543 |
path = NULL; |
path = NULL; |
545 |
} |
} |
546 |
|
|
547 |
// retie all the occupation and positional markers |
// retie all the occupation and positional markers |
548 |
map->SetOccu(is->x, is->y, *this ); // move the occupation to the new tile |
themap->SetOccu(is->x, is->y, *this ); // move the occupation to the new tile |
549 |
map->UnsetOccu(was->x, was->y); // NULL the old one, it's vacant |
themap->UnsetOccu(was->x, was->y); // NULL the old one, it's vacant |
550 |
x_pos = is->x; // set internal positional markers |
x_pos = is->x; // set internal positional markers |
551 |
y_pos = is->y; |
y_pos = is->y; |
552 |
//---------------/\-------------- |
//---------------/\-------------- |
553 |
|
|
554 |
|
|
555 |
// trample road |
// trample road |
556 |
map->TrampleRoad(is->x, is->y); // TODO: maybe add trample amount depending on pod weight? |
themap->TrampleRoad(is->x, is->y, (size / ROAD_TRAMPLE_DIVISOR) ); // TODO: adjust trample weight (?) |
557 |
|
|
558 |
// TODO: pick up map specials |
// TODO: pick up map specials |
559 |
|
|
560 |
// timing loop and shell display |
// timing loop and shell display |
561 |
clock_t s = clock(); |
clock_t s = clock(); |
562 |
while ( (clock() - s) < TIMING_LOOP_DELAY) {continue;} // NOTE: unix dependent time ticks |
while ( (clock() - s) < TIMING_LOOP_DELAY) {continue;} // NOTE: unix dependent time ticks |
563 |
system("clear"); |
//system("clear"); |
564 |
map->PrintToScreen(); |
//map->PrintToScreen(); |
565 |
|
rm->GetActiveScreen()->MovePod(was->x, was->y, is->x, is->y); |
566 |
|
//cout << rm->GetTileSize(); |
567 |
|
|
568 |
// Engagement Prompt (will you marry me? :-) |
// Engagement Prompt (will you marry me? :-) |
569 |
// check for enemy occupations in each adjascent tile |
// check for enemy occupations in each adjascent tile |
571 |
int x_coords[] = {1,-1,0,0}; |
int x_coords[] = {1,-1,0,0}; |
572 |
int y_coords[] = {0,0,1,-1}; |
int y_coords[] = {0,0,1,-1}; |
573 |
for (int i=0; i < 4; i++) { |
for (int i=0; i < 4; i++) { |
574 |
if (map->IsValid(is->x + x_coords[i], is->y + y_coords[i]) == 0) {continue;} |
if (themap->IsValid(is->x + x_coords[i], is->y + y_coords[i]) == 0) {continue;} |
575 |
enemy = map->GetOccu(is->x + x_coords[i], is->y + y_coords[i]); |
enemy = themap->GetOccu(is->x + x_coords[i], is->y + y_coords[i]); |
576 |
if (enemy != NULL) { // if it's occupied |
if (enemy != NULL) { // if it's occupied |
577 |
if (enemy->GetAlign() != this->GetAlign()) { // if he's a bad guy |
if (enemy->GetAlign() != this->GetAlign()) { // if he's a bad guy |
578 |
PromptEngagement(); // let's fight! (or not) |
PromptEngagement(enemy); // let's fight! (or not) |
579 |
} |
} |
580 |
} |
} |
581 |
} |
} |
602 |
|
|
603 |
// MISC FUNCTIONS |
// MISC FUNCTIONS |
604 |
// ================================== |
// ================================== |
605 |
void Pod::PromptEngagement() { |
void Pod::PromptEngagement(Pod* enemy) { |
606 |
/* TODO: function not made yet */ |
/* TODO: function not made yet */ |
607 |
cout << "Found Adjascent Enemy Pod! Shall i tear his arms off, sir?\n"; |
//cout << "Found Adjascent Enemy Pod! Shall i tear his arms off, sir?\n"; |
608 |
|
|
609 |
// decide to fight depending on what engagement set to. |
// decide to fight depending on what engagement set to. |
610 |
// send signal to the other pod so he can fight us if he wants |
if (0) { /*fight*/ } |
611 |
|
|
612 |
|
// otherwise, send signal to the other pod so he can fight us if he wants |
613 |
|
else { |
614 |
|
msgport->Send(enemy, MSG_ATTACK); |
615 |
|
} |
616 |
|
|
617 |
} |
} |
618 |
|
|
619 |
// ================================== |
// ================================== |