AgentsCoverHeatmap.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. // Agents take Cover.
  2. // Todo :
  3. //gfx
  4. // agents shoot back
  5. // collision bullets vs entities
  6. #include "raylib.h"
  7. #include <math.h>
  8. enum tiles{FLOOR,WALL};
  9. #define MAP_WIDTH 40
  10. #define MAP_HEIGHT 20
  11. #define MAX_TURRETS 1
  12. #define TURRET_TURNSPEED 0.01
  13. #define MAX_BULLETS 128
  14. #define BULLET_SPEED 3
  15. #define TURRET_TARGET_TIME 600
  16. #define MAX_AGENTS 15
  17. #define MAX_PATH 100024
  18. static int screenWidth,screenHeight;
  19. // This is our tile map. Note that [y][x]!!
  20. // 1 = wall
  21. int tempmap[10][20] = { {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
  22. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  23. {1,0,0,1,1,0,0,0,1,1,1,1,0,0,0,1,1,0,0,1},
  24. {1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1},
  25. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  26. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  27. {1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1},
  28. {1,0,0,1,1,0,0,0,1,1,1,1,0,0,0,1,1,0,0,1},
  29. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  30. {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}};
  31. int map[MAP_HEIGHT][MAP_WIDTH]={0};
  32. // heat map..
  33. // The heat map is used here to let the agents know the map area heated is dangerous and not
  34. // to be traveled on. (influence mapping.)
  35. float hmap[MAP_HEIGHT][MAP_WIDTH]={0};
  36. // cover position map..
  37. // The cover map is a map where positions are where bullets from the enemy do not have effect. (behind walls)
  38. // I find them by simulating the turret shooting in every angle.
  39. bool cmap[MAP_HEIGHT][MAP_WIDTH]={0};
  40. // coverislands
  41. // coverspots connected to each other have a unique number.
  42. // These are used to let the agents run from one island to another
  43. int cimap[MAP_HEIGHT][MAP_WIDTH]={0};
  44. static int numislands;
  45. //path map
  46. int pathmap[MAP_HEIGHT][MAP_WIDTH]={0};
  47. float tileWidth,tileHeight;
  48. typedef struct turret{
  49. float x,y;
  50. float angle;
  51. float direction;
  52. int burst;
  53. bool targetactive;
  54. int targetx,targety;
  55. int targettime;
  56. }turret;
  57. static struct turret arr_turret[MAX_TURRETS];
  58. typedef struct bullet{
  59. bool active;
  60. float x,y;
  61. float angle;
  62. int speed;
  63. }bullet;
  64. static struct bullet arr_bullet[MAX_BULLETS];
  65. typedef struct agent{
  66. bool active;
  67. float x,y;
  68. int speed;
  69. int pathx[1024];
  70. int pathy[1024];
  71. int pathloc;
  72. int pathlen;
  73. int myisland;
  74. }agent;
  75. static struct agent arr_agent[MAX_AGENTS];
  76. typedef struct pathnode{
  77. int x;
  78. int y;
  79. }pathnode;
  80. static pathnode arr_path[MAX_PATH];
  81. static int arr_path_len;
  82. static void drawmap();
  83. static void drawturrets();
  84. static void updateturrets();
  85. static void drawbullets();
  86. static void updatebullets();
  87. static void shootbullet(int x, int y, float angle);
  88. static bool recttilecollide(int x,int y,int w, int h, int offsetx,int offsety);
  89. static bool rectsoverlap(int x1,int y1,int w1,int h1,int x2,int y2,int w2,int h2);
  90. static void drawheatmap();
  91. static void updateheatmap();
  92. static int orientation(int ax,int ay,int bx, int by, int cx, int cy);
  93. static void createcovermap();
  94. static void drawcovermap();
  95. static void drawcoverislands();
  96. static void createcoverislands();
  97. static void drawagents();
  98. static void updateagents();
  99. static bool agentfindpath(int agent, int island);
  100. int main(void)
  101. {
  102. // Initialization
  103. //--------------------------------------------------------------------------------------
  104. screenWidth = 800;
  105. screenHeight = 450;
  106. tileWidth = ceil((float)screenWidth/(float)MAP_WIDTH);
  107. tileHeight = ceil((float)screenHeight/(float)MAP_HEIGHT);
  108. // first let us copy the temp map into the main map(double size)
  109. for (int y=0;y<MAP_HEIGHT/2;y++){
  110. for(int x=0;x<MAP_WIDTH/2;x++){
  111. map[y*2][x*2]=tempmap[y][x];
  112. map[y*2+1][x*2]=tempmap[y][x];
  113. map[y*2][x*2+1]=tempmap[y][x];
  114. map[y*2+1][x*2+1]=tempmap[y][x];
  115. }
  116. }
  117. InitWindow(screenWidth, screenHeight, "raylib example.");
  118. SetTargetFPS(60); // Set our game to run at 60 frames-per-second
  119. //--------------------------------------------------------------------------------------
  120. // Our turret is placed in the center..
  121. arr_turret[0].x = 20;
  122. arr_turret[0].y = 10;
  123. arr_turret[0].angle = 0;
  124. arr_turret[0].direction = TURRET_TURNSPEED;
  125. arr_turret[0].burst=0;
  126. arr_turret[0].targetactive = true;
  127. arr_turret[0].targetx = 12;
  128. arr_turret[0].targety = 3;
  129. arr_turret[0].targettime=TURRET_TARGET_TIME;
  130. // create our covermap
  131. createcovermap();
  132. createcoverislands();
  133. for (int i=0;i<MAX_AGENTS;i++){
  134. arr_agent[i].active = true;
  135. arr_agent[i].x = 3*tileWidth;
  136. arr_agent[i].y = 3*tileHeight;
  137. arr_agent[i].speed = 2;
  138. arr_agent[i].myisland=1;
  139. arr_agent[i].pathloc=-1;
  140. arr_agent[i].pathlen=-1;
  141. }
  142. /* arr_agent[0].active = true;
  143. arr_agent[0].x = 3*tileWidth;
  144. arr_agent[0].y = 3*tileHeight;
  145. arr_agent[0].speed = 2;
  146. arr_agent[0].myisland=1;
  147. arr_agent[0].pathloc=-1;
  148. arr_agent[0].pathlen=-1;
  149. */
  150. // Main game loop
  151. while (!WindowShouldClose()) // Detect window close button or ESC key
  152. {
  153. // Update
  154. //----------------------------------------------------------------------------------
  155. updateturrets();
  156. updatebullets();
  157. updateheatmap();
  158. updateagents();
  159. // If the user presses the mouse then place new target on map at mpos;
  160. if(IsMouseButtonDown(0)){
  161. arr_turret[0].targetactive=true;
  162. arr_turret[0].targetx = GetMouseX()/tileWidth;
  163. arr_turret[0].targety = GetMouseY()/tileHeight;
  164. arr_turret[0].targettime=TURRET_TARGET_TIME;
  165. }
  166. //----------------------------------------------------------------------------------
  167. // Draw
  168. //----------------------------------------------------------------------------------
  169. BeginDrawing();
  170. ClearBackground(RAYWHITE);
  171. drawheatmap();
  172. drawcovermap();
  173. drawcoverislands();
  174. drawmap();
  175. drawturrets();
  176. drawbullets();
  177. //draw the path..
  178. for(int i=0;i<arr_path_len-1;i++){
  179. DrawRectangle(arr_path[i].x*tileWidth,arr_path[i].y*tileHeight,tileWidth,tileHeight,YELLOW);
  180. }
  181. drawagents();
  182. DrawText("Press mouse to place target.. Space to path..",0,0,20,GRAY);
  183. DrawRectangle(0,screenHeight-44,screenWidth,28,DARKGRAY);
  184. DrawText("Heatmap",130,screenHeight-40,20,WHITE);
  185. DrawRectangle(100,screenHeight-40,20,20,RED);
  186. DrawRectangle(screenWidth/2,screenHeight-40,20,20,GREEN);
  187. DrawText("Covermap",screenWidth/2+30,screenHeight-40,20,WHITE);
  188. EndDrawing();
  189. //----------------------------------------------------------------------------------
  190. }
  191. // De-Initialization
  192. //--------------------------------------------------------------------------------------
  193. CloseWindow(); // Close window and OpenGL context
  194. //--------------------------------------------------------------------------------------
  195. return 0;
  196. }
  197. void drawmap(){
  198. for(int y=0;y<MAP_HEIGHT;y++){
  199. for(int x=0;x<MAP_WIDTH;x++){
  200. if(map[y][x]==1){
  201. DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,BLACK);
  202. }
  203. }
  204. }
  205. }
  206. void drawturrets(){
  207. for(int i=0;i<MAX_TURRETS;i++){
  208. int x = arr_turret[i].x*tileWidth;
  209. int y = arr_turret[i].y*tileHeight;
  210. float angle = arr_turret[i].angle;
  211. int x1 = x+tileWidth/2;
  212. int y1 = y+tileHeight/2;
  213. int x2 = x1+cos(angle)*(tileWidth);
  214. int y2 = y1+sin(angle)*(tileHeight);
  215. DrawRectangle(x,y,tileWidth,tileHeight,BLUE);
  216. DrawLineEx((Vector2){x1,y1},(Vector2){x2,y2},6,RED);
  217. // draw target if active
  218. if(arr_turret[i].targetactive){
  219. x = arr_turret[i].targetx*tileWidth;
  220. y = arr_turret[i].targety*tileHeight;
  221. DrawRectangle(x,y,tileWidth,tileHeight,BLUE);
  222. }
  223. }
  224. }
  225. void updateturrets(){
  226. for(int i=0;i<MAX_TURRETS;i++){
  227. // If there is no target the turn randomly
  228. if(arr_turret[i].targetactive==false && GetRandomValue(0,500)<2){
  229. arr_turret[i].direction = -arr_turret[i].direction;
  230. }
  231. // If there is a target then turn towards taget.
  232. if(arr_turret[i].targetactive){
  233. int x=(arr_turret[i].x*tileWidth);
  234. int y=(arr_turret[i].y*tileHeight);
  235. int oriented=orientation( x,
  236. y,
  237. x+cos(arr_turret[i].angle)*tileWidth*12,
  238. y+sin(arr_turret[i].angle)*tileHeight*12,
  239. arr_turret[i].targetx*tileWidth,
  240. arr_turret[i].targety*tileHeight);
  241. if(oriented==-1){
  242. arr_turret[i].direction=-TURRET_TURNSPEED;
  243. }else if(oriented==1){
  244. arr_turret[i].direction=TURRET_TURNSPEED;
  245. }
  246. }
  247. // rotate the turret
  248. arr_turret[i].angle+=arr_turret[i].direction;
  249. if(arr_turret[i].angle>PI*2.0f){
  250. arr_turret[i].angle=0;
  251. }
  252. if(arr_turret[i].angle<0){
  253. arr_turret[i].angle=PI*2.0f;
  254. }
  255. // shoot bullets
  256. if(GetRandomValue(0,60)<2 || arr_turret[i].burst>0){
  257. if(arr_turret[i].burst>0){
  258. arr_turret[i].burst-=1;
  259. }else{
  260. if(GetRandomValue(0,20)<2)arr_turret[i].burst=5;
  261. }
  262. int bx = arr_turret[i].x*tileWidth;
  263. int by = arr_turret[i].y*tileHeight;
  264. shootbullet( (bx+tileWidth/2)+(cos(arr_turret[i].angle)*tileWidth),
  265. (by+tileHeight/2)+(sin(arr_turret[i].angle)*tileHeight),
  266. arr_turret[i].angle);
  267. }
  268. // if target is active then decrease that time
  269. if(arr_turret[i].targetactive){
  270. arr_turret[i].targettime-=1;
  271. if(arr_turret[i].targettime<=0){
  272. arr_turret[i].targetactive = false;
  273. }
  274. }
  275. }
  276. }
  277. void drawbullets(){
  278. for(int i=0;i<MAX_BULLETS;i++){
  279. if(arr_bullet[i].active==false)continue;
  280. DrawRectangle(arr_bullet[i].x,arr_bullet[i].y,tileWidth/4,tileHeight/4,BLACK);
  281. DrawRectangle(arr_bullet[i].x+1,arr_bullet[i].y+1,tileWidth/4-2,tileHeight/4-2,YELLOW);
  282. }
  283. }
  284. void updatebullets(){
  285. for(int i=0;i<MAX_BULLETS;i++){
  286. if(arr_bullet[i].active==false)continue;
  287. for(int speed=0;speed<arr_bullet[i].speed;speed++){
  288. arr_bullet[i].x += cos(arr_bullet[i].angle)*1;
  289. arr_bullet[i].y += sin(arr_bullet[i].angle)*1;
  290. // if outside screen then disable bullet.
  291. if( arr_bullet[i].x<0 ||
  292. arr_bullet[i].x>screenWidth ||
  293. arr_bullet[i].y<0 ||
  294. arr_bullet[i].y>screenHeight){
  295. arr_bullet[i].active = false;
  296. }
  297. if(recttilecollide( arr_bullet[i].x,
  298. arr_bullet[i].y,
  299. tileWidth/4,
  300. tileHeight/4,
  301. 0,0)){
  302. arr_bullet[i].active=false;
  303. }
  304. }
  305. }
  306. }
  307. void shootbullet(int x,int y,float angle){
  308. for(int i=0;i<MAX_BULLETS;i++){
  309. if(arr_bullet[i].active==false){
  310. arr_bullet[i].active = true;
  311. arr_bullet[i].x = x;
  312. arr_bullet[i].y = y;
  313. arr_bullet[i].angle = angle;
  314. arr_bullet[i].speed = BULLET_SPEED;
  315. return;
  316. }
  317. }
  318. }
  319. //Unit collide with solid blocks true/false
  320. bool recttilecollide(int x,int y,int w, int h, int offsetx,int offsety){
  321. int cx = (x+offsetx)/tileWidth;
  322. int cy = (y+offsety)/tileHeight;
  323. for(int y2=cy-1; y2<cy+5;y2++){
  324. for(int x2=cx-1; x2<cx+5;x2++){
  325. if(x2>=0 && x2<MAP_WIDTH && y2>=0 && y2<MAP_HEIGHT){
  326. if(map[y2][x2] == 1){
  327. int x3 = (x2)*tileWidth;
  328. int y3 = (y2)*tileHeight;
  329. if(rectsoverlap(x+offsetx,y+offsety,w,h,x3,y3,tileWidth,tileHeight)){
  330. return true;
  331. }
  332. }
  333. }
  334. }}
  335. return false;
  336. }
  337. // Rectangles overlap
  338. bool rectsoverlap(int x1,int y1,int w1,int h1,int x2,int y2,int w2,int h2){
  339. if(x1 >= (x2 + w2) || (x1 + w1) <= x2) return false;
  340. if(y1 >= (y2 + h2) || (y1 + h1) <= y2) return false;
  341. return true;
  342. }
  343. void updateheatmap(){
  344. // increase heat below bullets
  345. for(int i=0;i<MAX_BULLETS;i++){
  346. if(arr_bullet[i].active==false)continue;
  347. int x=arr_bullet[i].x/tileWidth;
  348. int y=arr_bullet[i].y/tileHeight;
  349. if(hmap[y][x]<255)hmap[y][x]+=5;
  350. if(hmap[y-1][x]<255)hmap[y-1][x]+=1.5;
  351. if(hmap[y][x+1]<255)hmap[y][x+1]+=1.5;
  352. if(hmap[y+1][x]<255)hmap[y+1][x]+=1.5;
  353. if(hmap[y][x-1]<255)hmap[y][x-1]+=1.5;
  354. if(hmap[y-2][x]<255)hmap[y-2][x]+=1.0;
  355. if(hmap[y][x+2]<255)hmap[y][x+2]+=1.0;
  356. if(hmap[y+2][x]<255)hmap[y+2][x]+=1.0;
  357. if(hmap[y][x-2]<255)hmap[y][x-2]+=1.0;
  358. }
  359. // decrease the heat..
  360. for(int y=0;y<MAP_HEIGHT;y++){
  361. for(int x=0;x<MAP_WIDTH;x++){
  362. if(hmap[y][x]==0)continue;
  363. hmap[y][x]-=0.5;
  364. if(hmap[y][x]<0.1)hmap[y][x]=0;
  365. }}
  366. }
  367. void drawheatmap(){
  368. for(int y=0;y<MAP_HEIGHT;y++){
  369. for(int x=0;x<MAP_WIDTH;x++){
  370. if(hmap[y][x]==0)continue;
  371. Color col = {hmap[y][x],0,0,25};
  372. DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,col);
  373. }
  374. }
  375. }
  376. //
  377. // This is the orientation function. It returns -1 if the point is left of the inputted line.
  378. // 0 if on the same and 1 if on the right of the line.
  379. // aa,bb,point
  380. int orientation(int ax,int ay,int bx, int by, int cx, int cy){
  381. if(((bx-ax)*(cy-ay)-(by-ay)*(cx-ax))<0)return -1;
  382. if(((bx-ax)*(cy-ay)-(by-ay)*(cx-ax))>0)return 1;
  383. return 0;
  384. }
  385. void createcovermap(){
  386. for(int i=0;i<MAX_TURRETS;i++){
  387. // Find all cover positions
  388. for(float angle=0;angle<PI*2.0f;angle+=0.03f){
  389. float x=(float)arr_turret[i].x*tileWidth;
  390. float y=(float)arr_turret[i].y*tileHeight;
  391. for(int z=0;z<300;z++){
  392. x+=cos(angle);
  393. y+=sin(angle);
  394. int x2 = (float)x/(float)tileWidth;
  395. int y2 = (float)y/(float)tileHeight;
  396. if(x2<1 || y2<1 || x2>=MAP_WIDTH || y2>=MAP_HEIGHT){
  397. goto LABEL;
  398. }
  399. if(recttilecollide(x,y,1,1,0,0)){
  400. while(recttilecollide(x,y,1,1,0,0)){
  401. x+=cos(angle);
  402. y+=sin(angle);
  403. x2 = (float)x/(float)tileWidth;
  404. y2 = (float)y/(float)tileHeight;
  405. if(x2<1 || y2<1 || x2>=MAP_WIDTH || y2>=MAP_HEIGHT){
  406. goto LABEL;
  407. }
  408. }
  409. cmap[y2][x2] = true;
  410. goto LABEL;
  411. }
  412. }
  413. LABEL:{}
  414. }
  415. // Remove edge cases.
  416. for(float angle=0;angle<PI*2.0f;angle+=0.03f){
  417. float x=(float)arr_turret[i].x*tileWidth;
  418. float y=(float)arr_turret[i].y*tileHeight;
  419. for(int z=0;z<300;z++){
  420. x+=cos(angle);
  421. y+=sin(angle);
  422. int x2 = (float)x/(float)tileWidth;
  423. int y2 = (float)y/(float)tileHeight;
  424. if(x2<0 || y2<0 || x2>=MAP_WIDTH || y2>=MAP_HEIGHT){
  425. goto LABEL2;
  426. }
  427. cmap[y2][x2]=false;
  428. if(recttilecollide(x,y,1,1,0,0)){
  429. goto LABEL2;
  430. }
  431. }
  432. LABEL2:{}
  433. }
  434. }
  435. }
  436. void drawcovermap(){
  437. for(int y=0;y<MAP_HEIGHT;y++){
  438. for(int x=0;x<MAP_WIDTH;x++){
  439. if(cmap[y][x]==false)continue;
  440. DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,GREEN);
  441. }
  442. }
  443. }
  444. void drawcoverislands(){
  445. for(int y=0;y<MAP_HEIGHT;y++){
  446. for(int x=0;x<MAP_WIDTH;x++){
  447. if(cimap[y][x]==0)continue;
  448. DrawText(FormatText("%i",cimap[y][x]),x*tileWidth,y*tileHeight,15,BLACK);
  449. }}
  450. }
  451. void createcoverislands(){
  452. int island=1;
  453. for(int y=0;y<MAP_HEIGHT;y++){
  454. for(int x=0;x<MAP_WIDTH;x++){
  455. if(cmap[y][x]==true && cimap[y][x]==0){
  456. //flood
  457. cimap[y][x]=island;
  458. int mx[200];
  459. int my[200];
  460. int mc=0;
  461. mx[mc]=x;
  462. my[mc]=y;
  463. mc++;
  464. while(mc>0){
  465. mc--;
  466. int fx=mx[mc];
  467. int fy=my[mc];
  468. for(int zy=fy-1;zy<fy+2;zy++){
  469. for(int zx=fx-1;zx<fx+2;zx++){
  470. if(zx<0 || zy<0 || zx>=MAP_WIDTH || zy>MAP_HEIGHT)continue;
  471. if(cmap[zy][zx]==true && cimap[zy][zx]==0){
  472. mx[mc]=zx;
  473. my[mc]=zy;
  474. cimap[zy][zx]=island;
  475. mc++;
  476. }
  477. }
  478. }
  479. }
  480. island++;
  481. numislands=island;
  482. }
  483. }}
  484. }
  485. void drawagents(){
  486. for(int i=0;i<MAX_AGENTS;i++){
  487. if(arr_agent[i].active==false)continue;
  488. DrawRectangle(arr_agent[i].x,arr_agent[i].y,tileWidth,tileHeight,RED);
  489. }
  490. }
  491. void updateagents(){
  492. for(int a=0;a<MAX_AGENTS;a++){
  493. if(arr_agent[a].active==false)continue;
  494. // Move agent from path location to next path location(smooth)
  495. if(arr_agent[a].pathloc>=0){
  496. for(int spd=0;spd<arr_agent[a].speed;spd++){
  497. if(arr_agent[a].x<arr_agent[a].pathx[arr_agent[a].pathloc]*tileWidth)arr_agent[a].x+=1;
  498. if(arr_agent[a].x>arr_agent[a].pathx[arr_agent[a].pathloc]*tileWidth)arr_agent[a].x-=1;
  499. if(arr_agent[a].y<arr_agent[a].pathy[arr_agent[a].pathloc]*tileHeight)arr_agent[a].y+=1;
  500. if(arr_agent[a].y>arr_agent[a].pathy[arr_agent[a].pathloc]*tileHeight)arr_agent[a].y-=1;
  501. if( arr_agent[a].x==arr_agent[a].pathx[arr_agent[a].pathloc]*tileWidth &&
  502. arr_agent[a].y==arr_agent[a].pathy[arr_agent[a].pathloc]*tileHeight){
  503. arr_agent[a].pathloc--;
  504. break;
  505. }
  506. }
  507. }
  508. // If the agent is at the end of its path.
  509. // move to next cover position.
  510. bool planpath = false;
  511. if(arr_agent[a].pathloc == -1 && GetRandomValue(0,1000)<10 )planpath=true;
  512. if(planpath==true){
  513. for(int shuffle=0;shuffle<5;shuffle++){
  514. int i=GetRandomValue(1,numislands);
  515. if(arr_agent[a].myisland!=i && agentfindpath(a,i)==true){
  516. arr_agent[a].myisland = i;
  517. arr_agent[a].pathlen = arr_path_len;
  518. arr_agent[a].pathloc = arr_path_len-1;
  519. for(int p=0;p<arr_path_len;p++){
  520. arr_agent[a].pathx[p] = arr_path[p].x;
  521. arr_agent[a].pathy[p] = arr_path[p].y;
  522. }
  523. return;
  524. }
  525. }
  526. }
  527. }
  528. }
  529. bool agentfindpath(int agent, int island){
  530. // 4 way search! left/up/down/right
  531. // int dx[4]={ 0,1,0,-1};
  532. // int dy[4]={-1,0,1,0};
  533. // 8 way search! left/up/down/right
  534. int dx[8]={-1,0,1,-1,1,-1,0,1};
  535. int dy[8]={-1,-1,-1,0,0,1,1,1};
  536. //find closest cover position that we are currently not ontop of.
  537. //
  538. // find a start and end location.
  539. //
  540. for(int y=0;y<MAP_HEIGHT;y++){
  541. for(int x=0;x<MAP_WIDTH;x++){
  542. pathmap[y][x]=0;
  543. }}
  544. int startx,starty,endx,endy;
  545. //flood to find closest cover position
  546. startx = arr_agent[agent].x/tileWidth;
  547. starty = arr_agent[agent].y/tileHeight;
  548. // find the destination coordinates.
  549. bool exitloop=false;
  550. int failloop=0;
  551. while(exitloop==false){
  552. int x = GetRandomValue(0,MAP_WIDTH);
  553. int y = GetRandomValue(0,MAP_HEIGHT);
  554. if(cimap[y][x]==island){
  555. endx = x;
  556. endy = y;
  557. exitloop=true;
  558. }
  559. failloop++;
  560. if(failloop>1000000)return false;
  561. }
  562. //
  563. // Flood the map with distances from the start.
  564. //
  565. struct pathnode list[MAX_PATH];
  566. //
  567. // We store the distance on each map cell if there is no wall there.
  568. //
  569. pathmap[starty][startx]=1;
  570. int listlen=0;
  571. list[listlen].x=startx;
  572. list[listlen].y=starty;
  573. listlen+=1;
  574. int failed=0;
  575. // While we have a list to work with
  576. while(listlen>0){
  577. // Take the first value from the array.
  578. int x1=list[0].x;
  579. int y1=list[0].y;
  580. // shift all up.
  581. for(int i=0;i<listlen;i++){
  582. list[i].x = list[i+1].x;
  583. list[i].y = list[i+1].y;
  584. }
  585. if(x1==endx && y1==endy){
  586. break;
  587. }
  588. // Decrease list length
  589. listlen-=1;
  590. //
  591. // Here we check around our current position.
  592. for(int i=0;i<8;i++){
  593. int nx = x1+dx[i];
  594. int ny = y1+dy[i];
  595. if(nx<0 || ny<0 || nx>= MAP_WIDTH || ny>= MAP_HEIGHT)continue;
  596. // If we can get there then put the new distance there and add this position
  597. // to the list.
  598. if(pathmap[ny][nx]==0 && map[ny][nx]==0){
  599. pathmap[ny][nx]=pathmap[y1][x1]+1;
  600. // add to last
  601. //
  602. list[listlen].x = nx;
  603. list[listlen].y = ny;
  604. listlen++;
  605. //
  606. }
  607. }
  608. // Error?
  609. failed+=1;
  610. if(failed>160000)return;
  611. }
  612. //
  613. // Here we create the actual path.
  614. //
  615. arr_path_len = 0;
  616. int x1=endx;
  617. int y1=endy;
  618. arr_path[0].x = x1;
  619. arr_path[0].y = y1;
  620. arr_path_len+=1;
  621. failed=0;
  622. // While distance is greater than 1
  623. while(pathmap[y1][x1]>1){
  624. int nx=0;
  625. int ny=0;
  626. // Get the current distance
  627. int lowest = pathmap[y1][x1];
  628. for(int i=0;i<8;i++){
  629. int x2=x1+dx[i];
  630. int y2=y1+dy[i];
  631. if(x2<0 || y2 <0 || x2>=MAP_WIDTH || y2>= MAP_HEIGHT )continue; // stay in bounds of array
  632. if(pathmap[y2][x2]>0 && pathmap[y2][x2]<lowest){ //if there is a map distance and if it is lower than the lowest variable
  633. lowest = pathmap[y2][x2];
  634. nx = x2;
  635. ny = y2;
  636. }
  637. }
  638. // store our new location
  639. x1 = nx;
  640. y1 = ny;
  641. if(hmap[y1][x1]>0){
  642. arr_path_len=0;
  643. return false;
  644. }
  645. // add to the path struct
  646. arr_path[arr_path_len].x = nx;
  647. arr_path[arr_path_len].y = ny;
  648. // add to length
  649. arr_path_len+=1;
  650. // error?
  651. failed+=1;
  652. if(failed>15000)return;
  653. }
  654. arr_agent[agent].x = startx*tileWidth;
  655. arr_agent[agent].y = starty*tileHeight;
  656. return true;
  657. }