#ifndef _MACROS_INCLUDED
#define _MACROS_INCLUDED

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

#include "prologin.h"


/* Raccourci dégueu pour pouvoir écrire elem[$(p)] au lieu de elem[p.x][p.y] */
#define $(p)	(p).x][(p).y

/* Raccourci dégueu pour faire des positions à la volée */
#define _(X,Y)	((position){.x=X,.y=Y})

/* L'infini. Sur 32 bits. */
#define INFNTY	1000000000


/* Superbe implémentation d'une file en C */
position _file[TAILLE_TERRAIN * TAILLE_TERRAIN];
int _debut, _fin;

#define INITIALISER_FILE()	do{_debut=_fin=0;}while(0)
#define FILE_VIDE()		((_debut%=(TAILLE_TERRAIN*TAILLE_TERRAIN*TAILLE_TERRAIN))==(_fin%=(TAILLE_TERRAIN*TAILLE_TERRAIN*TAILLE_TERRAIN)))

#define ENFILER(p)		do{_file[_debut++%(TAILLE_TERRAIN*TAILLE_TERRAIN*TAILLE_TERRAIN)]=(p);}while(0)
#define DEFILER()		(_file[_fin++%(TAILLE_TERRAIN*TAILLE_TERRAIN*TAILLE_TERRAIN)])

/* Regarde si une case donnée est valide -- Ni une base, nis hors-terrain */
#define VALIDE(p)		(type_case(p)!=INTERDIT&&type_case(p)!=BASE)

/* Sommes-nous le joueur vertical ? */
#define EN_VERTICAL()		(proprietaire_base(_(13,0))==moi())

/* Macros très pratiques pour itérer « proprement » sur les cases */
#define POUR_CHAQUE_BASE(p)	for(position_array _b=ma_base();_b.length;free((_b.length=0,_b.datas)))for(size_t _i=0,__=1;_i<_b.length;_i++,__=1)for(position p=_b.datas[_i];__;__=0)
#define POUR_CHAQUE_BASE_ENNEMIE(p)	for(position_array _b=base_ennemie();_b.length;free((_b.length=0,_b.datas)))for(size_t _i=0,__=1;_i<_b.length;_i++,__=1)for(position p=_b.datas[_i];__;__=0)
#define POUR_CHAQUE_CASE(p)	for(int _n=0,__=1;_n<39*39;_n++,__=1)for(position p=(position){.x=_n%39,.y=_n/39};__;__=0)
#define POUR_CHAQUE_VOISIN(p,v)	for(int _n=0,__=1,_x=0,_y=1,_z;_n<4;_n++,__=1,_z=_x,_x=-_y,_y=_z)for(position v=(position){.x=(p).x+_x,.y=(p).y+_y};VALIDE(v)&&__;__=0)

/* Raccourci pour réinitialiser un tableau statique (ou une structure) à 0 */
#define NETTOYER(t)	memset((t),0,sizeof(t))

/* Raccourci pour copier un tableau statique */
#define COPIER(a,b)	memmove((b),(a),sizeof(b))

#define ECHANGER(a,b)	do { position _c = (a); (a) = (b); (b) = _c; } while(0)
#define max(a,b)	((a)>(b)?(a):(b))
#define TIMEOUT_PROTECTION() do { if (3 * (clock() - t) >= 2 * CLOCKS_PER_SEC) return; } while(0)

#endif /* _MACROS_INCLUDED */
