#include "prolo.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/* Quelques constantes... */
#define pi M_PI
#define sqr(x) ((x)*(x))
#define MAX 300
#define RAYON_MIN 1
#define OUVERTURE_DEPART pi/4
#define DEFENSE_DISTANCE 5
#define DEFENSE_OUVERTURE 5
#define ATTAQUE_DISTANCE 1
#define ATTAQUE_OUVERTURE 0.01
#define GRATUIT_FREQ 10/10
#define GRATUIT_OUVERTURE 0.5
#define AIDE_TIMELIMIT 10000
#define AIDE_NBLIMIT 1
#define AIDE_OUVERTURE (2*r4d2_get_speed()+1)
/* Variables globales */
struct
{
int team;
float x,y;
float angle,ouverture;
} akx[MAX];
struct
{
float x,y,r;
} vise;
int capturing[MAX];
int nation;
/* Player_Init */
void player_init(int team_id, int nb_team)
{
int i;
nation=team_id;
printf("version 2\n");
printf("je suis %d\n",nation);
printf("akx_see_power : %f\n",akx_get_see_power());
for (i=0;i<MAX;i++)
{
akx[i].ouverture=OUVERTURE_DEPART;
akx[i].team=-1;
capturing[i]=-1;
}
return;
}
/* Player_New_Turn */
void player_new_turn(int turn_number)
{
int i,j,best_akx,best_r4d2;
float best,dist;
/* Mise a jour de la table locale des AnaKronoX */
for (i=0;i<MAX;i++) if (akx_get_team(i)!=-1)
{
if (akx[i].team==-1)
{
printf("akx %d trouve\n",i);
akx[i].x=akx_get_pos_x(i);
akx[i].y=akx_get_pos_y(i);
akx[i].team=akx_get_team(i);
}
if (akx[i].team!=akx_get_team(i))
{
printf("akx %d a change de team\n",i);
akx[i].team=akx_get_team(i);
}
if ((akx[i].x!=akx_get_pos_x(i)) || (akx[i].y!=akx_get_pos_y(i)))
{
printf("akx %d a bouge\n",i);
akx[i].x=akx_get_pos_x(i);
akx[i].y=akx_get_pos_y(i);
}
}
/* S'il ne reste que peu de r4d2 ou qu'on approche de la fin de partie, on defend le plus possible un des r4d2 restants */
if ((turn_counter()>=AIDE_TIMELIMIT) || (map_count_my_r4d2()<=AIDE_NBLIMIT))
for (i=0;i<MAX;i++) if (r4d2_get_team(i)==nation)
{
printf("AIDE r4d2 %d\n",i);
vise.x=r4d2_get_pos_x(i);
vise.y=r4d2_get_pos_y(i);
vise.r=AIDE_OUVERTURE;
return;
}
/* Recherche du r4d2 ennemi le plus proche d'un de mes AnaKronoX */
best=10000;
for (i=0;i<MAX;i++) if (((akx_get_team(i)==nation)||(akx_get_team(i))==0) && ((j=map_get_nearest_r4d2_plot(akx_get_pos_x(i),akx_get_pos_y(i),-nation))!=-1))
{
dist=sqrt(sqr(akx_get_pos_x(i)-r4d2_get_pos_x(j))
+sqr(akx_get_pos_y(i)-r4d2_get_pos_y(j)));
if (dist<best)
{
best=dist;
best_akx=i;
best_r4d2=j;
}
}
/* S'il y a un r4d2 ennemi tres proche d'un de mes AnaKronoX (surement en train de convertir donc surement imobile, on le vise tres serre */
if (best<ATTAQUE_DISTANCE)
{
printf("ATTAQUE %d\n",best_r4d2);
vise.x=r4d2_get_pos_x(best_r4d2);
vise.y=r4d2_get_pos_y(best_r4d2);
vise.r=ATTAQUE_OUVERTURE;
return;
}
/* S'il y a un r4d2 ennemi assez proche d'un des mes AnaKronoX, on le gene faisant un defense de zone autour de l'AnaKronoX */
if (best<DEFENSE_DISTANCE)
{
printf("DEFENSE %d\n",best_akx);
vise.x=akx_get_pos_x(best_akx);
vise.y=akx_get_pos_y(best_akx);
vise.r=DEFENSE_OUVERTURE;
return;
}
/* On tente une attaque "gratuite" sur un r4d2 ennemi de temps en temps */
if (map_random()<GRATUIT_FREQ)
for (i=0;i<MAX;i++) if ((r4d2_get_team(i)!=-1) && (r4d2_get_team(i)!=nation))
{
vise.x=r4d2_get_pos_x(i);
vise.y=r4d2_get_pos_y(i);
vise.r=GRATUIT_OUVERTURE;
return;
}
/* Sinon on ne vise rien de special (on fera du scanning) */
vise.r=-1;
return;
}
/* Player_AKX_Turn */
void player_akx_turn(int akx_id)
{
float rayon,ouverture,tcos,tsin;
/* Si on n'a plus de r4d2, on fait une defense de zone tres concentree, en bougeant une fois sur 3 */
if (map_count_my_r4d2()==0)
{
/* J'utilise l'angle comme boolean pour alterner deplacement/defense */
if (akx[akx_id].angle<2)
{
akx[akx_id].angle++;
vise.x=akx_get_pos_x(akx_id);
vise.y=akx_get_pos_y(akx_id);
vise.r=RAYON_MIN;
}
else
{
akx[akx_id].angle=0;
akx_move(akx_id,1,1);
return;
}
}
/* Si on a une directive de visee, on l'execute */
if (vise.r!=-1)
{
rayon=sqrt(sqr(akx_get_pos_x(akx_id)-vise.x)
+sqr(akx_get_pos_y(akx_id)-vise.y));
/* Si la distance entre l'AnaKronoX et sa cible est trop faible, on fait une defense circulaire */
if (rayon<RAYON_MIN)
akx_pulse(akx_id,akx_get_pos_x(akx_id)+RAYON_MIN,akx_get_pos_y(akx_id),2*pi);
/* Sinon on vise la cible avec l'ouverture demandee, en centrant au maximum */
else
{
tcos=(vise.x-akx_get_pos_x(akx_id))/rayon;
tsin=(vise.y-akx_get_pos_y(akx_id))/rayon;
ouverture=2*atan(vise.r/rayon);
akx_pulse(akx_id,vise.x+tcos*vise.r,vise.y+tsin*vise.r,ouverture);
}
return;
}
/* Sinon on scanne la carte pour trouver de nouveaux objectifs */
rayon=sqrt(2*akx_get_power()/(akx_get_see_power()*akx[akx_id].ouverture));
rayon--;
akx_pulse(akx_id,akx_get_pos_x(akx_id)+cos(akx[akx_id].angle)*rayon,akx_get_pos_y(akx_id)+sin(akx[akx_id].angle)*rayon,akx[akx_id].ouverture);
/* Calcul du prochain scan : on evite de scanner en dehors de la carte */
do
{
akx[akx_id].angle+=akx[akx_id].ouverture;
while (akx[akx_id].angle>=2*pi) akx[akx_id].angle-=2*pi;
/* Si on a fait un tour complet, on scanne plus serre et plus loin */
if ((akx[akx_id].angle>=0) && (akx[akx_id].angle<akx[akx_id].ouverture))
{
akx[akx_id].angle=0;
/* Si on scanne deja un rayon plus grand que la map, on repart sur un petit scan */
if ((rayon>=map_get_size_x()) && (rayon>=map_get_size_y())) akx[akx_id].ouverture=OUVERTURE_DEPART;
else akx[akx_id].ouverture=akx[akx_id].ouverture/2;
}
rayon=sqrt(2*akx_get_power()/(akx_get_see_power()*akx[akx_id].ouverture));
}
while ((akx_get_pos_x(akx_id)+cos(akx[akx_id].angle)*rayon<-1) ||
(akx_get_pos_x(akx_id)+cos(akx[akx_id].angle)*rayon>map_get_size_x()+1) ||
(akx_get_pos_y(akx_id)+sin(akx[akx_id].angle)*rayon<-1) ||
(akx_get_pos_y(akx_id)+sin(akx[akx_id].angle)*rayon>map_get_size_y()+1));
return;
}
int being_captured(int akx_id)
/* Retourne 1 si l'AnaKronoX passe en parametre est deja en cours de capture */
{
int i;
for (i=0;i<MAX;i++) if (capturing[i]==akx_id) return(1);
return(0);
}
int choose_nearest_akx_plot(int x, int y)
/* Retourne l'AnaKronoX le plus proche du point (x,y) et qui n'est pas deja en cours de capture */
{
float dist,best=10000;
int id=-1,i;
for (i=0;i<MAX;i++) if ((akx[i].team!=-1) && (akx[i].team!=nation) && (!being_captured(i)))
{
dist=sqrt(sqr(akx_get_pos_x(i)-x)+sqr(akx_get_pos_y(i)-y));
if (dist<best)
{
best=dist;
id=i;
}
}
return(id);
}
/* Player_R4D2_Turn */
void player_r4d2_turn(int r4d2_id)
{
int i;
if (akx_get_team(capturing[r4d2_id])==nation)
{
printf("%d -/-> %d\n",r4d2_id,capturing[r4d2_id]);
capturing[r4d2_id]=-1;
}
if (capturing[r4d2_id]==-1)
{
if ((i=choose_nearest_akx_plot(r4d2_get_pos_x(r4d2_id),r4d2_get_pos_y(r4d2_id)))==-1)
r4d2_move(r4d2_id,map_get_size_x()/2,map_get_size_y()/2);
else
{
r4d2_move(r4d2_id,akx[i].x,akx[i].y);
capturing[r4d2_id]=i;
printf("%d ---> %d\n",r4d2_id,i);
}
}
else
if (sqrt(sqr(r4d2_get_pos_x(r4d2_id)-akx[capturing[r4d2_id]].x)+
sqr(r4d2_get_pos_y(r4d2_id)-akx[capturing[r4d2_id]].y))<1)
r4d2_take_akx(r4d2_id,capturing[r4d2_id]);
else
r4d2_move(r4d2_id,akx[capturing[r4d2_id]].x,akx[capturing[r4d2_id]].y);
return;
}