/*!
** This file has been generated, if you wish to
** modify it in a permanent way, please refer
** to the script file : gen/generator_c.rb
*/

#pragma once

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

/*!
** Taille de l’établi de travail (longueur et largeur)
*/
# define TAILLE_ETABLI             6

/*!
** Nombre de tours à jouer avant la fin de l’affrontement
*/
# define NB_TOURS                  150

/*!
** Taille de l’énumération ``case_type``
*/
# define NB_TYPE_CASES             6

/*!
** Types de cases
*/
typedef enum case_type {
  VIDE, /* <- Case vide */
  PLOMB, /* <- Plomb ; transmutable en or */
  FER, /* <- Fer ; transmutable en or */
  CUIVRE, /* <- Cuivre ; transmutable en or */
  SOUFRE, /* <- Soufre ; transmutable en catalyseur */
  MERCURE, /* <- Mercure ; transmutable en catalyseur */
} case_type;


/*!
** Types de propriétés des éléments
*/
typedef enum element_propriete {
  AUCUNE, /* <- Les cases vides ne contiennent pas d’élément, et n’ont donc aucune propriété */
  TRANSMUTABLE_OR, /* <- Élement transmutable en or */
  TRANSMUTABLE_CATALYSEUR, /* <- Élément transmutable en catalyseur */
} element_propriete;


/*!
** Erreurs possibles
*/
typedef enum erreur {
  OK, /* <- L’action a été exécutée avec succès */
  POSITION_INVALIDE, /* <- La position spécifiée n’est pas sur l’établi */
  PLACEMENT_INVALIDE, /* <- Les deux positions ne correspondent pas à des cases adjacentes */
  PLACEMENT_IMPOSSIBLE, /* <- Les cases ciblées ne sont pas vides */
  PLACEMENT_INCORRECT, /* <- Un des deux éléments de l'échantillon doit être placé adjacent à un élément du même type déjà présent sur l'établi */
  CASE_VIDE, /* <- La case ciblée est vide */
  ECHANTILLON_INCOMPLET, /* <- L’échantillon doit contenir deux éléments. */
  ECHANTILLON_INVALIDE, /* <- L’échantillon doit contenir au moins un des éléments de l’échantillon reçu auparavant */
  AUCUN_CATALYSEUR, /* <- Aucun catalyseur disponible */
  CATALYSE_INVALIDE, /* <- L'élément de destination ne peut pas être vide. */
  DEJA_POSE, /* <- L’échantillon a déjà été posé ce tour-ci */
  DEJA_DONNE, /* <- L’échantillon a déjà été donné ce tour-ci */
} erreur;


/*!
** Types d’actions
*/
typedef enum action_type {
  ACTION_PLACER, /* <- Action ``placer_echantillon`` */
  ACTION_TRANSMUTER, /* <- Action ``transmuter`` */
  ACTION_CATALYSER, /* <- Action ``catalyser`` */
  ACTION_DONNER_ECHANTILLON, /* <- Action ``donner_echantillon`` */
} action_type;


struct position;
struct echantillon;
struct position_echantillon;
struct action_hist;

typedef struct position_array {
  struct position* datas;
  size_t length;
} position_array;

typedef struct position_echantillon_array {
  struct position_echantillon* datas;
  size_t length;
} position_echantillon_array;

typedef struct action_hist_array {
  struct action_hist* datas;
  size_t length;
} action_hist_array;

/*!
** Position sur la carte, donnée par deux coordonnées
*/
typedef struct position {
  int ligne;  /* <- Coordonnée : ligne */
  int colonne;  /* <- Coordonnée : colonne */
} position;


/*!
** Échantillon, défini par deux types d’éléments
*/
typedef struct echantillon {
  case_type element1;  /* <- Élément 1 */
  case_type element2;  /* <- Élément 2 */
} echantillon;


/*!
** Position d’un échantillon, donnée par deux positions adjacentes
*/
typedef struct position_echantillon {
  position pos1;  /* <- Position de l’élément 1 de l’échantillon */
  position pos2;  /* <- Position de l’élément 2 de l’échantillon */
} position_echantillon;


/*!
** Action représentée dans l’historique. L’action ``placer_echantillon`` utilise ``pos1`` et ``pos2``. L’action ``transmuter`` utilise ``pos1``. L’action ``catalyser`` utilise ``pos1``, ``id_apprenti`` et ``nouvelle_case``. L’action ``donner_echantillon`` n’est pas représentée dans l’historique, car ``echantillon_tour`` donne l’information.
*/
typedef struct action_hist {
  action_type atype;  /* <- Type de l’action */
  position pos1;  /* <- Position, pour les actions placer (1er élément), transmuter et catalyser */
  position pos2;  /* <- Position, pour l’action placer (2e élément) */
  int id_apprenti;  /* <- ID de l’apprenti, pour l’action catalyser */
  case_type nouvelle_case;  /* <- Élément pour l’action catalyser */
} action_hist;


/*!
** Place l’échantillon du tour sur l’établi, avec les coordonnées de deux cases adjacentes.
*/
erreur placer_echantillon(position pos1, position pos2);

