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

#include "interface.hh"

static void _init_php();

template <typename Lang, typename Cxx>
Lang cxx2lang(Cxx in)
{
    return in.__if_that_triggers_an_error_there_is_a_problem;
}

template <>
zval* cxx2lang<zval*, int>(int in)
{
    zval* x;
    MAKE_STD_ZVAL(x);
    ZVAL_LONG(x, (long)in);
    return x;
}

template <>
zval* cxx2lang<zval*, bool>(bool in)
{
    zval* x;
    MAKE_STD_ZVAL(x);
    ZVAL_BOOL(x, in);
    return x;
}

template <>
zval* cxx2lang<zval*, double>(double in)
{
    zval* x;
    MAKE_STD_ZVAL(x);
    ZVAL_DOUBLE(x, in);
    return x;
}

template <>
zval* cxx2lang<zval*, std::string>(std::string in)
{
    zval* x;
    MAKE_STD_ZVAL(x);
    ZVAL_STRINGL(x, in.c_str(), in.length(), true);
    return x;
}

template <typename Cxx>
zval* cxx2lang_array(const std::vector<Cxx>& in)
{
    zval* x;
    MAKE_STD_ZVAL(x);
    array_init(x);

    size_t s = in.size();

    for (size_t i = 0; i < s; ++i)
      add_next_index_zval(x, cxx2lang<zval*, Cxx>(in[i]));

    return x;
}

template <typename Lang, typename Cxx>
Cxx lang2cxx(Lang in)
{
    return in.__if_that_triggers_an_error_there_is_a_problem;
}

template <>
int lang2cxx<zval*, int>(zval* in)
{
    if (in->type != IS_LONG) {
        zend_error(E_WARNING, "parameter should be an int");
        throw 42;
    }
    return (int)Z_LVAL_P(in);
}

template <>
double lang2cxx<zval*, double>(zval* in)
{
    if (in->type != IS_DOUBLE) {
        zend_error(E_WARNING, "parameter should be a double");
        throw 42;
    }
    return (double)Z_DVAL_P(in);
}

template <>
bool lang2cxx<zval*, bool>(zval* in)
{
    if (in->type != IS_BOOL) {
        zend_error(E_WARNING, "parameter should be a boolean");
        throw 42;
    }
    return Z_BVAL_P(in);
}

template <>
std::string lang2cxx<zval*, std::string>(zval* in)
{
    if (in->type != IS_STRING) {
        zend_error(E_WARNING, "parameter should be a string");
        throw 42;
    }
    return Z_STRVAL_P(in);
}

template <typename Cxx>
std::vector<Cxx> lang2cxx_array(zval* in)
{
    if (in->type != IS_ARRAY) {
        zend_error(E_WARNING, "parameter should be an array");
        throw 42;
    }

    HashTable* ht = Z_ARRVAL_P(in);
    std::vector<Cxx> out;
    size_t s = zend_hash_num_elements(ht);

    for (size_t i = 0; i < s; ++i)
    {
        zval** v;
        zend_hash_index_find(ht, i, (void**)&v);
        out.push_back(lang2cxx<zval*, Cxx>(*v));
    }

    return out;
}
/// Erreurs possibles
template <>
zval* cxx2lang<zval*, erreur>(erreur in)
{
    return cxx2lang<zval*, int>((int)in);
}

template <>
erreur lang2cxx<zval*, erreur>(zval* in)
{
    return (erreur)lang2cxx<zval*, int>(in);
}

/// Types de cases
template <>
zval* cxx2lang<zval*, case_type>(case_type in)
{
    return cxx2lang<zval*, int>((int)in);
}

template <>
case_type lang2cxx<zval*, case_type>(zval* in)
{
    return (case_type)lang2cxx<zval*, int>(in);
}

/// Position sur la carte, donnée par deux coordonnées.
template <>
zval* cxx2lang<zval*, position>(position in)
{
    zval* ret;
    zval* tmp;
    MAKE_STD_ZVAL(ret);
    array_init(ret);
    tmp = (cxx2lang<zval*, int>(in.x));
    add_assoc_zval(ret, "x", tmp);
    tmp = (cxx2lang<zval*, int>(in.y));
    add_assoc_zval(ret, "y", tmp);
    return ret;
}

