/*
 * Ce délicieux programme écrit en C avec amour ne saura vous évoquer que
 * morts violentes et chatons colériques. Celui-ci fait encore preuve d'un
 * abus déplorable de l'outil le plus fantastique jamais inventé pour un
 * langage de programmation : un préprocesseur.
 *
 * Il n'y a pas de véritable principe astucieux, il s'agit d'un assemblage
 * simpliste de méthodes bourrines pour déterminer les solutions localement
 * optimales.
 *
 * En gros, on essaye de placer au mieux l'échantillon, puis de triturer
 * au mieux les catalyseurs pour faire chier le plus, à notre plus grand
 * intérêt.
 *
 * Deux choses manquent à ce programme : un parcours plus approfondi des
 * situations possibles, en effectuant non pas une mais deux transmutations
 * possibles, ou alors une transmutation et une catalyse ; ainsi que la
 * réécriture de la bibliothèque fournie du point de vue de l'adversaire,
 * afin d'anticiper ses coups localement optimaux, et agir en conséquence.
 *
 * Outre le « manque de temps » absolument pas ressenti, la contrainte
 * agréablement spectaculaire de pratiquer le C au lieu d'autres prétendus
 * langages de « haut niveau » a pu potentiellement fortement réviser les
 * ambitions de l'auteur à la baisse.
 *
 * La page 6 du « Livret du candidat » résume très bien ce que l'on devra
 * retenir de l'expérience : « Les meilleurs codent en C ».
 *
 * Vous pouvez pas monkey test ...
 */
#include "mess.h"