/*!
** Provoque la transformation chimique de l’élément à la case ciblée, ainsi que tous les éléments adjacents du même type, ceux du même type adjacents à ces derniers, etc. Ils disparaissent alors tous dans leur transmutation en or ou en catalyseur.
*/
erreur transmuter(position pos);

/*!
** Utilise un catalyseur sur la case ciblée de l'apprenti indiqué. Transforme l’ancien élément en l’élément indiqué.
*/
erreur catalyser(position pos, int id_apprenti, case_type terrain);

/*!
** Définit l’échantillon que l’adversaire recevra à son prochain tour.
*/
erreur donner_echantillon(echantillon echantillon_donne);

/*!
** Renvoie le type d’une case donnée, ou 0 si la case est invaide.
*/
case_type type_case(position pos, int id_apprenti);

/*!
** Indique si une case donnée est vide ou contient un élément. Renvoie faux en cas d'erreur.
*/
bool est_vide(position pos, int id_apprenti);

/*!
** Renvoie la propriété de l’élément sur une case donnée. Un élément invalide n'a pas de propriété.
*/
element_propriete propriete_case(position pos, int id_apprenti);

/*!
** Renvoie la propriété d’un type de case donné.
*/
element_propriete propriete_case_type(case_type ctype);

/*!
** Renvoie la taille de la région à laquelle appartient un élément. Renvoie -1 si la position est invalide.
*/
int taille_region(position pos, int id_apprenti);

/*!
** Renvoie la liste des positions des cases composant la région à laquelle appartient un élément donné. Renvoie une liste vide en cas d'erreur.
*/
position_array positions_region(position pos, int id_apprenti);

/*!
** Détermine si le placement d’un échantillon est valide.
*/
bool placement_possible_echantillon(echantillon echantillon_a_placer, position pos1, position pos2, int id_apprenti);

/*!
** Renvoie la liste des placements possibles pour un échantillon donné sur l’établi d’un apprenti donné. Renvoie une liste vide en cas d'erreur.
*/
position_echantillon_array placements_possible_echantillon(echantillon echantillon_a_placer, int id_apprenti);

/*!
** Renvoie la liste des actions jouées par l’adversaire pendant son tour, dans l’ordre chronologique.
*/
action_hist_array historique(void);

/*!
** Renvoie votre numéro d’apprenti.
*/
int moi(void);

/*!
** Renvoie le numéro d’apprenti de votre adversaire.
*/
int adversaire(void);

/*!
** Renvoie la quantité d’or amassée par l’apprenti désigné par le numéro ``id_apprenti``. Renvoie 0 si ``id_apprenti`` est invalide (attention, le score d’un apprenti valide peut aussi être 0).
*/
int score(int id_apprenti);

/*!
** Renvoie le numéro du tour actuel.
*/
int tour_actuel(void);

/*!
** Annule la dernière action. Renvoie ``false`` quand il n’y a pas d’action à annuler ce tour-ci.
*/
bool annuler(void);

/*!
** Indique le nombre de catalyseurs en votre possession.
*/
int nombre_catalyseurs(void);

/*!
** Indique l’échantillon reçu pour ce tour.
*/
echantillon echantillon_tour(void);

/*!
** Indique si l’échantillon reçu pour ce tour a déjà été posé.
*/
bool a_pose_echantillon(void);

/*!
** Indique si un échantillon a déjà été donné ce tour.
*/
bool a_donne_echantillon(void);

/*!
** Renvoie la quantité d’or (et donc le score) obtenue par la transmutation de ``taille_region`` éléments transmutables en or.
*/
int quantite_transmutation_or(int taille_region);

/*!
** Renvoie la quantité de catalyseurs obtenue par la transmutation de ``taille_region`` éléments transmutables en catalyseur.
*/
int quantite_transmutation_catalyseur(int taille_region);

/*!
** Renvoie la quantité d’or obtenue par la transmutation de ``taille_region`` éléments transmutables en catalyseur.
*/
int quantite_transmutation_catalyseur_or(int taille_region);

/*!
** Indique l’échantillon par défaut lors du premier tour
*/
echantillon echantillon_defaut_premier_tour(void);

/*!
** Affiche l'état actuel des deux établis dans la console.
*/
void afficher_etablis(void);

/*!
** Affiche le contenu d'une valeur de type case_type
*/
void afficher_case_type(case_type v);

/*!
** Affiche le contenu d'une valeur de type element_propriete
*/
void afficher_element_propriete(element_propriete v);

/*!
** Affiche le contenu d'une valeur de type erreur
*/
void afficher_erreur(erreur v);

/*!
** Affiche le contenu d'une valeur de type action_type
*/
void afficher_action_type(action_type v);

/*!
** Affiche le contenu d'une valeur de type position
*/
void afficher_position(position v);

/*!
** Affiche le contenu d'une valeur de type echantillon
*/
void afficher_echantillon(echantillon v);

/*!
** Affiche le contenu d'une valeur de type position_echantillon
*/
void afficher_position_echantillon(position_echantillon v);

/*!
** Affiche le contenu d'une valeur de type action_hist
*/
void afficher_action_hist(action_hist v);

/*!
** Fonction appelée au début de la partie.
*/
void partie_init(void);

/*!
** Fonction appelée à chaque tour.
*/
void jouer_tour(void);

/*!
** Fonction appelée à la fin de la partie.
*/
void partie_fin(void);

