1 #ifdef _WIN32
2 #include "windows.h"
3 #endif
4
5 #include "string.h"
6 #include <stdlib.h>
7 #include "stdio.h"
8 #include "math.h"
9
10 #include "GL/gl.h"
11 #include "GL/glu.h"
12 #include "GL/glut.h"
13 #include "SDL/SDL.h"
14 #include "SDL/SDL_mixer.h"
15
16 #include "list.h"
17 #include "vector.h"
18 #include "cmc.h"
19 #include "3dobject.h"
20 #include "shadow3dobject.h"
21 #include "piece3dobject.h"
22 #include "myglutaux.h"
23 #include "nether.h"
24
25 /* Artificial Intelligence variables: */
26 /*
27
28 int *discreetmap; -> - Will keep a discreet copy of the map, telling whether a robot can occupy a position
29 or not.
30 - Each cell of the original map, transform to a set of 2x2 cells of this new map, so
31 each 2x2 square of this cells correspond to one of the positions where a robot can
32 be.
33
34 int *bk_discreetmap; -> just contains the background.
35
36 AI_OPERATOR *searchmap; -> In this map is where the search process will be performed.
37
38 */
39
40 const int WE_SEARCH_DEPTH=12; /* Search depth for robots with ELECTRONICS */
41 //const int WE_SEARCH_DEPTH=80; /* Search depth for robots with ELECTRONICS */
42 const int WOE_SEARCH_DEPTH=4; /* Search depth for robots without ELECTRONICS */
43
44 const int xd[4]={ 1, 0,-1, 0};
45 const int yd[4]={ 0, 1, 0,-1};
46 const int xd2[4]={ 0, 0,-1, 0};
47 const int yd2[4]={ 0, 0, 0,-1};
48 const int xd3[4]={ 1, 0, 1, 0};
49 const int yd3[4]={ 0, 1, 0, 1};
50 const int dangle[4]={0,90,180,270};
51
52
53 extern FILE *debug_fp;
54
robot_zone(Vector pos,int * x,int * y,int * dx,int * dy)55 void robot_zone(Vector pos,int *x,int *y,int *dx,int *dy)
56 {
57 *x=int((pos.x-0.5)/0.5);
58 *y=int((pos.y-0.5)/0.5);
59
60 if ((int(pos.x*256)%128)==0) *dx=2;
61 else *dx=3;
62 if ((int(pos.y*256)%128)==0) *dy=2;
63 else *dy=3;
64 } /* robot_zone */
65
66
fill_zone(int * map,int w,int val,int x,int y,int dx,int dy)67 void fill_zone(int *map,int w,int val,int x,int y,int dx,int dy)
68 {
69 int i,j;
70
71 for(i=0;i<dx;i++) {
72 for(j=0;j<dy;j++) {
73 map[(y+j)*w+(x+i)]=val;
74 } /* for */
75 } /* for */
76 } /* fill_zone */
77
78
AI_precomputations(void)79 void NETHER::AI_precomputations(void)
80 {
81 int i;
82 int x,y;
83
84 discreetmap=new int[(map_w*2)*(map_h*2)];
85 bk_discreetmap=new int[(map_w*2)*(map_h*2)];
86 searchmap=new AI_OPERATOR *[(map_w*2)*(map_h*2)];
87 atackmap=new int[(map_w*2)*(map_h*2)];
88 for(i=0;i<(map_w*2)*(map_h*2);i++) {
89 searchmap[i]=new AI_OPERATOR();
90 searchmap[i]->used=false;
91 atackmap[i]=0;
92 } /* for */
93
94 /* Setup the terrains for the new map: */
95 for(y=0;y<map_h;y++) {
96 for(x=0;x<map_w;x++) {
97 fill_zone(discreetmap,map_w*2,MapTerrain(float(x),float(y)),x*2,y*2,2,2);
98 fill_zone(bk_discreetmap,map_w*2,MapTerrain(float(x),float(y)),x*2,y*2,2,2);
99 } /* for */
100 } /* for */
101
102 /* Transfer all the buildings to the new map: */
103 {
104 List<BUILDING> l;
105 BUILDING *b;
106
107 l.Instance(buildings);
108 l.Rewind();
109
110 while(l.Iterate(b)) {
111 x=int(b->pos.x/0.5);
112 y=int(b->pos.y/0.5);
113 fill_zone(discreetmap,map_w*2,T_BUILDING,x,y,2,2);
114 } /* while */
115 }
116 } /* NETHER::AI_precomputations */
117
118
AI_deleteprecomputations(void)119 void NETHER::AI_deleteprecomputations(void)
120 {
121 int i;
122
123 delete discreetmap;
124 discreetmap=0;
125 delete bk_discreetmap;
126 bk_discreetmap=0;
127 for(i=0;i<map_w*2*map_h*2;i++) {
128 delete searchmap[i];
129 searchmap[i]=0;
130 } /* for */
131 delete searchmap;
132 searchmap=0;
133 } /* NETHER::AI_deleteprecomputations */
134
135
AI_removebuilding(Vector pos)136 void NETHER::AI_removebuilding(Vector pos)
137 {
138 int i,j;
139 int x,y;
140
141 x=int(pos.x/0.5);
142 y=int(pos.y/0.5);
143
144 for(i=0;i<2;i++) {
145 for(j=0;j<2;j++) {
146 discreetmap[(y+j)*(map_w*2)+(x+i)]=bk_discreetmap[(y+j)*(map_w*2)+(x+i)];
147 } /* for */
148 } /* for */
149 } /* NETHER::AI_removebuilding */
150
151
AI_release(void)152 void NETHER::AI_release(void)
153 {
154 delete discreetmap;
155 discreetmap=0;
156 } /* NETHER::AI_release */
157
158
AI_newrobot(Vector pos,int owner)159 void NETHER::AI_newrobot(Vector pos,int owner)
160 {
161 int x,y,dx,dy;
162
163 robot_zone(pos,&x,&y,&dx,&dy);
164 if (owner==0) fill_zone(discreetmap,map_w*2,T_ROBOT,x,y,dx,dy);
165 else fill_zone(discreetmap,map_w*2,T_EROBOT,x,y,dx,dy);
166 } /* NETHER::AI_newrobot */
167
168
AI_killrobot(Vector pos)169 int NETHER::AI_killrobot(Vector pos)
170 {
171 int i,j;
172 int x,y,dx,dy;
173 int owner;
174
175 robot_zone(pos,&x,&y,&dx,&dy);
176 owner=discreetmap[y*(map_w*2)+x];
177 for(i=0;i<dx;i++) {
178 for(j=0;j<dy;j++) {
179 discreetmap[(y+j)*(map_w*2)+(x+i)]=bk_discreetmap[(y+j)*(map_w*2)+(x+i)];
180 } /* for */
181 } /* for */
182
183 return owner;
184 } /* NETHER::AI_killrobot */
185
186
AI_moverobot(Vector oldpos,Vector newpos,int owner)187 void NETHER::AI_moverobot(Vector oldpos,Vector newpos,int owner)
188 {
189 AI_killrobot(oldpos);
190 AI_newrobot(newpos,owner);
191 } /* NETHER::AI_moverobot */
192
193
AI_availableoperators(Vector pos,int angle,int traction,List<AI_OPERATOR> * l)194 void NETHER::AI_availableoperators(Vector pos,int angle,int traction,List<AI_OPERATOR> *l)
195 {
196 int i;
197 int x,y,dx,dy;
198 int terrain;
199 int n_turns;
200 int dif;
201 int cost;
202 AI_OPERATOR *op;
203
204 robot_zone(pos,&x,&y,&dx,&dy);
205
206 for(i=0;i<4;i++) {
207 terrain=AI_WorseMapTerrain(x+xd2[i],y+yd2[i],2+xd3[i],2+yd3[i]);
208 if (terrain<=T_HOLE &&
209 Walkable(traction,terrain)) {
210
211 /* Rotation cost: */
212 dif=dangle[i]-angle;
213 if (dif>360) dif-=360;
214 if (dif<0) dif+=360;
215 n_turns=0;
216 if (dif==90 || dif==270) n_turns=1;
217 if (dif==180) n_turns=2;
218 {
219 float tmp=float(RobotRotationSpeed(terrain,traction));
220 cost=n_turns*int(90/tmp);
221 }
222
223 /* Displacement cost: */
224 terrain=AI_WorseMapTerrain(x+xd[i],y+yd[i],2,2);
225 {
226 float tmp=RobotSpeed(terrain,traction);
227 cost+=int(0.5/tmp);
228 }
229
230 /* Build a new AI_operator: */
231 op=new AI_OPERATOR();
232 op->cost=cost;
233 op->previous=-1;
234 op->deadend=false;
235 if (dif==0) op->first_robotop=ROBOTOP_FORWARD;
236 if (dif==90) op->first_robotop=ROBOTOP_RIGHT;
237 if (dif==180) op->first_robotop=ROBOTOP_RIGHT;
238 if (dif==270) op->first_robotop=ROBOTOP_LEFT;
239 op->newpos=Vector(pos.x+xd[i]*0.5,pos.y+yd[i]*0.5,pos.z);
240 l->Add(op);
241 } /* if */
242 } /* for */
243 } /* NETHER::AI_availableoperators */
244
245
AI_expandoperators(int x,int y,int angle,int traction,int previous,int oldcost,int depth)246 bool NETHER::AI_expandoperators(int x,int y,int angle,int traction,int previous,int oldcost,int depth)
247 {
248 int newpos;
249 int i;
250 int terrain,terrain2;
251 int n_turns;
252 int dif;
253 int cost;
254 bool deadend=true;
255
256 for(i=0;i<4;i++) {
257 newpos=previous+xd[i]+yd[i]*(map_w*2);
258 if (newpos!=searchmap[previous]->previous) {
259 terrain=AI_WorseMapTerrain(x+xd2[i],y+yd2[i],2+xd3[i],2+yd3[i]);
260 if (terrain<=T_HOLE &&
261 Walkable(traction,terrain)) {
262 cost=oldcost;
263
264 /* Rotation cost: */
265 dif=dangle[i]-angle;
266 if (dif>360) dif-=360;
267 if (dif<0) dif+=360;
268 n_turns=0;
269 if (dif==90 || dif==270) n_turns=1;
270 if (dif==180) n_turns=2;
271
272 terrain2=AI_WorseMapTerrain(x,y,2,2);
273 cost+=n_turns*int(90/float(RobotRotationSpeed(traction,terrain2)));
274
275 /* Displacement cost: */
276 cost+=int(0.5/RobotSpeed(traction,terrain));
277
278 /* Replace the an old operator by a new one: */
279 if (!searchmap[newpos]->used ||
280 searchmap[newpos]->cost>cost) {
281
282 /* Set the new AI_operator: */
283 searchmap[newpos]->used=true;
284 searchmap[newpos]->cost=cost;
285 searchmap[newpos]->previous=previous;
286 searchmap[newpos]->deadend=false;
287 if (dif==0) searchmap[newpos]->first_robotop=ROBOTOP_FORWARD;
288 if (dif==90) searchmap[newpos]->first_robotop=ROBOTOP_RIGHT;
289 if (dif==180) searchmap[newpos]->first_robotop=ROBOTOP_RIGHT;
290 if (dif==270) searchmap[newpos]->first_robotop=ROBOTOP_LEFT;
291 searchmap[newpos]->newpos=Vector((x+xd[i])*0.5,(y+yd[i])*0.5,0);
292
293 /* Continue the search process: */
294 if (depth>0) {
295 if (!AI_expandoperators(x+xd[i],y+yd[i],dangle[i],traction,newpos,cost,depth-1)) {
296 deadend=false;
297 } /* if */
298 } else {
299 deadend=false;
300 } /* if */
301 } /* if */
302 } /* if */
303 } /* if */
304 } /* for */
305
306 searchmap[previous]->deadend=deadend;
307
308 return deadend;
309 } /* NETHER::AI_expandoperators */
310
311
AI_searchengine(Vector pos,int angle,int goaltype,Vector goalpos,int traction,int depth)312 int NETHER::AI_searchengine(Vector pos,int angle,int goaltype,Vector goalpos,int traction,int depth)
313 {
314 int offs;
315 int x,y,dx,dy;
316
317 #ifdef _WRITE_REPORT_
318 fprintf(debug_fp,"Expanding de search tree\n");
319 fflush(debug_fp);
320 #endif
321
322 /* Expand the search tree: */
323 robot_zone(pos,&x,&y,&dx,&dy);
324
325 /* Build a new AI_operator: */
326 offs=y*(map_w*2)+x;
327 searchmap[offs]->used=true;
328 searchmap[offs]->cost=0;
329 searchmap[offs]->previous=-1;
330 searchmap[offs]->first_robotop=ROBOTOP_NONE;
331 searchmap[offs]->newpos=pos;
332 searchmap[offs]->deadend=false;
333 AI_expandoperators(x,y,angle,traction,y*(map_w*2)+x,0,depth);
334
335 #ifdef _WRITE_REPORT_
336 fprintf(debug_fp,"Expanding de search tree finished\n");
337 fflush(debug_fp);
338 #endif
339
340
341 /* ADVANCE PROGRAM: */
342 if (goaltype==PROGRAM_ADVANCE) {
343 int i,j;
344 double further;
345 int mincost;
346 bool first=true;
347 AI_OPERATOR *op,*bestop=0;
348
349 for(i=-depth;i<depth;i++) {
350 for(j=-depth;j<depth;j++) {
351 if ((x+i)>=0 && (x+i)<(map_w*2) &&
352 (y+j)>=0 && (y+j)<(map_h*2) &&
353 (i!=0 || j!=0)) {
354 op=searchmap[(y+j)*(map_w*2)+(x+i)];
355 if (op->used) {
356 if (first ||
357 (op->deadend==bestop->deadend &&
358 (op->newpos.y>further ||
359 (op->newpos.y==further && op->cost<mincost))) ||
360 (!op->deadend && bestop->deadend)) {
361 bestop=op;
362 further=op->newpos.y;
363 mincost=op->cost;
364 first=false;
365 } /*if */
366 } /* if */
367 } /* if */
368 } /* for */
369 } /* for */
370
371 if (bestop!=0) {
372 int rop;
373 AI_OPERATOR *prev;
374
375 prev=bestop;
376 while(bestop->previous!=-1 && searchmap[bestop->previous]->used) {
377 prev=bestop;
378 bestop=searchmap[bestop->previous];
379 } /* while */
380 rop=prev->first_robotop;
381
382 AI_resetsearch(pos,depth);
383 return rop;
384 } else {
385 AI_resetsearch(pos,depth);
386 return ROBOTOP_NONE;
387 } /* if */
388
389 AI_resetsearch(pos,depth);
390 if (bestop!=0) return bestop->first_robotop;
391 else return ROBOTOP_NONE;
392 } /* if */
393
394 /* RETREAT PROGRAM: */
395 if (goaltype==PROGRAM_RETREAT) {
396 int i,j;
397 double further;
398 int mincost;
399 bool first=true;
400 AI_OPERATOR *op,*bestop=0;
401
402 for(i=-depth;i<depth;i++) {
403 for(j=-depth;j<depth;j++) {
404 if ((x+i)>=0 && (x+i)<(map_w*2) &&
405 (y+j)>=0 && (y+j)<(map_h*2) &&
406 (i!=0 || j!=0)) {
407 op=searchmap[(y+j)*(map_w*2)+(x+i)];
408 if (op->used) {
409 if (first ||
410 (op->deadend==bestop->deadend &&
411 (op->newpos.y<further ||
412 (op->newpos.y==further && op->cost<mincost))) ||
413 (!op->deadend && bestop->deadend)) {
414 bestop=op;
415 further=op->newpos.y;
416 mincost=op->cost;
417 first=false;
418 } /*if */
419 } /* if */
420 } /* if */
421 } /* for */
422 } /* for */
423
424 if (bestop!=0) {
425 int rop;
426 AI_OPERATOR *prev;
427
428 prev=bestop;
429 while(bestop->previous!=-1 && searchmap[bestop->previous]->used) {
430 prev=bestop;
431 bestop=searchmap[bestop->previous];
432 } /* while */
433 rop=prev->first_robotop;
434
435 AI_resetsearch(pos,depth);
436 return rop;
437 } else {
438 AI_resetsearch(pos,depth);
439 return ROBOTOP_NONE;
440 } /* if */
441
442 AI_resetsearch(pos,depth);
443 if (bestop!=0) return bestop->first_robotop;
444 else return ROBOTOP_NONE;
445 } /* if */
446
447 /* CAPTURE PROGRAM: */
448 if (goaltype==PROGRAM_CAPTURE) {
449 int i,j;
450 double closer;
451 int mincost;
452 bool first=true;
453 AI_OPERATOR *op,*bestop=0;
454
455 #ifdef _WRITE_REPORT_
456 fprintf(debug_fp,"Search engine for CAPTURE START\n");
457 fflush(debug_fp);
458 #endif
459
460 for(i=-depth;i<depth;i++) {
461 for(j=-depth;j<depth;j++) {
462 if ((x+i)>=0 && (x+i)<(map_w*2) &&
463 (y+j)>=0 && (y+j)<(map_h*2) &&
464 (i!=0 || j!=0)) {
465 op=searchmap[(y+j)*(map_w*2)+(x+i)];
466 if (op->used) {
467 if (first ||
468 ((op->deadend==bestop->deadend || (op->newpos+Vector(0.5,0.5,0)-goalpos).norma()==0) &&
469 ((op->newpos+Vector(0.5,0.5,0)-goalpos).norma()<closer ||
470 ((op->newpos+Vector(0.5,0.5,0)-goalpos).norma()==closer && op->cost<mincost))) ||
471 (!op->deadend && bestop->deadend && closer!=0)) {
472 bestop=op;
473 closer=(op->newpos+Vector(0.5,0.5,0)-goalpos).norma();
474 mincost=op->cost;
475 first=false;
476 } /*if */
477 } /* if */
478 } /* if */
479 } /* for */
480 } /* for */
481
482 #ifdef _WRITE_REPORT_
483 fprintf(debug_fp,"Search engine for CAPTURE FINISHED\n");
484 fflush(debug_fp);
485 #endif
486
487 if (bestop!=0) {
488 int rop;
489 AI_OPERATOR *prev;
490
491 prev=bestop;
492 while(bestop->previous!=-1 && searchmap[bestop->previous]->used) {
493 prev=bestop;
494 bestop=searchmap[bestop->previous];
495 } /* while */
496 rop=prev->first_robotop;
497
498 AI_resetsearch(pos,depth);
499 return rop;
500 } else {
501 AI_resetsearch(pos,depth);
502 return ROBOTOP_NONE;
503 } /* if */
504
505 AI_resetsearch(pos,depth);
506 if (bestop!=0) return bestop->first_robotop;
507 else return ROBOTOP_NONE;
508 } /* if */
509
510
511 /* DESTROY PROGRAM: */
512 if (goaltype==PROGRAM_DESTROY) {
513 int i,j;
514 double closer;
515 AI_OPERATOR *op;
516 int mincost,mincost2;
517 bool first=true,first2=true;
518 AI_OPERATOR *bestop=0; /* Best operator to get closer to the nearest robot */
519 AI_OPERATOR *bestop2=0; /* Best operator to reach an attaking position */
520
521 for(i=-depth;i<depth;i++) {
522 for(j=-depth;j<depth;j++) {
523 if ((x+i)>=0 && (x+i)<(map_w*2) &&
524 (y+j)>=0 && (y+j)<(map_h*2) &&
525 (i!=0 || j!=0)) {
526 op=searchmap[(y+j)*(map_w*2)+(x+i)];
527 if (op->used) {
528 if (first ||
529 ((op->deadend==bestop->deadend || (op->newpos+Vector(0.5,0.5,0)-goalpos).norma()==0) &&
530 ((op->newpos+Vector(0.5,0.5,0)-goalpos).norma()<closer ||
531 ((op->newpos+Vector(0.5,0.5,0)-goalpos).norma()==closer && op->cost<mincost))) ||
532 (!op->deadend && bestop->deadend && closer!=0)) {
533 bestop=op;
534 closer=(op->newpos+Vector(0.5,0.5,0)-goalpos).norma();
535 mincost=op->cost;
536 first=false;
537 } /*if */
538 if (atackmap[(y+j)*(map_w*2)+(x+i)]!=0 ||
539 atackmap[(y+j+1)*(map_w*2)+(x+i)]!=0 ||
540 atackmap[(y+j)*(map_w*2)+(x+i+1)]!=0 ||
541 atackmap[(y+j+1)*(map_w*2)+(x+i+1)]!=0) {
542 if (first2 ||
543 op->cost<mincost2) {
544 bestop2=op;
545 mincost2=op->cost;
546 first2=false;
547 } /*if */
548 } /* if */
549 } /* if */
550 } /* if */
551 } /* for */
552 } /* for */
553
554 /* It's better to reach an attacking position if this is possible: */
555 if (bestop2!=0) bestop=bestop2;
556
557 if (bestop!=0) {
558 int rop;
559 AI_OPERATOR *prev;
560
561 prev=bestop;
562 while(bestop->previous!=-1 && searchmap[bestop->previous]->used) {
563 prev=bestop;
564 bestop=searchmap[bestop->previous];
565 } /* while */
566 rop=prev->first_robotop;
567
568 AI_resetsearch(pos,depth);
569 return rop;
570 } else {
571 AI_resetsearch(pos,depth);
572 return ROBOTOP_NONE;
573 } /* if */
574
575 AI_resetsearch(pos,depth);
576 if (bestop!=0) return bestop->first_robotop;
577 else return ROBOTOP_NONE;
578 } /* if */
579
580 return ROBOTOP_NONE;
581 } /* AI_searchengine */
582
583
AI_resetsearch(Vector pos,int depth)584 void NETHER::AI_resetsearch(Vector pos,int depth)
585 {
586 int i,j;
587 int x,y,dx,dy;
588
589 robot_zone(pos,&x,&y,&dx,&dy);
590
591 for(i=-depth;i<depth;i++) {
592 for(j=-depth;j<depth;j++) {
593 if ((x+i)>=0 && (x+i)<(map_w*2) &&
594 (y+j)>=0 && (y+j)<(map_h*2)) {
595 searchmap[(y+j)*(map_w*2)+(x+i)]->used=false;
596 } /* if */
597 } /* for */
598 } /* for */
599
600 } /* AI_resetsearch */
601
602
AI_WorseMapTerrain(int x,int y,int dx,int dy)603 int NETHER::AI_WorseMapTerrain(int x,int y,int dx,int dy)
604 {
605 int t=T_GRASS,t2;
606 int i,j;
607
608 for(i=0;i<dx;i++) {
609 for(j=0;j<dy;j++) {
610 if (x+i<0 || x+i>=map_w*2 ||
611 y+j<0 || y+j>=map_h*2) return T_OUT;
612 t2=discreetmap[(y+j)*(map_w*2)+x+i];
613 if (t2>t) t=t2;
614 } /* if */
615 } /* for */
616
617 return t;
618 } /* NETHER::AI_WorseMapTerrain */
619
620
AI_program_advance(int amount,Vector pos,int angle,int traction,bool electronics,int player,bool * pieces)621 int NETHER::AI_program_advance(int amount,Vector pos,int angle,int traction,bool electronics,int player,bool *pieces)
622 {
623 /* First of all, delete the robot from the discreet map: */
624 int op=ROBOTOP_NONE;
625 int type;
626 List<AI_OPERATOR> l;
627 Vector tmp_goal;
628
629 op=AI_program_stopdefend(&tmp_goal,pos,angle,traction,electronics,player,pieces);
630 if (op!=ROBOTOP_NONE) return op;
631
632 type=AI_killrobot(pos);
633
634 AI_availableoperators(pos,angle,traction,&l);
635
636 if (!l.EmptyP()) {
637 /* Choose one operator: */
638 AI_OPERATOR *aiop;
639
640 if (electronics) {
641 op=AI_searchengine(pos,angle,PROGRAM_ADVANCE,Vector(0,0,0),traction,WE_SEARCH_DEPTH);
642 } else {
643 if ((rand()%4)!=0) {
644 op=AI_searchengine(pos,angle,PROGRAM_ADVANCE,Vector(0,0,0),traction,WOE_SEARCH_DEPTH);
645 } else {
646 AI_rankoperators_advance(&l);
647 aiop=AI_chooseoperator(&l,8);
648 op=aiop->first_robotop;
649 } /* if */
650 } /* if */
651 } /* if */
652
653 /* Reconstruct the decreet map: */
654 if (type==T_ROBOT) AI_newrobot(pos,0);
655 else AI_newrobot(pos,2);
656
657 return op;
658 } /* NETHER::AI_program_advance */
659
660
AI_program_retreat(int amount,Vector pos,int angle,int traction,bool electronics,int player,bool * pieces)661 int NETHER::AI_program_retreat(int amount,Vector pos,int angle,int traction,bool electronics,int player,bool *pieces)
662 {
663 /* First of all, delete the robot from the discreet map: */
664 int op=ROBOTOP_NONE;
665 int type;
666 List<AI_OPERATOR> l;
667 Vector tmp_goal;
668
669 op=AI_program_stopdefend(&tmp_goal,pos,angle,traction,electronics,player,pieces);
670 if (op!=ROBOTOP_NONE) return op;
671
672 type=AI_killrobot(pos);
673
674 AI_availableoperators(pos,angle,traction,&l);
675
676 if (!l.EmptyP()) {
677 /* Choose one operator: */
678 AI_OPERATOR *aiop;
679
680 if (electronics) {
681 op=AI_searchengine(pos,angle,PROGRAM_RETREAT,Vector(0,0,0),traction,WE_SEARCH_DEPTH);
682 } else {
683 if ((rand()%4)!=0) {
684 op=AI_searchengine(pos,angle,PROGRAM_RETREAT,Vector(0,0,0),traction,WOE_SEARCH_DEPTH);
685 } else {
686 AI_rankoperators_retreat(&l);
687 aiop=AI_chooseoperator(&l,8);
688 op=aiop->first_robotop;
689 } /* if */
690 } /* if */
691 } /* if */
692
693 /* Reconstruct the decreet map: */
694 if (type==T_ROBOT) AI_newrobot(pos,0);
695 else AI_newrobot(pos,1);
696
697 return op;
698 } /* NETHER::AI_program_retreat */
699
700
AI_program_capture(int goal,Vector * program_goal,Vector pos,int angle,int traction,bool electronics,int player,bool * pieces)701 int NETHER::AI_program_capture(int goal,Vector *program_goal,Vector pos,int angle,int traction,bool electronics,int player,bool *pieces)
702 {
703 /* First of all, delete the robot from the discreet map: */
704 int op=ROBOTOP_NONE;
705 int type;
706 List<AI_OPERATOR> l;
707
708 #ifdef _WRITE_REPORT_
709 fprintf(debug_fp,"AI_program_capture START\n");
710 fflush(debug_fp);
711 #endif
712
713 op=AI_program_stopdefend(program_goal,pos,angle,traction,electronics,player,pieces);
714 if (op!=ROBOTOP_NONE) return op;
715
716 type=AI_killrobot(pos);
717
718 #ifdef _WRITE_REPORT_
719 fprintf(debug_fp,"Searching available operators\n");
720 fflush(debug_fp);
721 #endif
722
723 AI_availableoperators(pos,angle,traction,&l);
724
725 if (!l.EmptyP()) {
726 /* Choose one operator: */
727 AI_OPERATOR *aiop;
728
729 #ifdef _WRITE_REPORT_
730 fprintf(debug_fp,"Seeking a goal\n");
731 fflush(debug_fp);
732 #endif
733
734 {
735 /* Seek a goal: */
736 List<BUILDING> l;
737 BUILDING *b;
738 bool anygoal=false;
739 float distance,minimumdistance;
740
741 *program_goal=Vector(-1,-1,-1);
742
743 l.Instance(buildings);
744 l.Rewind();
745 while(l.Iterate(b)) {
746 if (goal==P_PARAM_WARBASES &&
747 b->type==B_WARBASE && b->owner!=player &&
748 AI_WorseMapTerrain(int((b->pos.x+2.0)/0.5),int(b->pos.y/0.5),2,2)<=T_HOLE) {
749 distance=float(((b->pos+Vector(2.5,0.5,0))-pos).norma());
750 if (!anygoal || distance<minimumdistance) {
751 anygoal=true;
752 minimumdistance=distance;
753 *program_goal=b->pos+Vector(2.5,0.5,0);
754 } /* if */
755 } /* if */
756 if (goal==P_PARAM_NFACTORIES &&
757 (b->type==B_FACTORY_ELECTRONICS ||
758 b->type==B_FACTORY_NUCLEAR ||
759 b->type==B_FACTORY_PHASERS ||
760 b->type==B_FACTORY_MISSILES ||
761 b->type==B_FACTORY_CANNONS ||
762 b->type==B_FACTORY_CHASSIS) && b->owner==0 &&
763 AI_WorseMapTerrain(int((b->pos.x+1.0)/0.5),int(b->pos.y/0.5),2,2)<=T_HOLE) {
764 distance=float(((b->pos+Vector(1.5,0.5,0))-pos).norma());
765 if (!anygoal || distance<minimumdistance) {
766 anygoal=true;
767 minimumdistance=distance;
768 *program_goal=b->pos+Vector(1.5,0.5,0);
769 } /* if */
770 } /* if */
771 if (goal==P_PARAM_EFACTORIES &&
772 (b->type==B_FACTORY_ELECTRONICS ||
773 b->type==B_FACTORY_NUCLEAR ||
774 b->type==B_FACTORY_PHASERS ||
775 b->type==B_FACTORY_MISSILES ||
776 b->type==B_FACTORY_CANNONS ||
777 b->type==B_FACTORY_CHASSIS) && b->owner!=0 && b->owner!=player &&
778 AI_WorseMapTerrain(int((b->pos.x+1.0)/0.5),int(b->pos.y/0.5),2,2)<=T_HOLE) {
779 distance=float(((b->pos+Vector(1.5,0.5,0))-pos).norma());
780 if (!anygoal || distance<minimumdistance) {
781 anygoal=true;
782 minimumdistance=distance;
783 *program_goal=b->pos+Vector(1.5,0.5,0);
784 } /* if */
785 } /* if */
786 } /* while */
787 }
788
789 #ifdef _WRITE_REPORT_
790 fprintf(debug_fp,"Searhing a plan to reach the goal\n");
791 fflush(debug_fp);
792 #endif
793
794 if (program_goal->x!=-1 &&
795 (*program_goal)!=pos) {
796 if (electronics) {
797 op=AI_searchengine(pos,angle,PROGRAM_CAPTURE,*program_goal,traction,WE_SEARCH_DEPTH);
798 } else {
799 if ((rand()%4)!=0) {
800 op=AI_searchengine(pos,angle,PROGRAM_CAPTURE,*program_goal,traction,WOE_SEARCH_DEPTH);
801 } else {
802 AI_rankoperators_capture(&l,*program_goal);
803 aiop=AI_chooseoperator(&l,8);
804 op=aiop->first_robotop;
805 } /* if */
806 } /* if */
807 } /* if */
808 } /* if */
809
810 /* Reconstruct the decreet map: */
811 if (type==T_ROBOT) AI_newrobot(pos,0);
812 else AI_newrobot(pos,1);
813
814 #ifdef _WRITE_REPORT_
815 fprintf(debug_fp,"AI_program_capture FINISHED\n");
816 fflush(debug_fp);
817 #endif
818
819 return op;
820 } /* NETHER::AI_program_capture */
821
822
AI_RealShotPaths(int x,int y,int player,int persistence)823 int NETHER::AI_RealShotPaths(int x,int y,int player,int persistence)
824 {
825 int rsp=0;
826 int i;
827 // int persistence=CANNON_PERSISTENCE;
828
829 for(i=2;i<int((persistence*BULLET_SPEED)/0.5)+2 && (x+i<map_w*2);i++) {
830 if (discreetmap[x+i+y*(map_w*2)]==T_BUILDING ||
831 discreetmap[x+i+(y+1)*(map_w*2)]==T_BUILDING) break;
832 if (player==1) {
833 if (discreetmap[x+i+y*(map_w*2)]==T_ROBOT ||
834 discreetmap[x+i+(y+1)*(map_w*2)]==T_ROBOT) break;
835 if (discreetmap[x+i+y*(map_w*2)]==T_EROBOT ||
836 discreetmap[x+i+(y+1)*(map_w*2)]==T_EROBOT) {
837 rsp|=1;
838 break;
839 } /* if */
840 } else {
841 if (discreetmap[x+i+y*(map_w*2)]==T_EROBOT ||
842 discreetmap[x+i+(y+1)*(map_w*2)]==T_EROBOT) break;
843 if (discreetmap[x+i+y*(map_w*2)]==T_ROBOT ||
844 discreetmap[x+i+(y+1)*(map_w*2)]==T_ROBOT) {
845 rsp|=1;
846 break;
847 } /* if */
848 } /* if */
849 } /* for */
850
851 for(i=1;i<int((persistence*BULLET_SPEED)/0.5)+1 && (x-i>=0);i++) {
852 if (discreetmap[x-i+y*(map_w*2)]==T_BUILDING ||
853 discreetmap[x-i+(y+1)*(map_w*2)]==T_BUILDING) break;
854 if (player==1) {
855 if (discreetmap[x-i+y*(map_w*2)]==T_ROBOT ||
856 discreetmap[x-i+(y+1)*(map_w*2)]==T_ROBOT) break;
857 if (discreetmap[x-i+y*(map_w*2)]==T_EROBOT ||
858 discreetmap[x-i+(y+1)*(map_w*2)]==T_EROBOT) {
859 rsp|=4;
860 break;
861 } /* if */
862 } else {
863 if (discreetmap[x-i+y*(map_w*2)]==T_EROBOT ||
864 discreetmap[x-i+(y+1)*(map_w*2)]==T_EROBOT) break;
865 if (discreetmap[x-i+y*(map_w*2)]==T_ROBOT ||
866 discreetmap[x-i+(y+1)*(map_w*2)]==T_ROBOT) {
867 rsp|=4;
868 break;
869 } /* if */
870 } /* if */
871 } /* for */
872
873 for(i=2;i<int((persistence*BULLET_SPEED)/0.5)+2 && (y+i<map_h*2);i++) {
874 if (discreetmap[x+(y+i)*(map_w*2)]==T_BUILDING ||
875 discreetmap[(x+1)+(y+i)*(map_w*2)]==T_BUILDING) break;
876 if (player==1) {
877 if (discreetmap[x+(y+i)*(map_w*2)]==T_ROBOT ||
878 discreetmap[(x+1)+(y+i)*(map_w*2)]==T_ROBOT) break;
879 if (discreetmap[x+(y+i)*(map_w*2)]==T_EROBOT ||
880 discreetmap[(x+1)+(y+i)*(map_w*2)]==T_EROBOT) {
881 rsp|=2;
882 break;
883 } /* if */
884 } else {
885 if (discreetmap[x+(y+i)*(map_w*2)]==T_EROBOT ||
886 discreetmap[(x+1)+(y+i)*(map_w*2)]==T_EROBOT) break;
887 if (discreetmap[x+(y+i)*(map_w*2)]==T_ROBOT ||
888 discreetmap[(x+1)+(y+i)*(map_w*2)]==T_ROBOT) {
889 rsp|=2;
890 break;
891 } /* if */
892 } /* if */
893 } /* for */
894
895 for(i=1;i<int((persistence*BULLET_SPEED)/0.5)+1 && (y-i>=0);i++) {
896 if (discreetmap[x+(y-i)*(map_w*2)]==T_BUILDING ||
897 discreetmap[(x+1)+(y-i)*(map_w*2)]==T_BUILDING) break;
898 if (player==1) {
899 if (discreetmap[x+(y-i)*(map_w*2)]==T_ROBOT ||
900 discreetmap[(x+1)+(y-i)*(map_w*2)]==T_ROBOT) break;
901 if (discreetmap[x+(y-i)*(map_w*2)]==T_EROBOT ||
902 discreetmap[(x+1)+(y-i)*(map_w*2)]==T_EROBOT) {
903 rsp|=8;
904 break;
905 } /* if */
906 } else {
907 if (discreetmap[x+(y-i)*(map_w*2)]==T_EROBOT ||
908 discreetmap[(x+1)+(y-i)*(map_w*2)]==T_EROBOT) break;
909 if (discreetmap[x+(y-i)*(map_w*2)]==T_ROBOT ||
910 discreetmap[(x+1)+(y-i)*(map_w*2)]==T_ROBOT) {
911 rsp|=8;
912 break;
913 } /* if */
914 } /* if */
915 } /* for */
916
917 return rsp;
918 } /* NETHER::AI_RealShotPaths */
919
920
AI_program_destroy(int goal,Vector * program_goal,Vector pos,int angle,int traction,bool electronics,int player,bool * pieces)921 int NETHER::AI_program_destroy(int goal,Vector *program_goal,Vector pos,int angle,int traction,bool electronics,int player,bool *pieces)
922 {
923 /* First of all, delete the robot from the discreet map: */
924 int op=ROBOTOP_NONE;
925 int type=AI_killrobot(pos);
926 List<AI_OPERATOR> lops;
927
928 AI_availableoperators(pos,angle,traction,&lops);
929
930 if (!lops.EmptyP()) {
931 /* Choose one operator: */
932 AI_OPERATOR *aiop;
933
934 if (goal!=P_PARAM_ROBOTS) {
935 /* Seek a goal: */
936 List<BUILDING> l;
937 BUILDING *b;
938 bool anygoal=false;
939 float distance,minimumdistance;
940
941 *program_goal=Vector(-1,-1,-1);
942
943 l.Instance(buildings);
944 l.Rewind();
945 while(l.Iterate(b)) {
946 if (goal==P_PARAM_WARBASES &&
947 b->type==B_WARBASE && b->owner!=player &&
948 AI_WorseMapTerrain(int((b->pos.x+2.0)/0.5),int(b->pos.y/0.5),2,2)<=T_HOLE) {
949 distance=float(((b->pos+Vector(2.5,0.5,0))-pos).norma());
950 if (!anygoal || distance<minimumdistance) {
951 anygoal=true;
952 minimumdistance=distance;
953 *program_goal=b->pos+Vector(2.5,0.5,0);
954 } /* if */
955 } /* if */
956 if (goal==P_PARAM_EFACTORIES &&
957 (b->type==B_FACTORY_ELECTRONICS ||
958 b->type==B_FACTORY_NUCLEAR ||
959 b->type==B_FACTORY_PHASERS ||
960 b->type==B_FACTORY_MISSILES ||
961 b->type==B_FACTORY_CANNONS ||
962 b->type==B_FACTORY_CHASSIS) && b->owner!=0 && b->owner!=player &&
963 AI_WorseMapTerrain(int((b->pos.x+1.0)/0.5),int(b->pos.y/0.5),2,2)<=T_HOLE) {
964 distance=float(((b->pos+Vector(1.5,0.5,0))-pos).norma());
965 if (!anygoal || distance<minimumdistance) {
966 anygoal=true;
967 minimumdistance=distance;
968 *program_goal=b->pos+Vector(1.5,0.5,0);
969 } /* if */
970 } /* if */
971 } /* while */
972
973 if (program_goal->x!=-1 &&
974 (*program_goal)!=pos) {
975 if (electronics) {
976 op=AI_searchengine(pos,angle,PROGRAM_CAPTURE,*program_goal,traction,WE_SEARCH_DEPTH);
977 } else {
978 if ((rand()%4)!=0) {
979 op=AI_searchengine(pos,angle,PROGRAM_CAPTURE,*program_goal,traction,WOE_SEARCH_DEPTH);
980 } else {
981 AI_rankoperators_capture(&lops,*program_goal);
982 aiop=AI_chooseoperator(&lops,8);
983 op=aiop->first_robotop;
984 } /* if */
985 } /* if */
986 } else {
987 if (program_goal->x!=-1) op=ROBOTOP_NUCLEAR;
988 } /* if */
989
990 } else {
991 /* Find the nearest position to destroy an enemy robot: */
992 List<ROBOT> l;
993 ROBOT *r;
994 int x,y,dx,dy,i,j,k;
995 bool collided;
996 bool first=true;
997 float distance;
998 int persistence=CANNON_PERSISTENCE;
999 if (pieces[1]) persistence=MISSILE_PERSISTENCE;
1000
1001 *program_goal=Vector(-1,-1,-1);
1002 for(i=0;i<map_w*2*map_h*2;i++) atackmap[i]=0;
1003
1004 /* Find the nearest FIRE position: */
1005 l.Instance(robots[2-player]);
1006 l.Rewind();
1007 while(l.Iterate(r)) {
1008 if (first ||
1009 (*program_goal-pos).norma()<distance) {
1010 first=false;
1011 distance=float((*program_goal-pos).norma());
1012 *program_goal=r->pos;
1013 } /* if */
1014
1015 robot_zone(r->pos,&x,&y,&dx,&dy);
1016 for(i=0;i<dx;i++) {
1017 for(j=0;j<dy;j++) {
1018 collided=false;
1019 for(k=1;!collided && k<int((persistence*BULLET_SPEED)/0.5);k++) {
1020 if (x+i+k<0 || x+i+k>=map_w*2 ||
1021 y+j<0 || y+j>=map_h*2 ||
1022 discreetmap[(y+j)*(map_w*2)+(x+i+k)]>3) {
1023 collided=true;
1024 } else {
1025 atackmap[(y+j)*(map_w*2)+(x+i+k)]|=4;
1026 } /* if */
1027 } /* for */
1028
1029 collided=false;
1030 for(k=1;!collided && k<int((persistence*BULLET_SPEED)/0.5);k++) {
1031 if (x+i-k<0 || x+i-k>=map_w*2 ||
1032 y+j<0 || y+j>=map_h*2 ||
1033 discreetmap[(y+j)*(map_w*2)+(x+i-k)]>3) {
1034 collided=true;
1035 } else {
1036 atackmap[(y+j)*(map_w*2)+(x+i-k)]|=1;
1037 } /* if */
1038 } /* for */
1039
1040 collided=false;
1041 for(k=1;!collided && k<int((persistence*BULLET_SPEED)/0.5);k++) {
1042 if (x+i<0 || x+i>=map_w*2 ||
1043 y+j+k<0 || y+j+k>=map_h*2 ||
1044 discreetmap[(y+j+k)*(map_w*2)+(x+i)]>3) {
1045 collided=true;
1046 } else {
1047 atackmap[(y+j+k)*(map_w*2)+(x+i)]|=8;
1048 } /* if */
1049 } /* for */
1050
1051 collided=false;
1052 for(k=1;!collided && k<int((persistence*BULLET_SPEED)/0.5);k++) {
1053 if (x+i<0 || x+i>=map_w*2 ||
1054 y+j-k<0 || y+j-k>=map_h*2 ||
1055 discreetmap[(y+j-k)*(map_w*2)+(x+i)]>3) {
1056 collided=true;
1057 } else {
1058 atackmap[(y+j-k)*(map_w*2)+(x+i)]|=2;
1059 } /* if */
1060 } /* for */
1061 } /* for */
1062 } /* for */
1063 } /* while */
1064
1065 if (!first) {
1066 robot_zone(pos,&x,&y,&dx,&dy);
1067 if ((atackmap[y*(map_w*2)+x]!=0 ||
1068 atackmap[(y+1)*(map_w*2)+x]!=0 ||
1069 atackmap[y*(map_w*2)+x+1]!=0 ||
1070 atackmap[(y+1)*(map_w*2)+x+1]!=0)) {
1071 int prsp=0,mrsp=0,crsp=0,rsp=0;
1072 if (pieces[2]) prsp=AI_RealShotPaths(x,y,player,PHASER_PERSISTENCE);
1073 if (pieces[1]) mrsp=AI_RealShotPaths(x,y,player,MISSILE_PERSISTENCE);
1074 if (pieces[0]) crsp=AI_RealShotPaths(x,y,player,CANNON_PERSISTENCE);
1075 rsp=prsp|mrsp|crsp;
1076
1077 if (rsp!=0) {
1078 int dirmask=0;
1079 if (angle==0) dirmask=1;
1080 if (angle==90) dirmask=2;
1081 if (angle==180) dirmask=4;
1082 if (angle==270) dirmask=8;
1083 if ((rsp&dirmask)!=0) {
1084 if ((prsp&dirmask)!=0) {
1085 op=ROBOTOP_PHASERS;
1086 } else {
1087 if ((mrsp&dirmask)!=0) {
1088 op=ROBOTOP_MISSILES;
1089 } else {
1090 op=ROBOTOP_CANNONS;
1091 } /* if */
1092 } /* if */
1093 } else {
1094 dirmask*=2;
1095 if (dirmask>=16) dirmask=1;
1096 if ((rsp&dirmask)!=0) {
1097 op=ROBOTOP_RIGHT;
1098 } else {
1099 op=ROBOTOP_LEFT;
1100 } /* if */
1101 } /* if */
1102 } else {
1103 if (electronics) {
1104 op=AI_searchengine(pos,angle,PROGRAM_DESTROY,*program_goal,traction,WE_SEARCH_DEPTH);
1105 } else {
1106 if ((rand()%4)!=0) {
1107 op=AI_searchengine(pos,angle,PROGRAM_DESTROY,*program_goal,traction,WOE_SEARCH_DEPTH);
1108 } else {
1109 AI_rankoperators_capture(&lops,*program_goal);
1110 aiop=AI_chooseoperator(&lops,8);
1111 op=aiop->first_robotop;
1112 } /* if */
1113 } /* if */
1114 } /* if */
1115 } else {
1116 if (electronics) {
1117 op=AI_searchengine(pos,angle,PROGRAM_DESTROY,*program_goal,traction,WE_SEARCH_DEPTH);
1118 } else {
1119 if ((rand()%4)!=0) {
1120 op=AI_searchengine(pos,angle,PROGRAM_DESTROY,*program_goal,traction,WOE_SEARCH_DEPTH);
1121 } else {
1122 AI_rankoperators_capture(&lops,*program_goal);
1123 aiop=AI_chooseoperator(&lops,8);
1124 op=aiop->first_robotop;
1125 } /* if */
1126 } /* if */
1127 } /* if */
1128 } else {
1129 /* There are no enemy robots: */
1130 op=ROBOTOP_NONE;
1131 } /* if */
1132 } /* if */
1133 } /* if */
1134
1135 /* Reconstruct the decreet map: */
1136 if (type==T_ROBOT) AI_newrobot(pos,0);
1137 else AI_newrobot(pos,1);
1138
1139 return op;
1140 } /* NETHER::AI_program_destroy */
1141
1142
AI_program_stopdefend(Vector * program_goal,Vector pos,int angle,int traction,bool electronics,int player,bool * pieces)1143 int NETHER::AI_program_stopdefend(Vector *program_goal,Vector pos,int angle,int traction,bool electronics,int player,bool *pieces)
1144 {
1145 /* First of all, delete the robot from the discreet map: */
1146 int op=ROBOTOP_NONE;
1147 int type=AI_killrobot(pos);
1148 List<AI_OPERATOR> lops;
1149
1150 AI_availableoperators(pos,angle,traction,&lops);
1151
1152 if (!lops.EmptyP()) {
1153 /* Choose one operator: */
1154
1155 /* Find the nearest position to destroy an enemy robot: */
1156 List<ROBOT> l;
1157 ROBOT *r;
1158 int x,y,dx,dy,i,j,k;
1159 bool collided;
1160 int persistence=CANNON_PERSISTENCE;
1161 if (pieces[1]) persistence=MISSILE_PERSISTENCE;
1162
1163 *program_goal=Vector(-1,-1,-1);
1164 for(i=0;i<map_w*2*map_h*2;i++) atackmap[i]=0;
1165
1166 /* Find the nearest FIRE position: */
1167 l.Instance(robots[2-player]);
1168 l.Rewind();
1169 while(l.Iterate(r)) {
1170 robot_zone(r->pos,&x,&y,&dx,&dy);
1171 for(i=0;i<dx;i++) {
1172 for(j=0;j<dy;j++) {
1173 collided=false;
1174 for(k=1;!collided && k<int((persistence*BULLET_SPEED)/0.5);k++) {
1175 if (x+i+k<0 || x+i+k>=map_w*2 ||
1176 y+j<0 || y+j>=map_h*2 ||
1177 discreetmap[(y+j)*(map_w*2)+(x+i+k)]>3) {
1178 collided=true;
1179 } else {
1180 atackmap[(y+j)*(map_w*2)+(x+i+k)]|=4;
1181 } /* if */
1182 } /* for */
1183
1184 collided=false;
1185 for(k=1;!collided && k<int((persistence*BULLET_SPEED)/0.5);k++) {
1186 if (x+i-k<0 || x+i-k>=map_w*2 ||
1187 y+j<0 || y+j>=map_h*2 ||
1188 discreetmap[(y+j)*(map_w*2)+(x+i-k)]>3) {
1189 collided=true;
1190 } else {
1191 atackmap[(y+j)*(map_w*2)+(x+i-k)]|=1;
1192 } /* if */
1193 } /* for */
1194
1195 collided=false;
1196 for(k=1;!collided && k<int((persistence*BULLET_SPEED)/0.5);k++) {
1197 if (x+i<0 || x+i>=map_w*2 ||
1198 y+j+k<0 || y+j+k>=map_h*2 ||
1199 discreetmap[(y+j+k)*(map_w*2)+(x+i)]>3) {
1200 collided=true;
1201 } else {
1202 atackmap[(y+j+k)*(map_w*2)+(x+i)]|=8;
1203 } /* if */
1204 } /* for */
1205
1206 collided=false;
1207 for(k=1;!collided && k<int((persistence*BULLET_SPEED)/0.5);k++) {
1208 if (x+i<0 || x+i>=map_w*2 ||
1209 y+j-k<0 || y+j-k>=map_h*2 ||
1210 discreetmap[(y+j-k)*(map_w*2)+(x+i)]>3) {
1211 collided=true;
1212 } else {
1213 atackmap[(y+j-k)*(map_w*2)+(x+i)]|=2;
1214 } /* if */
1215 } /* for */
1216 } /* for */
1217 } /* for */
1218 } /* while */
1219
1220
1221 if (!robots[2-player].EmptyP()) {
1222 robot_zone(pos,&x,&y,&dx,&dy);
1223 if ((atackmap[y*(map_w*2)+x]!=0 ||
1224 atackmap[(y+1)*(map_w*2)+x]!=0 ||
1225 atackmap[y*(map_w*2)+x+1]!=0 ||
1226 atackmap[(y+1)*(map_w*2)+x+1]!=0)) {
1227 int prsp=0,mrsp=0,crsp=0,rsp=0;
1228 if (pieces[2]) prsp=AI_RealShotPaths(x,y,player,PHASER_PERSISTENCE);
1229 if (pieces[1]) mrsp=AI_RealShotPaths(x,y,player,MISSILE_PERSISTENCE);
1230 if (pieces[0]) crsp=AI_RealShotPaths(x,y,player,CANNON_PERSISTENCE);
1231 rsp=prsp|mrsp|crsp;
1232
1233 if (rsp!=0) {
1234 int dirmask=0;
1235
1236 /* This is just to make the program not to think that the robot doesn't have any goal: */
1237 *program_goal=Vector(0,0,0);
1238
1239 if (angle==0) dirmask=1;
1240 if (angle==90) dirmask=2;
1241 if (angle==180) dirmask=4;
1242 if (angle==270) dirmask=8;
1243 if ((rsp&dirmask)!=0) {
1244 if ((prsp&dirmask)!=0) {
1245 op=ROBOTOP_PHASERS;
1246 } else {
1247 if ((mrsp&dirmask)!=0) {
1248 op=ROBOTOP_MISSILES;
1249 } else {
1250 op=ROBOTOP_CANNONS;
1251 } /* if */
1252 } /* if */
1253 } else {
1254 dirmask*=2;
1255 if (dirmask>=16) dirmask=1;
1256 if ((rsp&dirmask)!=0) {
1257 op=ROBOTOP_RIGHT;
1258 } else {
1259 op=ROBOTOP_LEFT;
1260 } /* if */
1261 } /* if */
1262 } else {
1263 /* There are no enemy robots at sight: */
1264 op=ROBOTOP_NONE;
1265 } /* if */
1266 } else {
1267 /* There are no enemy robots at sight: */
1268 op=ROBOTOP_NONE;
1269 } /* if */
1270 } else {
1271 /* There are no enemy robots: */
1272 op=ROBOTOP_NONE;
1273 } /* if */
1274
1275 } /* if */
1276
1277 /* Reconstruct the decreet map: */
1278 if (type==T_ROBOT) AI_newrobot(pos,0);
1279 else AI_newrobot(pos,1);
1280
1281 return op;
1282 } /* NETHER::AI_program_stopdefend */
1283
1284
AI_rankoperators_advance(List<AI_OPERATOR> * l)1285 void NETHER::AI_rankoperators_advance(List<AI_OPERATOR> *l)
1286 {
1287 AI_OPERATOR *op1,*op2;
1288 LLink<AI_OPERATOR> *p1,*p2;
1289 bool changes;
1290
1291 /* Bubble sort: */
1292 do {
1293 changes=false;
1294 p1=p2=0;
1295 l->Rewind();
1296 while(!l->EndP()) {
1297 p1=p2;
1298 p2=l->GetPos();
1299 if (p1!=0 && p2!=0) {
1300 op1=p1->GetObj();
1301 op2=p2->GetObj();
1302 if ((op2->newpos.y>op1->newpos.y) ||
1303 (op2->newpos.y==op1->newpos.y && op2->cost<op1->cost)) {
1304 p1->Setobj(op2);
1305 p2->Setobj(op1);
1306 changes=true;
1307 } /* if */
1308 } /* if */
1309 l->Next();
1310 } /* while */
1311 }while(changes);
1312
1313 } /* NETHER::AI_rankoperators_advance */
1314
1315
AI_rankoperators_retreat(List<AI_OPERATOR> * l)1316 void NETHER::AI_rankoperators_retreat(List<AI_OPERATOR> *l)
1317 {
1318 AI_OPERATOR *op1,*op2;
1319 LLink<AI_OPERATOR> *p1,*p2;
1320 bool changes;
1321
1322 /* Bubble sort: */
1323 do {
1324 changes=false;
1325 p1=p2=0;
1326 l->Rewind();
1327 while(!l->EndP()) {
1328 p1=p2;
1329 p2=l->GetPos();
1330 if (p1!=0 && p2!=0) {
1331 op1=p1->GetObj();
1332 op2=p2->GetObj();
1333 if ((op2->newpos.y<op1->newpos.y) ||
1334 (op2->newpos.y==op1->newpos.y && op2->cost<op1->cost)) {
1335 p1->Setobj(op2);
1336 p2->Setobj(op1);
1337 changes=true;
1338 } /* if */
1339 } /* if */
1340 l->Next();
1341 } /* while */
1342 }while(changes);
1343
1344 } /* NETHER::AI_rankoperators_retreat */
1345
1346
AI_rankoperators_capture(List<AI_OPERATOR> * l,Vector goal)1347 void NETHER::AI_rankoperators_capture(List<AI_OPERATOR> *l,Vector goal)
1348 {
1349 AI_OPERATOR *op1,*op2;
1350 LLink<AI_OPERATOR> *p1,*p2;
1351 bool changes;
1352 float dist1 = 0;
1353 float dist2 = 0;
1354 int c1,c2;
1355
1356 #ifdef _WRITE_REPORT_
1357 fprintf(debug_fp,"Rank operators START\n");
1358 fflush(debug_fp);
1359 #endif
1360
1361 #ifdef _WRITE_REPORT_
1362 fprintf(debug_fp,"Rank operators START\n");
1363 fflush(debug_fp);
1364 #endif
1365
1366 /* Bubble sort: */
1367 do {
1368 changes=false;
1369 p1=p2=0;
1370 l->Rewind();
1371 while(!l->EndP()) {
1372 p1=p2;
1373 p2=l->GetPos();
1374 if (p1!=0 && p2!=0) {
1375 op1=p1->GetObj();
1376 op2=p2->GetObj();
1377 dist1 = (op1->newpos-goal).norma();
1378 dist2 = (op2->newpos-goal).norma();
1379 c1=(0.1)<(dist1-dist2);
1380 c2=0;
1381 if ((0.1)>(dist1-dist2) &&
1382 (-0.1)<(dist1-dist2)) c2=op2->cost<op1->cost;
1383 if (c1 || c2) {
1384
1385 #ifdef _WRITE_REPORT_
1386 fprintf(debug_fp,"Change: (%.16f,%i) <> (%.16f,%i) %i %i\n",dist1,op1->cost,dist2,op2->cost,c1,c2);
1387 fflush(debug_fp);
1388 #endif
1389 p1->Setobj(op2);
1390 p2->Setobj(op1);
1391 changes=true;
1392 } /* if */
1393 } /* if */
1394 l->Next();
1395 } /* while */
1396 }while(changes);
1397
1398 #ifdef _WRITE_REPORT_
1399 fprintf(debug_fp,"Rank operators FINISHED\n");
1400 fflush(debug_fp);
1401 #endif
1402
1403 } /* NETHER::AI_rankoperators_capture */
1404
1405
AI_chooseoperator(List<AI_OPERATOR> * l,int factor)1406 AI_OPERATOR *NETHER::AI_chooseoperator(List<AI_OPERATOR> *l,int factor)
1407 {
1408 if (factor==0) {
1409 l->Rewind();
1410 return l->GetObj();
1411 } else {
1412 l->Rewind();
1413 while(!l->LastP() && (rand()%factor)==0) l->Next();
1414 return l->GetObj();
1415 } /* if */
1416 } /* NETHER::AI_chooseoperator */
1417
1418
AI_robothere(Vector pos)1419 int NETHER::AI_robothere(Vector pos)
1420 {
1421 int x,y;
1422 int robot;
1423
1424 x=int(pos.x/0.5);
1425 y=int(pos.y/0.5);
1426
1427 robot=discreetmap[y*(map_w*2)+x];
1428
1429 if (robot!=T_ROBOT && robot!=T_EROBOT) robot=0;
1430
1431 return robot;
1432 } /* AI_robothere */
1433
1434
1435