template <>
position lang2cxx<zval*, position>(zval* in)
{
    position out;
    if (in->type != IS_ARRAY) {
        zend_error(E_WARNING, "parameter is not a structure");
        throw 42;
    }
    zval** tmp;
    HashTable* ht = Z_ARRVAL_P(in);
    if (zend_hash_find(ht, "x", 2, (void**)&tmp) != SUCCESS) {
        zend_error(E_WARNING, "field \"x\" of struct \"position\" not found");
        throw 42;
    }
    out.x = lang2cxx<zval*, int>(*tmp);
    if (zend_hash_find(ht, "y", 2, (void**)&tmp) != SUCCESS) {
        zend_error(E_WARNING, "field \"y\" of struct \"position\" not found");
        throw 42;
    }
    out.y = lang2cxx<zval*, int>(*tmp);
    return out;
}

/// Représente un pulsar existant.
template <>
zval* cxx2lang<zval*, pulsar_info>(pulsar_info in)
{
    zval* ret;
    zval* tmp;
    MAKE_STD_ZVAL(ret);
    array_init(ret);
    tmp = (cxx2lang<zval*, int>(in.periode));
    add_assoc_zval(ret, "periode", tmp);
    tmp = (cxx2lang<zval*, double>(in.puissance));
    add_assoc_zval(ret, "puissance", tmp);
    tmp = (cxx2lang<zval*, int>(in.pulsations_restantes));
    add_assoc_zval(ret, "pulsations_restantes", tmp);
    tmp = (cxx2lang<zval*, int>(in.pulsations_totales));
    add_assoc_zval(ret, "pulsations_totales", tmp);
    return ret;
}

template <>
pulsar_info lang2cxx<zval*, pulsar_info>(zval* in)
{
    pulsar_info out;
    if (in->type != IS_ARRAY) {
        zend_error(E_WARNING, "parameter is not a structure");
        throw 42;
    }
    zval** tmp;
    HashTable* ht = Z_ARRVAL_P(in);
    if (zend_hash_find(ht, "periode", 8, (void**)&tmp) != SUCCESS) {
        zend_error(E_WARNING, "field \"periode\" of struct \"pulsar_info\" not found");
        throw 42;
    }
    out.periode = lang2cxx<zval*, int>(*tmp);
    if (zend_hash_find(ht, "puissance", 10, (void**)&tmp) != SUCCESS) {
        zend_error(E_WARNING, "field \"puissance\" of struct \"pulsar_info\" not found");
        throw 42;
    }
    out.puissance = lang2cxx<zval*, double>(*tmp);
    if (zend_hash_find(ht, "pulsations_restantes", 21, (void**)&tmp) != SUCCESS) {
        zend_error(E_WARNING, "field \"pulsations_restantes\" of struct \"pulsar_info\" not found");
        throw 42;
    }
    out.pulsations_restantes = lang2cxx<zval*, int>(*tmp);
    if (zend_hash_find(ht, "pulsations_totales", 19, (void**)&tmp) != SUCCESS) {
        zend_error(E_WARNING, "field \"pulsations_totales\" of struct \"pulsar_info\" not found");
        throw 42;
    }
    out.pulsations_totales = lang2cxx<zval*, int>(*tmp);
    return out;
}