/* ... et vous avez perdu */
THE_GAME {
  E e = echantillon_tour();
  int fst = e.element1, snd = e.element2, plus_large, catalyseurs;

  /*
   * Cherche où placer l'échantillon dans la grille moyennant des critères
   * heuristiques plus ou moins arbitraires.
   */
  for (int _ = 0; _ < 36; _++)
    /* Ce n'est pas du Perl, je vous l'assure */
    if (!est_vide($_, moi())) {
      S meilleur = {0};

      for (int _ = 0; _ < 36; _++) {
        int cout = taille_region($_, moi());

        /*
         * On s'autorise à transmuter au plus une région.
         * À la base je voulais faire deux, parce que ça passe en temps,
         * mais finalement, j'ai eu la flemme.
         */
        transmuter($_);
        {
          PE_A a = placements_possible_echantillon(e, moi());

          while (a.length--) {
            PE x = a.datas[a.length];

            placer_echantillon(x.pos1, x.pos2);
            {
              /*
               * Le score d'une situation possible est simple : il s'agit
               * de l'or total potentiel en plaçant l'échantillon à un
               * endroit, et idéalement en ne transmutant aucune région.
               *
               * Si transmutation il y a, alors on choisit la plus grande
               * région pour laquelle ça marche, afin de libérer de la place
               * pour les autres échantillons futurs.
               */
              int score = potentiel(x.pos1, moi()) + potentiel(x.pos2, moi())
                        - (!!cout) * (1000 - cout);

              /* On a ajouté un champ « non_vide » pour éviter les fuites */
              if (!meilleur.non_vide || score >= meilleur.score)
                meilleur = $S(x, $_, score);
            }
            annuler();
          }
          /* Libérée, délivrée */
          free(a.datas);
        }
        annuler();
      }
      if (meilleur.non_vide) {
        transmuter(meilleur.p);
        placer_echantillon(meilleur.x.pos1, meilleur.x.pos2);
      }
      break;
    }

  /*
   * La boucle géante suivante se charge d'effectuer les catalyses.
   * Puisqu'on peut être amené à recréer des éléments utilisables pour
   * la catalyse, on effectue ces opérations un nombre arbitraire de fois
   * (ici, 5) en boucle.
   */
  for (int _ = 0; _ < 5; _++) {

    /*
     * On commence par éliminer les régions d'éléments de catalyse qui
     * sont plus grandes que les régions de « vrais » éléments.
     *
     * On prend évidemment garde à ne pas supprimer celles qui ne valent rien.
     */
    plus_large = 0;
    for (int _ = 0; _ < 36; _++)
      if (propriete_case_type(type_case($_, moi())) == TRANSMUTABLE_OR) {
        int taille = taille_region($_, moi());

        if (taille > plus_large)
          plus_large = taille;
      }
    if (plus_large >= 3)
      for (int _ = 0; _ < 36; _++)
        if (propriete_case_type(type_case($_, moi())) == TRANSMUTABLE_CATALYSEUR
            && taille_region($_, moi()) >= plus_large)
          transmuter($_);

    /*
     * Ensuite, on détermine toutes les cases que l'on peut catalyser chez
     * l'ennemi pour le faire chier le plus : le degré dit de « chiantisme »
     * est calculé comme la différence de la somme du carré de la taille
     * des régions respectives des voisins d'une case avant et après catalyse.
     *
     * Ce degré est calculé ainsi pour favoriser la déconnexion de grandes
     * régions en plusieurs régions plus petites, plutôt que d'émietter
     * bout à bout les régionsi adverses.
     */
    catalyseurs = nombre_catalyseurs();
    for (int _ = 0; _ < catalyseurs; _++) {
      T pire = {0};

      for (int _ = 0; _ < 36; _++)
        if (!est_vide($_, adversaire()))
          for (int e = PLOMB; e <= MERCURE; e++)
            if (type_case($_, adversaire()) != e) {
              int score = 0, x;
              
              /* Alors oui, c'est moche, mais les boucles aussi */
              x = taille_region($P($_.ligne+1, $_.colonne), adversaire());
              score += x * x;
              x = taille_region($P($_.ligne-1, $_.colonne), adversaire());
              score += x * x;
              x = taille_region($P($_.ligne, $_.colonne+1), adversaire());
              score += x * x;
              x = taille_region($P($_.ligne, $_.colonne-1), adversaire());
              score += x * x;

              catalyser($_, adversaire(), e);
              {
                x = taille_region($P($_.ligne+1, $_.colonne), adversaire());
                score -= x * x;
                x = taille_region($P($_.ligne-1, $_.colonne), adversaire());
                score -= x * x;
                x = taille_region($P($_.ligne, $_.colonne+1), adversaire());
                score -= x * x;
                x = taille_region($P($_.ligne, $_.colonne-1), adversaire());
                score -= x * x;

                if (!pire.non_vide || score >= pire.score)
                  pire = $T(e, $_, score);
              }
              annuler();
            }
      if (pire.non_vide)
        catalyser(pire.p, adversaire(), pire.element);
    }

    /*
     * Si on est au dernier tour, on peut bricoler pour augmenter son score
     * final à partir des éléments de catalyse disponibles chez soi.
     *
     * On le fait après l'opération précédente pour d'abord favoriser
     * notre création d'or par l'opération suivante.
     */
    if (tour_actuel() >= 149)
      for (int _ = 0; _ < 36; _++)
        if (propriete_case_type(type_case($_, moi()))
            == TRANSMUTABLE_CATALYSEUR
            && valeur($_, moi()) > 0)
          transmuter($_);

    /*
     * On regarde les éléments que l'on peut catalyser chez soi pour augmenter
     * la valeur des régions.
     *
     * C'est toujours utile, ça marche bien, et c'est cool en fin de partie.
     */
    catalyseurs = nombre_catalyseurs();
    for (int _ = 0; _ < catalyseurs; _++) {
      T meilleur = {0};

      for (int _ = 0; _ < 36; _++)
        if (!est_vide($_, moi()))
          for (int e = PLOMB; e <= MERCURE; e++)\
            if (type_case($_, moi()) != e) {
              int score = -valeur($_, moi());

              catalyser($_, moi(), e);
              {
                score += valeur($_, moi());

                if (!meilleur.non_vide || score >= meilleur.score)
                  meilleur = $T(e, $_, score);
              }
              annuler();
            }
      if (meilleur.non_vide)
        catalyser(meilleur.p, moi(), meilleur.element);
    }
  }

  /* Pour correctement tout rafler à la fin de la partie */
  if (tour_actuel() >= 149)
    for (int _ = 0; _ < 36; _++)
      if (valeur($_, moi()) >= 0)
        transmuter($_);

  /*
   * Ici, on inspecte les terres ennemies pour voir s'il a les moyens de
   * créer des catalyseurs lors du tour prochain : si c'est le cas,
   * on se prémunit de tous problèmes en transmutant nos plus grandes régions.
   */
  plus_large = 0;
  for (int _ = 0; _ < 36; _++)
    if (propriete_case_type(type_case($_, adversaire()))
        == TRANSMUTABLE_CATALYSEUR) {
      int taille = taille_region($_, adversaire());

      if (taille > plus_large)
        plus_large = taille;
    }
  
  if (quantite_transmutation_catalyseur(plus_large)) {
    for (int _ = 0; _ < 36; _++)
      if (propriete_case_type(type_case($_, moi())) == TRANSMUTABLE_OR
          && taille_region($_, moi()) >= 7)
        transmuter($_);
  }

  /* Au cas où on n'a pas placé d'échantillon, on le fait dans un coin */
  placer_echantillon($P(0,0), $P(0,1));
  {
    /*
     * On donne à l'adversaire les deux éléments qu'il a le moins,
     * en se débrouillant avec la contrainte de devoir lui donner un élément
     * qu'on a reçu.
     */
    int compte[MERCURE] = {0}, minimal = 1, suivant = 1;

    for (int _ = 0; _ < 36; _++)
      compte[type_case($_, adversaire())]++;
    for (int _ = PLOMB; _ <= MERCURE; _++)
      if (compte[_] <= compte[minimal])
        suivant = minimal, minimal = _;
    if (minimal != fst && minimal != snd && suivant != fst && suivant != snd)
      suivant = (compte[fst] < compte[snd]) ? fst : snd;
    donner_echantillon($E(minimal, suivant));
  }
}
