#ifndef BATTERY_INCLUDED
#define BATTERY_INCLUDED

#include <stdio.h>
#include <stdlib.h>

#include "prologin.h"


typedef int my;


                        void  partie_init   (void) { }
#define NEVER_GONNA     void  jouer_tour    (void)
                        void  partie_fin    (void) { }

#define NaN             0xfffffff
#define undef           -1

#define $(x)            ({int __a=(x);(struct position){.ligne=__a/25,.colonne=__a%25};})
#define _(x,y)          ((x)*25+(y))

#define owner(x)        (agent_sur_case($(x)))
#define invaded(x)      (alien_sur_case($(x)))
#define blocked(x)      ({int __b=(x);type_case($(__b))!=LIBRE||owner(__b)!=undef;})
#define aligned(x,y)    ({int __c=(x),__d=(y);__c/25==__d/25||__c%25==__d%25;})

#define foreach         for

#define direction(x)    my _i=0,_d[4]={1,25,-1,-25};_i<4;_i++)for(my x=_d[_i];x;x=0
#define neighbor(x)     my _i=0,_d[4]={1,25,-1,-25};_i<4;_i++)for(my x=$_+_d[_i];x!=-1&&aligned($_,x);x=-1
#define alien(x)        ...

#define $ME             (moi())
#define $YOU            (adversaire())
#define $TURN           (tour_actuel())

#define agent(x,y)      ({struct position __d=position_agent((y),(x));_(__d.ligne,__d.colonne);})

/* ///////////////////////////////////////////////////////////////////////// */

static int cost[625][625], next[625][625];

static inline void move(int a, int c) {
  struct position p_agent = position_agent(moi(), a), p_cible;

  if (c < 0 || c >= 625)
    return;
  p_cible = $(next[_(p_agent.ligne, p_agent.colonne)][c]);
  if (p_cible.ligne >= 25 || p_cible.colonne >= 25)
    return;

  if (p_agent.ligne - p_cible.ligne > 0)
    (p_agent.ligne - p_cible.ligne == 1) ? deplacer(a, NORD) : glisser(a, NORD);
  else if (p_agent.ligne - p_cible.ligne < 0)
    (p_agent.ligne - p_cible.ligne == -1) ? deplacer(a, SUD) : glisser(a, SUD);
  else if (p_agent.colonne - p_cible.colonne > 0)
    (p_agent.colonne - p_cible.colonne == 1) ? deplacer(a, OUEST) : glisser(a, OUEST);
  else if (p_agent.colonne - p_cible.colonne < 0)
    (p_agent.colonne - p_cible.colonne == -1) ? deplacer(a, EST) : glisser(a, EST);

}

static inline int _abs(int x) { return x > 0 ? x : -x; }

static inline int distance(int x, int y) {
  int p = 0, t = 0;

  if (x < 0 || y < 0 || x >= 625 || y >= 625 || next[x][y] >= 625)
    return NaN;
  for (int n = next[x][y]; x != y; x = n, n = next[n][y]) {
    struct position a = $(x), b = $(n);

    p += (_abs(a.ligne - b.ligne) + _abs(a.colonne - b.colonne) == 1) ? 1 : 3;
    if (p >= 8) {
      t += p / 8;
      p %= 8;
    }
  }
  return t + !!p;
}

#endif /* BATTERY_INCLUDED */