/// Construit un tuyau sur une case donnée.
PHP_FUNCTION(php_api_construire)
{
    zval* _pos;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &_pos) == FAILURE)
    {
        RETURN_NULL();
    }

        try {
zval* ret = cxx2lang<zval*, erreur>(api_construire(lang2cxx<zval*, position>(_pos)));
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Améliore un tuyau en Super Tuyau™.
PHP_FUNCTION(php_api_ameliorer)
{
    zval* _pos;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &_pos) == FAILURE)
    {
        RETURN_NULL();
    }

        try {
zval* ret = cxx2lang<zval*, erreur>(api_ameliorer(lang2cxx<zval*, position>(_pos)));
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Détruit un tuyau sur une case donnée.
PHP_FUNCTION(php_api_detruire)
{
    zval* _pos;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &_pos) == FAILURE)
    {
        RETURN_NULL();
    }

        try {
zval* ret = cxx2lang<zval*, erreur>(api_detruire(lang2cxx<zval*, position>(_pos)));
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Déplace une unité de puissance d'aspiration d'une case de votre base vers une autre.
PHP_FUNCTION(php_api_deplacer_aspiration)
{
    zval* _source;
    zval* _destination;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &_source, &_destination) == FAILURE)
    {
        RETURN_NULL();
    }

        try {
zval* ret = cxx2lang<zval*, erreur>(api_deplacer_aspiration(lang2cxx<zval*, position>(_source), lang2cxx<zval*, position>(_destination)));
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Déblaye une case de débris.
PHP_FUNCTION(php_api_deblayer)
{
    zval* _pos;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &_pos) == FAILURE)
    {
        RETURN_NULL();
    }

        try {
zval* ret = cxx2lang<zval*, erreur>(api_deblayer(lang2cxx<zval*, position>(_pos)));
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie le type d'une case donnée.
PHP_FUNCTION(php_api_type_case)
{
    zval* _pos;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &_pos) == FAILURE)
    {
        RETURN_NULL();
    }

        try {
zval* ret = cxx2lang<zval*, case_type>(api_type_case(lang2cxx<zval*, position>(_pos)));
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie la liste de tous les pulsars présents.
PHP_FUNCTION(php_api_liste_pulsars)
{
        try {
zval* ret = cxx2lang_array(api_liste_pulsars());
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie la liste des cases contenant du plasma.
PHP_FUNCTION(php_api_liste_plasmas)
{
        try {
zval* ret = cxx2lang_array(api_liste_plasmas());
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie la liste des cases contenant un tuyau ou Super Tuyau™.
PHP_FUNCTION(php_api_liste_tuyaux)
{
        try {
zval* ret = cxx2lang_array(api_liste_tuyaux());
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie la liste des cases contenant un Super Tuyau™.
PHP_FUNCTION(php_api_liste_super_tuyaux)
{
        try {
zval* ret = cxx2lang_array(api_liste_super_tuyaux());
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie la liste des cases contenant des débris.
PHP_FUNCTION(php_api_liste_debris)
{
        try {
zval* ret = cxx2lang_array(api_liste_debris());
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie vrai si et seulement si la case contient un pulsar.
PHP_FUNCTION(php_api_est_pulsar)
{
    zval* _pos;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &_pos) == FAILURE)
    {
        RETURN_NULL();
    }

        try {
zval* ret = cxx2lang<zval*, bool>(api_est_pulsar(lang2cxx<zval*, position>(_pos)));
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie vrai si et seulement si la case contient un tuyau ou un Super Tuyau™.
PHP_FUNCTION(php_api_est_tuyau)
{
    zval* _pos;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &_pos) == FAILURE)
    {
        RETURN_NULL();
    }

        try {
zval* ret = cxx2lang<zval*, bool>(api_est_tuyau(lang2cxx<zval*, position>(_pos)));
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie vrai si et seulement si la case contient un simple tuyau.
PHP_FUNCTION(php_api_est_simple_tuyau)
{
    zval* _pos;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &_pos) == FAILURE)
    {
        RETURN_NULL();
    }

        try {
zval* ret = cxx2lang<zval*, bool>(api_est_simple_tuyau(lang2cxx<zval*, position>(_pos)));
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie vrai si et seulement si la case contient un Super Tuyau™.
PHP_FUNCTION(php_api_est_super_tuyau)
{
    zval* _pos;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &_pos) == FAILURE)
    {
        RETURN_NULL();
    }

        try {
zval* ret = cxx2lang<zval*, bool>(api_est_super_tuyau(lang2cxx<zval*, position>(_pos)));
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie vrai si et seulement si la case contient un débris.
PHP_FUNCTION(php_api_est_debris)
{
    zval* _pos;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &_pos) == FAILURE)
    {
        RETURN_NULL();
    }

        try {
zval* ret = cxx2lang<zval*, bool>(api_est_debris(lang2cxx<zval*, position>(_pos)));
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie vrai si et seulement s'il est possible de construire sur cette case.
PHP_FUNCTION(php_api_est_libre)
{
    zval* _pos;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &_pos) == FAILURE)
    {
        RETURN_NULL();
    }

        try {
zval* ret = cxx2lang<zval*, bool>(api_est_libre(lang2cxx<zval*, position>(_pos)));
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie les informations propres au pulsar à la position donnée.
PHP_FUNCTION(php_api_info_pulsar)
{
    zval* _pos;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &_pos) == FAILURE)
    {
        RETURN_NULL();
    }

        try {
zval* ret = cxx2lang<zval*, pulsar_info>(api_info_pulsar(lang2cxx<zval*, position>(_pos)));
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie la quantité de plasma sur une case donnée.
PHP_FUNCTION(php_api_charges_presentes)
{
    zval* _pos;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &_pos) == FAILURE)
    {
        RETURN_NULL();
    }

        try {
zval* ret = cxx2lang<zval*, double>(api_charges_presentes(lang2cxx<zval*, position>(_pos)));
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie le numéro du joueur ayant dernièrement construit ou amélioré un tuyau sur une case.
PHP_FUNCTION(php_api_constructeur_tuyau)
{
    zval* _pos;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &_pos) == FAILURE)
    {
        RETURN_NULL();
    }

        try {
zval* ret = cxx2lang<zval*, int>(api_constructeur_tuyau(lang2cxx<zval*, position>(_pos)));
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie le numéro du propriétaire d'une case de base.
PHP_FUNCTION(php_api_proprietaire_base)
{
    zval* _pos;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &_pos) == FAILURE)
    {
        RETURN_NULL();
    }

        try {
zval* ret = cxx2lang<zval*, int>(api_proprietaire_base(lang2cxx<zval*, position>(_pos)));
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie la liste des cases composant votre base.
PHP_FUNCTION(php_api_ma_base)
{
        try {
zval* ret = cxx2lang_array(api_ma_base());
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie la liste des cases composant la base de votre ennemi.
PHP_FUNCTION(php_api_base_ennemie)
{
        try {
zval* ret = cxx2lang_array(api_base_ennemie());
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie la puissance d'aspiration d'une case de base donnée. Renvoie -1 si la position n'est pas celle d'une base.
PHP_FUNCTION(php_api_puissance_aspiration)
{
    zval* _pos;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &_pos) == FAILURE)
    {
        RETURN_NULL();
    }

        try {
zval* ret = cxx2lang<zval*, int>(api_puissance_aspiration(lang2cxx<zval*, position>(_pos)));
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie pour une case donnée la liste des cases vers lesquelles le plasma se propagera. Renvoie la liste vide si la case n'est pas une case contenant un tuyau ou si elle n'est reliée à aucune base.
PHP_FUNCTION(php_api_directions_plasma)
{
    zval* _pos;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &_pos) == FAILURE)
    {
        RETURN_NULL();
    }

        try {
zval* ret = cxx2lang_array(api_directions_plasma(lang2cxx<zval*, position>(_pos)));
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie la valeur du coût de la prochaine modification de vos puissances d'aspiration.
PHP_FUNCTION(php_api_cout_prochaine_modification_aspiration)
{
        try {
zval* ret = cxx2lang<zval*, int>(api_cout_prochaine_modification_aspiration());
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie la liste des tuyaux construits par votre adversaire au dernier tour.
PHP_FUNCTION(php_api_hist_tuyaux_construits)
{
        try {
zval* ret = cxx2lang_array(api_hist_tuyaux_construits());
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie la liste des tuyaux détruits par votre adversaire au dernier tour.
PHP_FUNCTION(php_api_hist_tuyaux_detruits)
{
        try {
zval* ret = cxx2lang_array(api_hist_tuyaux_detruits());
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie la liste des tuyaux améliorés par votre adversaire au dernier tour.
PHP_FUNCTION(php_api_hist_tuyaux_ameliores)
{
        try {
zval* ret = cxx2lang_array(api_hist_tuyaux_ameliores());
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie la liste des débris déblayés par votre adversaire au dernier tour.
PHP_FUNCTION(php_api_hist_debris_deblayes)
{
        try {
zval* ret = cxx2lang_array(api_hist_debris_deblayes());
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie la liste des cases de base de votre adversaire qui ont reçu un point d'aspiration (une même case peut apparaître plusieurs fois).
PHP_FUNCTION(php_api_hist_points_aspiration_ajoutes)
{
        try {
zval* ret = cxx2lang_array(api_hist_points_aspiration_ajoutes());
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie la liste des cases de base de votre adversaire qui ont perdu un point d'aspiration (une même case peut apparaître plusieurs fois).
PHP_FUNCTION(php_api_hist_points_aspiration_retires)
{
        try {
zval* ret = cxx2lang_array(api_hist_points_aspiration_retires());
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie votre numéro de joueur.
PHP_FUNCTION(php_api_moi)
{
        try {
zval* ret = cxx2lang<zval*, int>(api_moi());
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie le numéro de votre adversaire.
PHP_FUNCTION(php_api_adversaire)
{
        try {
zval* ret = cxx2lang<zval*, int>(api_adversaire());
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Indique votre nombre de points d'actions restants pour ce tour-ci.
PHP_FUNCTION(php_api_points_action)
{
        try {
zval* ret = cxx2lang<zval*, int>(api_points_action());
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie le score du joueur désigné par le numéro ``id_joueur``. Renvoie -1 si ``id_joueur`` est invalide.
PHP_FUNCTION(php_api_score)
{
    zval* _id_joueur;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &_id_joueur) == FAILURE)
    {
        RETURN_NULL();
    }

        try {
zval* ret = cxx2lang<zval*, int>(api_score(lang2cxx<zval*, int>(_id_joueur)));
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Renvoie le numéro du tour actuel.
PHP_FUNCTION(php_api_tour_actuel)
{
        try {
zval* ret = cxx2lang<zval*, int>(api_tour_actuel());
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Annule la dernière action. Renvoie ``false`` quand il n'y a pas d'action à annuler ce tour-ci.
PHP_FUNCTION(php_api_annuler)
{
        try {
zval* ret = cxx2lang<zval*, bool>(api_annuler());
    RETURN_ZVAL(ret, 0, 0);
    } catch (...) { RETURN_NULL(); }
}

/// Affiche le contenu d'une valeur de type erreur
PHP_FUNCTION(php_api_afficher_erreur)
{
    zval* _v;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &_v) == FAILURE)
    {
        RETURN_NULL();
    }

        try {
api_afficher_erreur(lang2cxx<zval*, erreur>(_v));
    RETURN_NULL();
    } catch (...) { RETURN_NULL(); }
}

/// Affiche le contenu d'une valeur de type case_type
PHP_FUNCTION(php_api_afficher_case_type)
{
    zval* _v;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &_v) == FAILURE)
    {
        RETURN_NULL();
    }

        try {
api_afficher_case_type(lang2cxx<zval*, case_type>(_v));
    RETURN_NULL();
    } catch (...) { RETURN_NULL(); }
}

/// Affiche le contenu d'une valeur de type position
PHP_FUNCTION(php_api_afficher_position)
{
    zval* _v;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &_v) == FAILURE)
    {
        RETURN_NULL();
    }

        try {
api_afficher_position(lang2cxx<zval*, position>(_v));
    RETURN_NULL();
    } catch (...) { RETURN_NULL(); }
}

/// Affiche le contenu d'une valeur de type pulsar_info
PHP_FUNCTION(php_api_afficher_pulsar_info)
{
    zval* _v;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &_v) == FAILURE)
    {
        RETURN_NULL();
    }

        try {
api_afficher_pulsar_info(lang2cxx<zval*, pulsar_info>(_v));
    RETURN_NULL();
    } catch (...) { RETURN_NULL(); }
}

static zend_function_entry module_functions_table[] = {
    PHP_FALIAS(construire, php_api_construire, NULL)    PHP_FALIAS(ameliorer, php_api_ameliorer, NULL)    PHP_FALIAS(detruire, php_api_detruire, NULL)    PHP_FALIAS(deplacer_aspiration, php_api_deplacer_aspiration, NULL)    PHP_FALIAS(deblayer, php_api_deblayer, NULL)    PHP_FALIAS(type_case, php_api_type_case, NULL)    PHP_FALIAS(liste_pulsars, php_api_liste_pulsars, NULL)    PHP_FALIAS(liste_plasmas, php_api_liste_plasmas, NULL)    PHP_FALIAS(liste_tuyaux, php_api_liste_tuyaux, NULL)    PHP_FALIAS(liste_super_tuyaux, php_api_liste_super_tuyaux, NULL)    PHP_FALIAS(liste_debris, php_api_liste_debris, NULL)    PHP_FALIAS(est_pulsar, php_api_est_pulsar, NULL)    PHP_FALIAS(est_tuyau, php_api_est_tuyau, NULL)    PHP_FALIAS(est_simple_tuyau, php_api_est_simple_tuyau, NULL)    PHP_FALIAS(est_super_tuyau, php_api_est_super_tuyau, NULL)    PHP_FALIAS(est_debris, php_api_est_debris, NULL)    PHP_FALIAS(est_libre, php_api_est_libre, NULL)    PHP_FALIAS(info_pulsar, php_api_info_pulsar, NULL)    PHP_FALIAS(charges_presentes, php_api_charges_presentes, NULL)    PHP_FALIAS(constructeur_tuyau, php_api_constructeur_tuyau, NULL)    PHP_FALIAS(proprietaire_base, php_api_proprietaire_base, NULL)    PHP_FALIAS(ma_base, php_api_ma_base, NULL)    PHP_FALIAS(base_ennemie, php_api_base_ennemie, NULL)    PHP_FALIAS(puissance_aspiration, php_api_puissance_aspiration, NULL)    PHP_FALIAS(directions_plasma, php_api_directions_plasma, NULL)    PHP_FALIAS(cout_prochaine_modification_aspiration, php_api_cout_prochaine_modification_aspiration, NULL)    PHP_FALIAS(hist_tuyaux_construits, php_api_hist_tuyaux_construits, NULL)    PHP_FALIAS(hist_tuyaux_detruits, php_api_hist_tuyaux_detruits, NULL)    PHP_FALIAS(hist_tuyaux_ameliores, php_api_hist_tuyaux_ameliores, NULL)    PHP_FALIAS(hist_debris_deblayes, php_api_hist_debris_deblayes, NULL)    PHP_FALIAS(hist_points_aspiration_ajoutes, php_api_hist_points_aspiration_ajoutes, NULL)    PHP_FALIAS(hist_points_aspiration_retires, php_api_hist_points_aspiration_retires, NULL)    PHP_FALIAS(moi, php_api_moi, NULL)    PHP_FALIAS(adversaire, php_api_adversaire, NULL)    PHP_FALIAS(points_action, php_api_points_action, NULL)    PHP_FALIAS(score, php_api_score, NULL)    PHP_FALIAS(tour_actuel, php_api_tour_actuel, NULL)    PHP_FALIAS(annuler, php_api_annuler, NULL)    PHP_FALIAS(afficher_erreur, php_api_afficher_erreur, NULL)    PHP_FALIAS(afficher_case_type, php_api_afficher_case_type, NULL)    PHP_FALIAS(afficher_position, php_api_afficher_position, NULL)    PHP_FALIAS(afficher_pulsar_info, php_api_afficher_pulsar_info, NULL)    {NULL, NULL, NULL}
};
static zend_module_entry api_module_entry = {
    STANDARD_MODULE_HEADER,
    "api",
    module_functions_table,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    "1.0",
    STANDARD_MODULE_PROPERTIES
};

static void _init_php()
{
    static int initialized = 0;
    if (initialized)
        return;
    initialized = 1;

    char* argv[] = { "champion", NULL };
    char buffer[1024];
    const char* path;
    zend_file_handle script;

    path = getenv("CHAMPION_PATH");
    if (!path)
        path = ".";

    snprintf(buffer, 1024, "include('%s/%s.php');", path, "prologin");

    php_embed_init(1, argv PTSRMLS_CC);
    zend_startup_module(&api_module_entry);
    zend_eval_string(buffer, NULL, "PHP to Stechec interface");
}

/// Fonction appelée au début de la partie.
extern "C" void partie_init()
{
    zval* ret;
    zval* fname;
    _init_php();

    MAKE_STD_ZVAL(ret);
    MAKE_STD_ZVAL(fname);
    ZVAL_STRING(fname, "partie_init", 1);
    if (call_user_function(EG(function_table), NULL, fname, ret, 0, NULL TSRMLS_CC) == FAILURE)
    {
        abort();
    }
    zval_ptr_dtor(&ret);
    zval_ptr_dtor(&fname);
}

/// Fonction appelée à chaque tour.
extern "C" void jouer_tour()
{
    zval* ret;
    zval* fname;
    _init_php();

    MAKE_STD_ZVAL(ret);
    MAKE_STD_ZVAL(fname);
    ZVAL_STRING(fname, "jouer_tour", 1);
    if (call_user_function(EG(function_table), NULL, fname, ret, 0, NULL TSRMLS_CC) == FAILURE)
    {
        abort();
    }
    zval_ptr_dtor(&ret);
    zval_ptr_dtor(&fname);
}

/// Fonction appelée à la fin de la partie.
extern "C" void partie_fin()
{
    zval* ret;
    zval* fname;
    _init_php();

    MAKE_STD_ZVAL(ret);
    MAKE_STD_ZVAL(fname);
    ZVAL_STRING(fname, "partie_fin", 1);
    if (call_user_function(EG(function_table), NULL, fname, ret, 0, NULL TSRMLS_CC) == FAILURE)
    {
        abort();
    }
    zval_ptr_dtor(&ret);
    zval_ptr_dtor(&fname);
}

