//**********************************************************************
//**********************************************************************
//	Projet      : Ulysse
//	Laboratoire : GREYC-ISMRA
//	Fichier     : agent-virtuel.cc
//      Annee       : 1997          ,
//	Auteur      : Christophe GODEREAUX
//**********************************************************************
//**********************************************************************


#include "util.cc"
//#include <osfcn.h>	//pour unlink

#define Je 	(*this)
#define J 	(*this)
#define Mon 	(*this)
#define Ma 	(*this)

#define CP strcpy

#define LONGUEUR_TEXTE_MAX 10000
#define TAILLE_REPLIQUE 150



// $$$$$$$$$$$$ VARIABLE GLOBALE DEFINIE DANS init3.cc $$$$$$$$$$

extern LexList*  dictionnaire;


char * valeur(Edge* PO,char* chemin, char* champ)
// Dans ce cas j'alloue la memoire necessaire -> penser a la deleter
// -> pas encore fait a cause de PO.
{
  if (strcmp(chemin,"")==0)
       return strdup(((DAG&)(PO->label()))[champ].Symbole());
  else return strdup((*(PO->GetNoeud(chemin)))[champ].Symbole());
}

char * valeur_sans_strdup(Edge* PO,char* chemin, char* champ)
// s'en servir avec des pincettes ou avec des fonctions sures comme si 
// dessous : CPV, egv et existev
// Le probleme est que ca retourne un pointeur sur la structure. Si ensuite
// on modifie la valeur pointee, on modifie aussi la structure ....
{ 
  if (strcmp(chemin,"")==0){//DEB4
       return ((DAG&)(PO->label()))[champ].Symbole();}
  else { return (*(PO->GetNoeud(chemin)))[champ].Symbole();}
}

void valeur_ens(char* tmp,Edge* PO,char* chemin, char* champ)
{
  ostrstream fl(tmp,100);
  if (strcmp(chemin,"")==0){
    fl<<((DAG&)(PO->label()))[champ];
    enlever_char(tmp,"{},");
  }

  //else fl<<(*(PO->GetNoeud(chemin)))[champ].Symbole();
}

/*void CPV(char*p,Edge* PO,char* chemin, char* champ)
  // copie dans p de la valeur du noeud ... sans allouer des char inutiles,
  // grace a valeur_sans_strdup.
{
  CP(p,valeur_sans_strdup(PO,chemin,champ));
}
*/

void CPNUM(char*p,Edge* PO,char* chemin, char* champ)
  // copie dans p de la valeur du noeud qui peut etre un entier
  // ... sans allouer des char inutiles, car res est delete
  // en cas de valeur inexistante un pointeur NULL est retourne dans res
  // je pense que CPV peut etre remplace par CPNUM car CPV plante
  // pour lire des entiers. de plus CPNUM ne plante pas pour les ensembles
  // c'est ce que j'ai fait : 
  // maintenant le vrai CPV en est en commentaire
{
  char* res;
  if (strcmp(chemin,"")==0)
    res=((DAG&)(PO->label()))[champ].valeurAtomique();
  else
    res=(*(PO->GetNoeud(chemin)))[champ].valeurAtomique();
  if (res){
    CP(p,res);
    delete res;
  } else CP(p,VIDE);  // si le champ n'existe pas on recopie la valeur VIDE
}

int RENDNUM(Edge* PO,char* chemin, char* champ)
{
  char cnum[50];
  CPNUM(cnum,PO,chemin,champ);
  return atoi(cnum);
}

void CPV(char*p,Edge* PO,char* chemin, char* champ)
//en fait CPV et CPNUM sont identique maintenant
{
  CPNUM(p,PO,chemin,champ);
}


int egv(Edge* PO,char* chemin, char* champ, char* b)
  // comparaison de p et de la valeur du noeud ... sans allouer des char 
  // inutiles, grace a valeur_sans_strdup.
{
  return !strcmp(valeur_sans_strdup(PO,chemin,champ),b);
}


int existev(Edge* PO,char* chemin, char* champ)
  // test d'existence de la valeur du noeud ... sans allouer des char 
  // inutiles, grace a valeur_sans_strdup.
{
  return existe(valeur_sans_strdup(PO,chemin,champ));
}

char * texte(Edge* PO)
{
  char texte[500]="";
  return strdup(&((*PO).Words(texte))[1]);
}

struct t_memoire_linguistique {
	t_gn gn_masc,gn_fem,dernier_gn;
	t_gv dernier_gv;
	t_tab_prop tab_prop;
	char derniere_replique_orale[TAILLE_REPLIQUE];

};



//**********************************************************************
//			Memoire linguistique commune aux agents
//**********************************************************************

struct pair_prop{
	char * nom;
	t_tab_prop tab;
};


ostream& operator<<(ostream& s,  pair_prop &t)
{
  s<<"************************** \n";
  if (existe(t.nom)) s<<t.nom<<'\n';
  return s<<t.tab;
}


class Memoire_ling {

public :
	Tablo<pair_prop> prop_compose;

	Memoire_ling(int );
	int exister_deja_verbe_comp(const char *,t_tab_prop&);
	void ajouter(const char *,t_tab_prop&);
};

Memoire_ling::Memoire_ling(int i)
:prop_compose(i)
{
}

int Memoire_ling::exister_deja_verbe_comp(const char * nom,t_tab_prop& props)
{
  for(int i=0;i<prop_compose.nbr();i++)
    if (eg(prop_compose[i].nom,nom)) {
      props= prop_compose[i].tab;
      return TRUE;
  } 
  return FALSE;
}

void Memoire_ling::ajouter(const char * nom,t_tab_prop& props)
{
  pair_prop p;
  p.tab=props;
  p.nom=strdup(nom);
  prop_compose.ajouter(p);

}


//**********************************************************************
//**********************************************************************
//**********************************************************************
//********************** AGENT_VIRTUEL
//**********************************************************************
//**********************************************************************
//**********************************************************************

class Controleur;
Memoire_ling mem_ling_commune(30);

class Agent_virtuel : public Locuteur{
	char nom_agent_user[20],user[20],prenom_user[20];
	t_tab_prop tab_prop;
	int nouveau_agent;

	int buffer;
	RuleList *rules;
	LexList *dico;
	tablocution *sons;

  public:
	char nom[20];
	char nom_entree_carte_vocale[60], nom_dive[60];
	int locuteur;
	t_memoire_linguistique mem_ling;
	Controleur *controleur;

	Agent_virtuel();
	Agent_virtuel(char*,char*,char *,char *,char*,RuleList *,LexList *
		     ,int, tablocution *,Controleur *);
	ostream& affiche(ostream& s );
	char* son_nom(){return nom;}
	char* son_prenom(){return nom;}
	int cree_nouveau_agent(){return nouveau_agent;}
	void initialise_champ_nouveau_agent() {nouveau_agent=0;}
	int analyse_syntaxiquement(Chart* & ,const Edge* &);
        void analyse_semantiquement(char *,t_tab_prop&);
        void analyse_semantiquement(Edge* ,t_tab_prop&);
        void analyse_semantiquement(t_tab_prop&);
	void analyse_replique_sn(Edge*,t_tab_prop&);
        void analyse_prop(Edge*,t_tab_prop&);
        void analyse_ordre(Edge* ,t_tab_prop&);
        void analyse_interrogation(Edge* ,t_tab_prop&);
        void analyse_affirmation(Edge*,t_tab_prop&);
        void analyse_subordonnee(Edge*,t_tab_prop&);
	void analyse_gprepv(Edge* ,t_tab_prop&);
        void analyse_intro(Edge*,t_tab_prop&);
        void analyse_interrogation_deb(t_prop &,Edge*);
        void analyse_salutation(Edge*,t_tab_prop&);
        void analyse_interjection(Edge*,t_tab_prop&);
	void analyse_adverbe(Edge*,t_tab_prop&);
	void analyse_gn(Edge*,t_prop&);
        void traite_enonce(Chart*,char*,char*);
        int traite_enonce(char*,char*);
        void traite_enonce(Edge* ,t_tab_prop&);
	int traite_enonce(Chart* ,char* ,t_tab_prop &,int);
	int compte_analyse_syntaxique(Chart *);
        void me_dis(char*);
        void dit(char*);
        t_prop cree_dire(char *);
        void cree_dire(char *,t_tab_prop&);
        void cree(t_prep&,Edge*);
        void cree_propersdis(t_gn&,Edge*);
	void cree(t_adv &,Edge*);
	void cree(t_adv *,int&,Edge*);
	void cree(t_adj *,int&, Edge*);
        void cree(t_det &,Edge*);
        void cree(t_gn &, Edge*);
        void cree_gn_intermediaire(t_tab_gn&, Edge*);
        void cree(t_tab_gn&,Edge*);
        void cree_sujet(t_tab_gn &,Edge*);
        void cree_pronom_gv(t_gv&,Edge*);
        void cree_relation(char*,Edge*);
	void cree(t_gv &,Edge*,char*,char*); 
	void consulte_dico_verbe(t_gv &,char*);
	void cree_prop_loc_verb(t_gv&);
        void cree_prop(t_prop&,Edge*,char *,char*,char*);
	void affiche_prop(t_prop p){cout<<p;}
	void affiche_props(t_tab_prop p){cout<<p;}
	void transmet_tab_prop(){tab_prop.transmettre(nom_dive);}
	int ajoutePdansTsuivantR(t_tab_gn &P,t_tab_gn &T,char* R);
	int ajoutePdansTsuivantR(t_prop &P,t_tab_prop &T,char* R);
	int ajoutePdansTsuivantR(t_tab_prop &P,t_tab_prop &T,char* R);
	int analyse_actes();
	char* parle();
	void parle(char*);
	char * ecoute(char* );
	int ecoute_agent(char* );
	int ecoute_agent_suite(char* ,FILE *);
	char* derniere_replique(char*,char* ,int);
	char * derniere_replique_ecrite();
	int exister_deja_verbe_comp(const char *n,t_tab_prop& p){
	// return Mon.controleur->mem_ling_commune.exister_deja_verbe_comp(n,p);}
	  return mem_ling_commune.exister_deja_verbe_comp(n,p);}
	void ajoute_dans_mem_ling_commune(const char *n,t_tab_prop& p){
	  mem_ling_commune.ajouter(n,p);}
	void efface_replique(){unlink(Mon.nom_entree_carte_vocale);}
        void analyse_pragmatiquement(t_tab_prop&);
	void analyse_pragmatiquement_sn(t_tab_gn &gns);
        void pragma_propers(t_gn &);
        void analyse_le_dialogue(t_tab_prop&);
        void analyse_le_dialogue_gn(t_tab_prop&);
        void analyse_le_dialogue_adv(t_tab_prop&);
        int synthetise_ma_replique(char*);
        int synthetise_ma_reponse(char*,t_tab_prop &);
  	void gere_l_historique_du_dialogue(t_tab_prop &);
};


//**********************************************************************
//	CONSTRUCTEUR + OSTREAM + AUTRES
//**********************************************************************
Agent_virtuel::Agent_virtuel(char* n,char* rep,char*user0,char* agent_user,
			     char* prenom,
			     RuleList *rules0,LexList *dico0,int numloc,
			     tablocution *sons0, Controleur *Robert)
{
  Ma.rules=rules0;
  Mon.dico=dico0;
  Mon.sons=sons0;
  CP(Mon.nom,n);
  CP(Mon.nom_agent_user,agent_user);
  CP(Mon.prenom_user,prenom);
  CP(Mon.user,user0);
  sprintf(Mon.nom_dive,"%s/%s.%s",rep,user0,n);
  sprintf(Mon.nom_entree_carte_vocale,"%s/%s.%s.in",rep,user0,n);
//  sprintf(Mon.nom_entree_carte_vocale,"%s/%s.1",rep,user0); 
  Mon.nouveau_agent=0;
  Mon.locuteur=numloc;
  Mon.buffer=0;
  Mon.controleur=Robert;
  CP(Ma.mem_ling.derniere_replique_orale,"OUI");//au cas ou repeter
}

Agent_virtuel::Agent_virtuel()
{
  CP(Mon.nom,"");
  CP(Mon.nom_dive,"");
  CP(Mon.nom_entree_carte_vocale,"");
  Mon.nouveau_agent=0;
}

ostream& Agent_virtuel::affiche(ostream& s )
{ 
   s<<"L'AGENT VIRTUEL :\n";
   s<<"  - Mon nom est "<<nom<<".\n";
   s<<"  - Mon numero de locuteur est : "<<locuteur<<".\n";
   s<<"  - Fichier d'entrée : "<<nom_entree_carte_vocale<<".\n";
   return s<<'\n';
}

char* Agent_virtuel::derniere_replique(char* rep_env,char*,int)
{
 sprintf(rep_env,"%s : %s .\n",nom,mem_ling.derniere_replique_orale);
 enlever_char(rep_env,'_');
 return rep_env;
}

//**********************************************************************
// 	PREPOSITION + PROPERSDIS
//**********************************************************************
void Agent_virtuel::cree(t_prep& prep,Edge* R_PREP)
{
  CPV(prep.sens,R_PREP,"","sens");
  CPV(prep.type,R_PREP,"","type");
  CPV(prep.avec_gv,R_PREP,"","avec_gv");
//deb("avecgv ");debn(valeur(R_PREP,"","avec_gv"));
//cout<<R_PREP->parse();
}

void Agent_virtuel::cree_propersdis(t_gn& gn,Edge* PROPERSDIS)
{
  CPV(gn.n.nombre,PROPERSDIS,"","nombre");
  CPV(gn.n.genre,PROPERSDIS,"","genre");
  CPV(gn.n.sens,PROPERSDIS,"","MOT");
  CP(gn.n.type,"PROPERSDIS");
}

//**********************************************************************
//	DETERMINANT + ADJECTIF
//**********************************************************************
void Agent_virtuel::cree(t_det & det,Edge* DET)
{
/*DEB1
char* res;
DAG& D=(DAG&)(DET->label());
cout<<D;
cout<<'\n'<<D;
res=D["nombre"].valeurAtomique();
DEB2
cout<<res<<'\n';cout.flush();
DEB3
delete res;*/
  CPV(det.type,DET,"","type");
  CPV(det.genre,DET,"","genre");
  CPNUM(det.nombre,DET,"","nombre");
  CPV(det.sens,DET,"","mot");
  CPV(det.quantite,DET,"","quantite");
}

void Agent_virtuel::cree(t_adj * adj,int & n,Edge* R_ADJ)
{
  Edge* p=R_ADJ;
  char recursif[10];
  do {
    if (n==NB_MAX_ADJ) {
      cerr<<"\n\n #### cree(t_adj : NB_MAX_ADJ :trop d'adjectifs\n\n\n";
      return;
    }
    CPV(recursif,p,"","recursif");
    if (!eg(recursif,"oui")||
       (eg(recursif,"oui")&&!egv(p,"","relation","NON"))){
      CPV(adj[n].sens,p,"R_ADJ0 ADJ","MOT");
      CPV(adj[n].genre,p,"R_ADJ0 ADJ","genre");
      CPV(adj[n].nombre,p,"R_ADJ0 ADJ","nombre");
      CPV(adj[n++].type,p,"R_ADJ0 ADJ","type");
    }
    if (eg(recursif,"oui")) {
      p=p->GetEdge("R_ADJ(2)");
    }
  } while (eg(recursif,"oui"));
}

//**********************************************************************
//	ADVERBE
//**********************************************************************
void Agent_virtuel::cree(t_adv &adv,Edge* ADV)
{
  CPV(adv.sens,ADV,"ADV","sens");
  CPV(adv.type,ADV,"ADV","type");
  CPV(adv.acte,ADV,"ADV","acte");
  if (eg(adv.type,"QUANTITÉ")){
    adv.quantite=0;
    if (eg(adv.sens,"+")) adv.compar=1.5;
    if (eg(adv.sens,"++")) adv.compar=2;
    if (eg(adv.sens,"+++")) adv.compar=3;
    if (eg(adv.sens,"-")) adv.compar=0.666667;
    if (eg(adv.sens,"--")) adv.compar=0.5;
    if (eg(adv.sens,"---")) adv.compar=0.333333;
    if (eg(adv.sens,"**")) { adv.compar=0; adv.quantite=3;}
  }
  else if (eg(adv.type,"MANIÈRE")){
    adv.compar=0;
    if (adv.sens[0]=='-') adv.quantite=0.5;
    else if (adv.sens[0]=='+') adv.quantite=2;
    else if (adv.sens[0]=='0') adv.quantite=1;
    CP(adv.sens,&adv.sens[1]);
  }
  else if (eg(adv.type,"LIEU")){
    adv.compar=0;
    adv.quantite=1;
  }
}

void Agent_virtuel::cree(t_adv * adv,int & n,Edge* R_ADV)
{
  Edge* P=R_ADV;
  char recursif[5]="";
  do {
    if (n==NB_MAX_ADV){
	cerr<<"\n\n\n??????cree(tab_adv:danger NB_MAX_ADV depasse\n\n\n\n";
	cerr.flush();
	return;
    }
    Je.cree(adv[n++],P->GetEdge("R_ADV0 ADV"));
//cout<<"n="<<n<<" adv[n-1]="<<adv[n-1];
    if (n>1 && eg(adv[n-2].type,"QUANTITÉ")){
//cout<<"test quantité:"<<"adv[n-2].type:avec n="<<n<<adv[n-2].type<<'\n';
      if (eg(adv[n-1].type,"QUANTITÉ")){
	  adv[n-1].compar*=adv[n-2].compar;
          adv[n-1].quantite*=adv[n-2].quantite;
          adv[n-2]=adv[--n];
      }
      if (eg(adv[n-1].type,"MANIÈRE")){
        if (adv[n-1].quantite>1){
	  adv[n-1].compar=adv[n-2].compar;
          adv[n-1].quantite=adv[n-2].quantite;
        }
        else {
	  if (adv[n-2].compar!=0) adv[n-1].compar=1/adv[n-2].compar;
          if (adv[n-2].quantite!=0) adv[n-1].quantite=1/adv[n-2].quantite;
	  else adv[n-1].quantite=0;
        }
        adv[n-2]=adv[--n];
      }
      else if (eg(adv[n-1].type,"LIEU")){
	  if (adv[n-2].compar<0) adv[n-1].compar=1/adv[n-2].compar;
	  else adv[n-1].compar=adv[n-2].compar;
          adv[n-1].quantite=adv[n-2].quantite;
          adv[n-2]=adv[--n];
      }
    }
    CPV(recursif,P,"","recursif");
    if (eg(recursif,"oui")) P=P->GetEdge("R_ADV(2)");
  } while (eg(recursif,"oui"));
}

//**********************************************************************
//	GROUPE NOMINAL
//**********************************************************************
void Agent_virtuel::cree(t_gn & gn, Edge* R_SN3)
{
  char genre_n[6]=VIDE;  //genre du nom dans le lexique
  char nombre_n[6]=VIDE; //nombre du nom dans le lexique
  char type[15];
  CPV(type,R_SN3,"","type"); 
  majusc(type);
  if (eg(type,"GN")){
    int nb_nom=RENDNUM(R_SN3,"R_SN2 R_SN1 R_SN0","nb");
    if (nb_nom==2){
      CPV(gn.n.sens,R_SN3,"R_SN2 R_SN1 R_SN0 R_NOM(2)","n");
      CPV(gn.n.type,R_SN3,"R_SN2 R_SN1 R_SN0 R_NOM(1)","n");
      CPV(genre_n,R_SN3,"R_SN2 R_SN1 R_SN0 R_NOM(1)","genre");
      CPV(nombre_n,R_SN3,"R_SN2 R_SN1 R_SN0 R_NOM(1)","nombre");
    }
    else {
      CPV(gn.n.sens,R_SN3,"R_SN2 R_SN1 R_SN0 R_NOM","n");
      CPV(gn.n.type,R_SN3,"R_SN2 R_SN1 R_SN0 R_NOM","type");
      CPV(genre_n,R_SN3,"R_SN2 R_SN1 R_SN0 R_NOM","genre");
      CPV(nombre_n,R_SN3,"R_SN2 R_SN1 R_SN0 R_NOM","nombre");
    }
    int nb_adj=RENDNUM(R_SN3,"R_SN2 R_SN1","nb_adj");
    char adresse[20]="R_SN2 R_SN1 R_ADJ";
    for (int i=1;i<=nb_adj;i++){
      if (nb_adj!=1) sprintf(adresse,"R_SN2 R_SN1 R_ADJ(%i)",i);
      Je.cree(gn.adj,gn.nb_adj,R_SN3->GetEdge(adresse));
    }
    if (egv(R_SN3,"","avec_det","oui"))
      Je.cree(gn.det,R_SN3->GetEdge("R_SN2 R_DET"));
      if (existe(gn.det.genre)) CP(gn.n.genre,gn.det.genre);
      else CP(gn.n.genre,genre_n);
      if (existe(gn.det.nombre)) CP(gn.n.nombre,gn.det.nombre);
      else CP(gn.n.nombre,nombre_n);    
  }
  else if (eg(type,"ADJ")){
    Je.cree(gn.adj,gn.nb_adj,R_SN3->GetEdge("R_SN2 R_ADJ"));    
    Je.cree(gn.det,R_SN3->GetEdge("R_SN2 R_DET"));
//  Nom : sens=OBJET type=SANS_REFERENCE genre=masc nombre=sing
  }
  else if (eg(type,"PRODEM")){
    char adresse[20];sprintf(adresse,"R_SN2 %s",type);
    CPV(gn.n.sens,R_SN3,adresse,"MOT");
    CPV(gn.n.genre,R_SN3,adresse,"genre");
    CPV(gn.n.nombre,R_SN3,adresse,"nombre");
    CP(gn.n.type,type);
  }
  else if (eg(type,"PROPERSDIS")){
    Je.cree_propersdis(gn,R_SN3->GetEdge("R_SN2 PROPERSDIS"));
  }
  else if (eg(type,"SYNTAGME")){
    CPV(gn.n.sens,R_SN3,type,"MOT");
    CP(gn.n.type,type);
  }
  if (egv(R_SN3,"","avec_adv","oui"))
    Je.cree(gn.adv,gn.nb_adv,R_SN3->GetEdge("R_ADV"));
}

void Agent_virtuel::cree_gn_intermediaire(t_tab_gn& tab,Edge* R_SN5)
{
  t_gn gn=tab.gn_courant();
  char type[40];
  CPV(type,R_SN5,"","type");
  CP(gn.texte,texte(R_SN5->GetEdge("R_SN4")));
  if (egv(R_SN5,"","avec_prep","oui"))
    Je.cree(gn.prep,R_SN5->GetEdge("R_SN4 R_PREP"));
  if (eg(type,"prep,r_adj")){
    Je.cree(gn.adj,gn.nb_adj,R_SN5->GetEdge("R_SN4 R_ADJ"));
    CP(gn.n.sens,gn.adj[0].type);
    tab.ajouter(gn);   
  }
  else {
    Je.cree(gn,R_SN5->GetEdge("R_SN4 R_SN3"));
    tab.ajouter(gn);
    if (eg(type,"gn,sub_rel")){
      if (egv(R_SN5,"R_SUB_REL","type","relative")){
        if (egv(R_SN5,"R_SUB_REL R_SUB","intro","QUI")){
          t_prop prop;
          char adresse[]="R_SUB_REL R_SUB R_SUB0 R_AFFIRM R_AFFIRM0";
          Je.cree_prop(prop,R_SN5->GetEdge(adresse),"relative","fo","R_V");
          tab.ajouter(prop.gn_comp);
        }
      } 
      else {
        t_tab_prop tmp;
        J.analyse_gprepv(R_SN5->GetEdge("R_SUB_REL R_GV"),tmp);
        tab.ajouter(tmp[0].gn_comp);
      }
    }
  }
}

/*void Agent_virtuel::cree(t_tab_gn& tab,Edge* R_SN)
{
  t_gn gn=tab.gn_courant(); 
  //t_gn* gn_texte=&(tab.gn_courant());
  char type[40];CPV(type,R_SN,"","type");
  if (egv(R_SN,"","recursif","oui")){
    t_tab_gn tab0;
    Je.cree_gn_intermediaire(tab0,R_SN->GetEdge("R_SN5"));
    CPV(gn.coord,R_SN,"","relation");
    CPV(tab0[0].coord,R_SN,"","relation");
    J.ajoutePdansTsuivantR(tab0,tab,gn.coord);
    Je.cree(tab,R_SN->GetEdge("R_SN(2)"));
  }
  else if (eg(type,"texte")){
    CP(gn.texte,texte(R_SN->GetEdge("TEXTE")));
    tab.ajouter(gn);
  }
  else { // le cas : simple ou prodem ou propersdis
    Je.cree_gn_intermediaire(tab,R_SN->GetEdge("R_SN5"));    
  }
  Ma.mem_ling.dernier_gn=gn;
  CP(Ma.mem_ling.dernier_gn.fonction,"COD");
  if (eg(gn.n.genre,"fem"))
	Ma.mem_ling.gn_fem=Ma.mem_ling.dernier_gn;
  else  Ma.mem_ling.gn_masc=Ma.mem_ling.dernier_gn;
  //if (!eg(type,"texte")) CP((*gn_texte).texte,texte(R_SN));
}
*/


void Agent_virtuel::cree(t_tab_gn& tab,Edge* R_SN)
{
  t_gn gn=tab.gn_courant(); 
  //t_gn* gn_texte=&(tab.gn_courant());

  Edge* p=R_SN;
  char relation[30]=VIDE;
  t_tab_gn tab0;
  int continuer=FALSE;
  if (egv(p,"","type","texte")){
      CP(gn.texte,texte(p->GetEdge("TEXTE")));
      tab.ajouter(gn);
  }
  else 
    do { 
      Je.cree_gn_intermediaire(tab0,p->GetEdge("R_SN5"));
      if (!eg(relation,"NON")) CP(tab0[0].coord,relation);
      if (continuer=egv(p,"","recursif","oui")) {
        CPV(relation,p,"","relation");
        p=p->GetEdge("R_SN(2)");
      }  
      else CP(relation,VIDE);
      J.ajoutePdansTsuivantR(tab0,tab,relation);
      tab0.init();
    } while (continuer);
  Ma.mem_ling.dernier_gn=gn;
  CP(Ma.mem_ling.dernier_gn.fonction,"COD");
  if (eg(gn.n.genre,"fem"))
	Ma.mem_ling.gn_fem=Ma.mem_ling.dernier_gn;
  else  Ma.mem_ling.gn_masc=Ma.mem_ling.dernier_gn;
  //if (!eg(type,"texte")) CP((*gn_texte).texte,texte(R_SN));
}

//**********************************************************************
//	GROUPE SUJET
//**********************************************************************
void Agent_virtuel::cree_sujet(t_tab_gn& tab,Edge* R_)

{
  if (egv(R_,"","contenu","gn")) {
    Je.cree(tab,R_->GetEdge("R_GN R_SN"));
  }
  else if (egv(R_,"","contenu","properssujet")) {
    CPV(tab[tab.nbr].n.sens,R_,"PROPERSSUJET","MOT");
    CPV(tab[tab.nbr].n.genre,R_,"PROPERSSUJET","genre");
    CPV(tab[tab.nbr].n.nombre,R_,"PROPERSSUJET","nombre");
    CP(tab[tab.nbr++].n.type,"PROPERSSUJET");
  }
}

//**********************************************************************
//	GROUPE VERBAL + PRONOMS et ADVERBES ATTACHES AU GV
//**********************************************************************
void Agent_virtuel::consulte_dico_verbe(t_gv& gv,char* intrtrpron)
{
  info INFO;  NOEUD Cat;
  int res=(*dictionnaire).FindFirst(gv.v.vinf,Cat,INFO);
  if (res==FALSE) {
     cerr<<"Verbe infinitif inconnu :"<<gv.v.vinf<<"\n";
     return;
  }
  CP(gv.v.intr_tr_pron,intrtrpron);//  intr tr ou pron.
  if (!existe(Cat[gv.v.intr_tr_pron].Symbole())){
    if (existe(Cat["intr"].Symbole())) CP(gv.v.intr_tr_pron,"intr");
    else if (existe(Cat["tr"].Symbole())) CP(gv.v.intr_tr_pron,"tr");
    else if (existe(Cat["pron"].Symbole())) CP(gv.v.intr_tr_pron,"pron");
  }
  CP(gv.v.sens,Cat[gv.v.intr_tr_pron].Symbole());
  CP(gv.v.type,Cat["type"].Symbole());
  char val_sem[400]; char chaine_nom[CHAINE_NOM],chaine_val[CHAINE_VALEUR];
  char champ_sem[10];sprintf(champ_sem,"%s_sem",gv.v.intr_tr_pron);
  int i=0;// pour eviter les boucles infinies en cas de probleme
//debn(champ_sem);
  CP(val_sem,Cat[champ_sem].Symbole());
  enlever_char(val_sem,",|");
//debn(val_sem);
  if (existe(val_sem)){
    do {
      i++;
      if(lire_un_mot(val_sem,chaine_nom) &&
          lire_un_mot(val_sem,chaine_val))
        gv.v.champs.ajouter(chaine_nom,chaine_val);
      else break;
//debn(chaine_nom);
//debn(chaine_val);
    } while (i<=30); //pour eviter les boucles infinies en cas de probleme
  }
}

void Agent_virtuel::cree(t_gv& gv,Edge* R_V,char* intrtrpron,char*rv_type)
{
  char adresse[100],adresse_tmp[100];
  if (eg(rv_type,"R_VIMP")) CP(adresse,"R_VIMP0 ");
  else if (eg(rv_type,"R_V_P_I")) CP(adresse,"R_V_P_I1 ");
  else if (eg(rv_type,"R_V")) CP(adresse,"R_V1 ");
  if (egv(R_V,"","contenu","locverb")){
     char rv_type_loc[20];
     CPV(rv_type_loc,R_V,"R_LOCVERB R_VLOC","rv_type");majusc(rv_type_loc);
     CPV(intrtrpron,R_V,"R_LOCVERB R_VLOC","sensv");
     Je.cree(gv,R_V->GetEdge("R_LOCVERB R_VLOC"),intrtrpron,rv_type_loc); 
	// pour s'assurer de prendre le bon type de verbe cf R_VLOC
     CPV(gv.v.vinf,R_V,"","vinf");
     Je.consulte_dico_verbe(gv,intrtrpron);//une 2eme fois-> c'est la bonne
     return;
  }
  CPV(gv.v.vinf,R_V,"","vinf");
  Je.consulte_dico_verbe(gv,intrtrpron);
  CPV(gv.contenu,R_V,"","contenu");
  if (egv(R_V,"","contenu","r_adv,r_v")){
    Je.cree(gv.adv,gv.nb_adv,R_V->GetEdge("R_ADV"));
  }
  if (eg(gv.contenu,"v,r_adv")||eg(gv.contenu,"v,r_pronom,r_adv")){
    sprintf(adresse_tmp,"%sR_ADV",adresse);
    Je.cree(gv.adv,gv.nb_adv,R_V->GetEdge(adresse_tmp));
// ca ne prends pas le pronom dans ce cas alors qu'il peut exister
// par exemple : pour ensuite le contourner
// le mieux serai de recoder la grammaire en faisant deux traits distincts
// -> le trait avec_adv et le trait avec_pronom
  }
  if (eg(gv.contenu,"v,r_pronom")||eg(gv.contenu,"v,r_pronom,r_adv")){
    sprintf(adresse_tmp,"%sR_PRONOM",adresse);
    Je.cree_pronom_gv(gv, R_V->GetEdge(adresse_tmp));
  }
  if (egv(R_V,"","attribut","oui")){
    Je.cree(gv.adj,gv.nb_adj,R_V->GetEdge("R_ADJ_ATTRIBUT_SUJET R_ADJ"));
  }
/*  if (existe(gv.v.champs["adv_lieu"])&& !gv.existe_adv("LIEU")){
    gv.adv[gv.nb_adv].type="LIEU";
    gv.adv[gv.nb_adv++].sens=gv.v.champs["adv_lieu"];
    //gv.lieu_def=gv.adv[gv.nb_adv-1];
  }
*/mem_ling.dernier_gv=gv;
  return;
}

void Agent_virtuel::cree_pronom_gv(t_gv& gv,Edge* R_PRONOM)
{
  char * contenu= valeur(R_PRONOM,"","contenu");majusc(contenu);
  if (eg(contenu,"PROPERSCOD,PROPERSCOI")){
    CPV(gv.pro_cod.sens,R_PRONOM,"PROPERSCOD","MOT");
    CPV(gv.pro_cod.genre,R_PRONOM,"PROPERSCOD","genre");
    CPV(gv.pro_cod.nombre,R_PRONOM,"PROPERSCOD","nombre");
    CP(gv.pro_cod.type,"PROPERSCOD");
    CPV(gv.pro_coi.sens,R_PRONOM,"PROPERSCOI","MOT");
    CP(gv.pro_coi.type,"PROPERSCOI");
  }
  else if (eg(contenu,"PROPERSCOD")){
    CPV(gv.pro_cod.sens,R_PRONOM,"PROPERSCOD","MOT");
    CPV(gv.pro_cod.genre,R_PRONOM,"PROPERSCOD","genre");
    CPV(gv.pro_cod.nombre,R_PRONOM,"PROPERSCOD","nombre");
    CP(gv.pro_cod.type,"PROPERSCOD");
  }
  else if (eg(contenu,"PROPERSCOI")){
    CPV(gv.pro_coi.sens,R_PRONOM,"PROPERSCOI","MOT");
    CP(gv.pro_coi.type,"PROPERSCOI");
  }
/*  else{
    CPV(gv.pro.sens,R_PRONOM,contenu,"MOT");
    CP(gv.pro.type,contenu);
  }
*/
}

//**********************************************************************
//	PROPOSITION SIMPLE SANS SUJET
//**********************************************************************
void Agent_virtuel::cree_prop(t_prop& prop,Edge* PO,char* type_ph,
				char* fonction_ph,char *rv_type)
{
  CP(prop.type,type_ph);
  CP(prop.fonction,fonction_ph);
  CPV(prop.contenu,PO,"","contenu");
  Je.cree(prop.gv,PO->GetEdge(rv_type),valeur(PO,"","sensv"),rv_type);
  J.analyse_gn(PO,prop);
  if (prop.gv.pro_cod.exister()){
    t_gn gn_tmp(prop.gv.pro_cod,"COD");
    prop.gn_comp.inserer(gn_tmp);
  }

}

void Agent_virtuel::analyse_gn(Edge*  R_GN_,t_prop& prop)
{
  if (egv(R_GN_,"","contenu","r_gnprep")){
    Je.cree(prop.gn_comp,R_GN_->GetEdge("R_GNPREP R_SN"));
    CP(prop.gn_comp[0].fonction,prop.gn_comp[0].prep.type);
  }
  else if (egv(R_GN_,"","contenu","r_gn")){
    Je.cree(prop.gn_comp,R_GN_->GetEdge("R_GN R_SN"));
    CP(prop.gn_comp[0].fonction,"COD");
  }
}

//**********************************************************************
//	GROUPE VERBAL AVEC OU SANS PREPOSITION
//**********************************************************************
void Agent_virtuel::analyse_gprepv(Edge* R_GV,t_tab_prop& props)
{
  char fonction_ph[30]="";
  t_prop prop;
  Edge* p=R_GV;
  char * contenu;
  t_prep prep0;
  if (!egv(p,"","prep","vide"))
    Je.cree(prep0,p->GetEdge("R_GV1 R_PREP")); 
  do { 
    if (!egv(p,"","prep","vide")){
      Je.cree(prop.prep_gv,p->GetEdge("R_GV1 R_PREP"));
      CP(fonction_ph,prop.prep_gv.avec_gv);
    }
    else if (prep0.exister()){
      prop.prep_gv=prep0;
      CP(fonction_ph,prep0.avec_gv);
    } else CP(fonction_ph,"gv_inf");
    Je.cree_prop(prop,p->GetEdge("R_GV1 R_GV_P_I"),
		   "prop_verb",fonction_ph,"R_V_P_I");
    contenu=valeur(p,"","contenu");
    if (eg(contenu,"recursif")) {
      CPV(prop.relation,p,"","relation");
      p=p->GetEdge("R_GV(2)");
    }
    J.ajoutePdansTsuivantR(prop,props,prop.relation);
    prop.init();
 
  } while (eg(contenu,"recursif"));
  //delete p; 
}

//**********************************************************************
//	ORDRE
//**********************************************************************
void Agent_virtuel::analyse_ordre(Edge* R_ORDRE,t_tab_prop& props)
{
  char fonction_ph[30]="prop_principale";
  t_prop prop;
  char * contenu;
  //cout<<p->parse();  
  Je.cree_prop(prop,R_ORDRE->GetEdge("R_ORDRE0"),
		"ordre",fonction_ph,"R_VIMP");
  contenu=valeur(R_ORDRE,"","contenu"); 
/*  t_tab_prop tmp;
  if (eg(tmp[0].fonction,"gérondif")){
    props.ajouter(tmp);
    props.ajouter(prop);
  }
  else {
    props.ajouter(prop);
    props.ajouter(tmp);
  } 
*/
  props.ajouter(prop);
}

//**********************************************************************
//	AFFIRMATION
//**********************************************************************
void Agent_virtuel::analyse_affirmation(Edge* R_AFFIRM,t_tab_prop& props)
{
  char fonction_ph[30]="";
  t_prop prop;
  if (!egv(R_AFFIRM,"","type_sujet","vide"))
    Je.cree_sujet(prop.gn_sujet,R_AFFIRM->GetEdge("R_GN_AVANT_R_V"));
  Je.cree_prop(prop,R_AFFIRM->GetEdge("R_AFFIRM0"),
		   "affirmation",fonction_ph,"R_V");
  props.ajouter(prop);	  
}

//**********************************************************************
//	QUESTION
//**********************************************************************
void Agent_virtuel::analyse_interrogation_deb(t_prop& p,Edge* R)
{
  if (egv(R,"","contenu","gn")||egv(R,"","contenu","gn,mot_interro"))
    ;//Je.cree(p.gn_autres,R->GetEdge("R_GN"));
  else if (!egv(R,"","type","gn")){
 CPV(p.interro.sens,R->GetEdge("R_INTERRO_DEB1 R_INTERRO_DEB0"),"","sens");
 CPV(p.interro.type,R->GetEdge("R_INTERRO_DEB1 R_INTERRO_DEB0"),"","type");
  }
  CP(p.type,"interrogation");

}

void Agent_virtuel::analyse_interrogation(Edge* R_INTERRO,t_tab_prop& props)
{
  t_tab_prop tmp;
  if (egv(R_INTERRO,"","contenu","r_affirm")){

    J.analyse_affirmation(R_INTERRO->GetEdge("R_AFFIRM"),tmp);
    J.analyse_interrogation_deb(tmp[0],
			      R_INTERRO->GetEdge("R_INTERRO_DEB"));  }
  else if (egv(R_INTERRO,"","contenu","gn")){
    tmp.nbr++;
    J.analyse_interrogation_deb(tmp[0],
			      R_INTERRO->GetEdge("R_INTERRO_DEB"));
    Je.cree(tmp[0].gv,R_INTERRO->GetEdge("R_V"),
	    valeur(R_INTERRO,"R_V","sensv"),"R_V");
    Je.cree_sujet(tmp[0].gn_sujet,R_INTERRO);
  }
/*  else if (egv(R_INTERRO,"","contenu","interro_propers")){
      if (egv(R_INTERRO,"","avec_suite","r_sn")){
       J.analyse_gn(R_INTERRO->GetEdge("R_INTERRO_SUITE R_XQWER"),tmp[0]);
      }
      else if (egv(R_INTERRO,"","avec_suite","r_adv"))
        Je.cree(tmp[0].gv.adv,tmp[0].gv.nb_adv,
	        R_INTERRO->GetEdge("R_INTERRO_SUITE R_ADV"));
  }
*/
  props.ajouter(tmp);
}

//**********************************************************************
//	PROPOSITION SUBORDONNÉE
//**********************************************************************
void Agent_virtuel::analyse_subordonnee(Edge* R_SUB,t_tab_prop& props)
{
  Edge* p=R_SUB;
  char type[20];
  t_tab_prop tmp;
  do { 
    CPV(type,p,"","type"); 
    J.analyse_affirmation(p->GetEdge("R_SUB0 R_AFFIRM"),tmp);
    CPV(tmp[0].conjsub,p,"","intro");
    if (egv(p,"R_SUB0","contenu","avec_r_gv"))
      J.analyse_gprepv(p->GetEdge("R_SUB0 R_GV"),tmp);
    if (eg(type,"recursif")) {
      CPV(tmp[0].relation,p,"","relation");
      p=p->GetEdge("R_SUB(2)");
    }
    J.ajoutePdansTsuivantR(tmp,props,tmp[0].relation);
    tmp.init();    
  } while (eg(type,"recursif"));
}

//**********************************************************************
//	PROPOSITION = ORDRE , QUESTION , AFFIRMATION, SUBORDONNEE
//**********************************************************************
void Agent_virtuel::analyse_prop(Edge* R_PROP,t_tab_prop& props)
{
  Edge* p=R_PROP;
  char type[20],relation[30]=VIDE;
  t_tab_prop ph_tmp;
  int continuer=FALSE;
  do { 
    CPV(type,p,"R_PROP1","type"); 
    if (eg(type,"ordre")){
      J.analyse_ordre(p->GetEdge("R_PROP1 R_PROP0 R_ORDRE"),ph_tmp);
    }
    else if (eg(type,"affirmation")){
      J.analyse_affirmation(p->GetEdge("R_PROP1 R_PROP0 R_AFFIRM"),ph_tmp);
    }
    else if (eg(type,"interrogation")){
      J.analyse_interrogation(p->GetEdge("R_PROP1 R_PROP0 R_INTERRO")
			     ,ph_tmp);
    }
    else if (eg(type,"sub_conj_inf")){
      J.analyse_gprepv(p->GetEdge("R_PROP1 R_PROP0 R_SUB_CONJ_INF R_GV"),ph_tmp);
    }
    else if (eg(type,"sub_conj")) {
      J.analyse_subordonnee(p->GetEdge("R_PROP1 R_PROP0 R_SUB_CONJ R_SUB")
			,ph_tmp);
    }
    CP(ph_tmp[0].type,type);
    if (!eg(relation,"NON")) CP(ph_tmp[0].relation,relation);
    if (continuer=egv(p,"","recursif","oui")) {
      Je.cree_relation(relation,p);
      p=p->GetEdge("R_PROP(2)");
    }  
    else CP(relation,VIDE);
    CP(ph_tmp[0].categorie,"proposition");
    if (eg(ph_tmp[0].fonction,"gérondif")){
      CP(ph_tmp[0].type,ph_tmp[0].fonction); //assez moche:type, fonction..
      props.inserer_T_avant_i(ph_tmp,props.nbr-1);
    }
    else J.ajoutePdansTsuivantR(ph_tmp,props,relation);
    ph_tmp.init();
  } while (continuer);
  //delete p;
}

void Agent_virtuel::cree_relation(char* relation,Edge* R_)
{
  if (!egv(R_,"","relation_nature","propagée")
      || !egv(R_,"","relation_propageable","non"))
    CPV(relation,R_,"","relation");
  else {deb("\n\nnon propageable : ");debn(valeur(R_,"","relation"));}
}

int Agent_virtuel::ajoutePdansTsuivantR(t_tab_gn &P,t_tab_gn &T,char* R)
{
  if (!eg(R,"NON")){
    T.ajouter(P);	
    return TRUE;	
  }
  else return FALSE;
}
int Agent_virtuel::ajoutePdansTsuivantR(t_prop &P,t_tab_prop &T,
					char* R)
{
  if (!eg(R,"NON")){
    T.ajouter(P);	
    return TRUE;	
  }
  else return FALSE;
}
int Agent_virtuel::ajoutePdansTsuivantR(t_tab_prop &P,t_tab_prop &T, 
					char* R)
{
  if (!eg(R,"NON")){
    T.ajouter(P);
    return TRUE;	
  }
  else return FALSE;
}

//**********************************************************************
//	INTERJECTION + SALUTATION
//**********************************************************************
void Agent_virtuel::analyse_interjection(Edge* INTERJ,t_tab_prop& props)
{
  if (egv(INTERJ,"","type","ACTION")){
    t_prop prop;
    CP(prop.categorie,"interjection");
    CP(prop.type,"ordre");
    CP(prop.fonction,"prop_principale");
    CP(prop.contenu,"interj");
    CPV(prop.gv.v.sens,INTERJ,"","sens");
    props.ajouter(prop);	  
  }
  if (egv(INTERJ,"","MOT","HEIN")){
    Je.cree_dire("la moitié de deux.",props);
  }
  if (egv(INTERJ,"","MOT","HA_QUE_COUCOU")){
    Je.cree_dire("coucou.",props);
  }
  if (egv(INTERJ,"","MOT","COUCOU")){
    Je.cree_dire("ha que coucou.",props);
  }
}

void Agent_virtuel::analyse_salutation(Edge* R_SALUT,t_tab_prop& props)
{
  char tab[100];
  sprintf(tab,"%s %s.",valeur(R_SALUT,"","sens"),Mon.prenom_user);
  Je.cree_dire(tab,props);
}

//**********************************************************************
//	LA REPLIQUE EST UN ADVERBE 
//**********************************************************************
void Agent_virtuel::analyse_adverbe(Edge* R_ADV,t_tab_prop& props)
{
  t_prop p;
  Je.cree(p.gv.adv,p.gv.nb_adv,R_ADV);
  CP(p.categorie,"adverbe");
  props.ajouter(p);
//cout<<"analyse_adverbe:"<<props.nbr<<"\n";
}


//**********************************************************************
//	LA REPLIQUE EST UNE SEQUENCE NOMINALE 
//**********************************************************************
void Agent_virtuel::analyse_replique_sn(Edge*  R_SN,t_tab_prop& props)
{
  t_prop p;
  Je.cree(p.gn_comp,R_SN);
  CP(p.categorie,"groupe_nominal");
  if (existe(p.gn_comp[0].prep.type))
    CP(p.gn_comp[0].fonction,p.gn_comp[0].prep.type);
  else CP(p.gn_comp[0].fonction,"COD");
  props.ajouter(p);
}


//**********************************************************************
//	ANALYSE DE L'INTRODUCTION D'UN ENONCE
//**********************************************************************
void Agent_virtuel::analyse_intro(Edge* R_INTRO,t_tab_prop& props)
{  
  char type[30];
  CPV(type,R_INTRO,"R_INTRO0","type");
  if (eg(type,"adverbe")){
    J.analyse_adverbe(R_INTRO->GetEdge("R_INTRO0 R_ADV"),props);
  }
  else if (eg(type,"interjection")){
    J.analyse_interjection(R_INTRO->GetEdge("R_INTRO0 INTERJ"),props);
  }
  else if (eg(type,"salutation")){
   J.analyse_salutation(R_INTRO->GetEdge("R_INTRO0 R_SALUTATION"),props);
  }
  if (egv(R_INTRO,"","recursif","oui")){
    J.analyse_intro(R_INTRO->GetEdge("R_INTRO(2)"),props);
  }
//cout<<"analyse_intro:"<<props.nbr<<"\n";
}

//**********************************************************************
//	ANALYSE SEMANTIQUE PRINCIPALE
//**********************************************************************
void Agent_virtuel::analyse_semantiquement(Edge*  PH,t_tab_prop &rep)
{  
  char type[30];
  rep.init();		// initialisation de rep en cas d'ambiguite
  CPV(type,PH,"S","type");
  if (egv(PH,"S","intro","oui")){
    J.analyse_intro(PH->GetEdge("S R_INTRO"),rep);
  }
  if (eg(type,"proposition")){
    J.analyse_prop(PH->GetEdge("S R_PROP"),rep);
  }
  else if (eg(type,"groupe_nominal")){
    J.analyse_replique_sn(PH->GetEdge("S R_SN"),rep);
  }
}

void Agent_virtuel::analyse_semantiquement(char * enonce,t_tab_prop &rep)
{  //le resultat est ajoute dans  Mon.tab_prop = effet de bord
  Chart *pChart=new Chart();
  assert(pChart!=NULL);
  Edge* PO2;
  Je.me_dis(enonce);
  cout<<"\n    => ";
  J.analyse_syntaxiquement(pChart,PO2);
  J.analyse_semantiquement(PO2,rep);
  delete pChart;
}

//**********************************************************************
//	ANALYSE SEMANTIQUE DE DEFINITION EN LANGAGE NATURELLE
//**********************************************************************
void Agent_virtuel::analyse_semantiquement(t_tab_prop &rep)
{
  int definition_en_LN=TRUE;
  t_tab_prop props;
  t_prep prep_syntag;
//  char syntag_sens[50];
  for (int nb_ref_croise=1;nb_ref_croise<=10 && definition_en_LN;
       nb_ref_croise++){ 
    definition_en_LN=FALSE;
    for (int i=0;i<rep.nbr;i++){
      if (rep[i].gv.compose()){
        definition_en_LN=TRUE;
        t_prop p=rep[i];
        enlever_char(p.gv.v.sens,'-');
        traiter_au_hasard(p.gv.v.sens);
	cout<<"Définition sémantique lexicale de "<<p.gv.v.vinf<<" :";
        traiter_enonce_pour_analyse_syntaxique(p.gv.v.sens);
        if (!exister_deja_verbe_comp(p.gv.v.sens,props)){
          J.analyse_semantiquement(p.gv.v.sens,props);
          J.ajoute_dans_mem_ling_commune(p.gv.v.sens,props);
        } 
        else cout<<" En mémoire.\n";
        for (int j=0;j<props.nbr;j++){
          for (int k=0;k<props[j].gn_comp.nbr;k++){
            if (eg(props[j].gn_comp[k].n.type,"SYNTAGME")){
//cout<<"WWWWWWWWWWWWWWWWWWWWWWW un syntagme trouve :"<<props[j].gn_comp;
	      prep_syntag=props[j].gn_comp[k].prep;
              if (eg(props[j].gn_comp[k].n.sens,"$COD"))
	        p.gn_comp[0].prep=prep_syntag;
	      if (prep_syntag.exister()){
     		CP(p.gn_comp[0].fonction,prep_syntag.type);
	        //sprintf(syntag_sens,"%s %s",
		//	prep_syntag.sens,p.gn_comp[0].texte);
		//CP(p.gn_comp[0].texte,syntag_sens);
	      }
             props[j].gn_comp=p.gn_comp;
            }
          }
          props[j].gn_sujet=p.gn_sujet;
          props[j].conjsub=p.conjsub;
          props[j].interro=p.interro;
          props[j].relation=p.relation;
          props[j].type=p.type;
	  if (!props[j].prep_gv.exister()) props[j].prep_gv=p.prep_gv;
	  if (!props[j].interro.exister()) props[j].interro=p.interro;
        }
//cout<<"props"<<props;
//cout<<"avant="<<rep.nbr<<'\n';
        rep.remplacer_Ti_par_P(i,props);
//cout<<"apres="<<rep.nbr<<'\n';
        props.init();
      }
    }
  }
}

//**********************************************************************
//	ANALYSE PRAGMATIQUE
//**********************************************************************
void Agent_virtuel::pragma_propers(t_gn& gn)
{
  if (!eg(gn.n.type,"PROPERSDIS")&&!eg(gn.n.type,"PROPERSSUJET")) return;
  if (eg(gn.n.sens,"TOI")){
    CP(gn.n.sens,Mon.nom);
    CP(gn.n.type,"AGENT");
    CP(gn.n.nombre,"sing");
  }
  else if (eg(gn.n.sens,"MOI")){
    CP(gn.n.sens,Mon.nom_agent_user); // a verifier car renvoie BOB
    CP(gn.n.type,"UTILISATEUR");
    CP(gn.n.nombre,"sing");
  }
  else if (eg(gn.n.sens,"TU")){
    CP(gn.n.sens,Mon.user);
    CP(gn.n.type,"AGENT");
    CP(gn.n.nombre,"sing");
  }
  else if (eg(gn.n.sens,"JE")){
    CP(gn.n.sens,Mon.prenom_user);
    CP(gn.n.type,"UTILISATEUR");
    CP(gn.n.nombre,"sing");
  }
}

void Agent_virtuel::analyse_pragmatiquement_sn(t_tab_gn &gns)
{
    for (int j=0;j<gns.nbr;j++){
      pragma_propers(gns[j]);
    }
}

void Agent_virtuel::analyse_pragmatiquement(t_tab_prop &rep)
{
  for (int i=0;i<rep.nbr;i++){
      J.analyse_pragmatiquement_sn(rep[i].gn_sujet);
      J.analyse_pragmatiquement_sn(rep[i].gn_comp);
  }
}

//**********************************************************************
//	ANALYSE DU DIALOGUE
//**********************************************************************
void Agent_virtuel::analyse_le_dialogue_gn(t_tab_prop &rep)
{
  t_tab_prop rep_dial;
  if (eg(rep[0].gn_comp[0].n.type,"PRODEM"))
    rep_dial= Ma.mem_ling.tab_prop;
  else if (eg(rep[0].gn_comp[0].prep.type,"LIEU")){
    rep_dial= Ma.mem_ling.tab_prop;
    rep_dial[0].gn_comp=rep[0].gn_comp;
  }
  else {
    rep_dial= Ma.mem_ling.tab_prop;
    rep_dial[0].gn_comp=rep[0].gn_comp;
  }
  rep=rep_dial;
}

void Agent_virtuel::analyse_le_dialogue_adv(t_tab_prop &rep)
{
  t_tab_prop rep_dial;
  t_adv adv;
  for (int i=0;i<rep[0].gv.nb_adv;i++){
    adv=rep[0].gv.adv[i];
//cout<<i<<adv;
    if (eg(adv.sens,"ENCORE")){
      rep_dial= Ma.mem_ling.tab_prop;
    }
    else if (eg(adv.type,"DÉICTIQUE")){
      rep_dial= Ma.mem_ling.tab_prop;
    }
    else if (eg(adv.type,"MANIÈRE")){
      t_prop p("ordre","prop_principale","gv");
      p.gv=mem_ling.dernier_gv;
      p.gv.adv=rep[0].gv.adv;p.gv.nb_adv=rep[0].gv.nb_adv;
      rep_dial.init();
      rep_dial.ajouter(p);
    }
    else if (existe(adv.acte)){
      traiter_au_hasard(adv.acte);
      traiter_enonce_pour_analyse_syntaxique(adv.acte);
      if (!exister_deja_verbe_comp(adv.acte,rep_dial)){
        J.analyse_semantiquement(adv.acte,rep_dial);
	J.ajoute_dans_mem_ling_commune(adv.acte,rep_dial);
      }
      else mem_ling.dernier_gv=rep_dial.derniere().gv;
    }
  }
  rep=rep_dial; // si l'adverbe n'est pas compris rep_dial est vide
}

void Agent_virtuel::analyse_le_dialogue(t_tab_prop &rep)
{
  t_tab_prop rep_dial=rep;
  if (eg(rep[0].categorie,"groupe_nominal"))
  { J.analyse_le_dialogue_gn(rep_dial);
    rep.remplacer_Ti_par_P(0,rep_dial);
    //for (int i=1; i<rep.nbr;i++) rep_dial.ajouter(rep[i]);
  } 
  else if (eg(rep[0].categorie,"adverbe"))
  { J.analyse_le_dialogue_adv(rep_dial);
//cout<<"rep_dial"<<rep_dial;
    rep.remplacer_Ti_par_P(0,rep_dial);
  }
}

//**********************************************************************
//	SYNTHESE DE LA REPLIQUE DE L'AGENT
//**********************************************************************

int Agent_virtuel::synthetise_ma_replique(char* rep)
// l'agent prend la parole.
{
//debn(rep);debin(strlen(rep));
  if (eg(rep,"OK VIDE ."))
    CP(rep,"Z"); // l'agent ne dit rien si rien n'est envoye
  else if (eg(rep,"VOILÀ .")||eg(rep,"VOILÀ .\n")) 
    CP(rep,"{VOILÀ VOILÀ ET_VOILÀ  ÇA_Y_EST J_AI_FINI VOILÀ} .");
  else if (strstr(rep,"MESSAGE CONNEXION ITHAQUES"))
	sprintf(rep,
	  "{BONJOUR SALUT} %s BIENVENU {0 ICI DANS_LE_MONDE_ITHAQUES} ." 
	  ,Mon.prenom_user);
//else debn("NNNNNNNNNNNNN");
  traiter_au_hasard(rep);
  traiter_enonce_pour_analyse_syntaxique(rep);
  if (!eg(rep,"Z")&&!eg(rep,"")) Je.parle(rep);
  return TRUE;
}

int Agent_virtuel::synthetise_ma_reponse(char* rep,t_tab_prop &replik)
// l'agent repond a la replique de l'utilisateur ou la commente.
{
  if (J.ecoute_agent(rep)){
    traiter_enonce_pour_analyse_syntaxique(rep);
    cout<<"Bilan positif.\n      Commentaire : "<<rep;
    if (eg(rep,"OK VIDE ."))
	CP(rep,"Z"); // l'agent ne dit rien si rien n'est envoye
    else if (strstr(rep,"OK"))
	if(eg(replik[0].interro.type,"question-oui-non"))
	  CP(rep,"OUI .");
	else CP(rep,"{OK D_ACCORD OUI C_EST_PARTI BIEN} .");
    else if (eg(rep,"")) CP(rep,"BIEN .");
    traiter_au_hasard(rep);
    traiter_enonce_pour_analyse_syntaxique(rep);
    //Je.parle(rep);
    return TRUE;
  }
  else {
    cout<<"Bilan négatif.\n     Commentaire : "<<rep;
debn(rep);
    if (eg(rep,"PRÉPOSITION INCONNUE\n"))
	  CP(rep,"JE NE CONNAIS PAS CETTE PRÉPOSITION .");
    //Je.parle(rep);
    return FALSE;
  }
}

//**********************************************************************
//	TRAITEMENT DES ENONCES
//**********************************************************************
void Agent_virtuel::traite_enonce(Chart* pchart,char* replik,char* reponse)
{
  NOEUD Goal;Goal["CAT"]="PH";EdgeInfoRec rec;
  Edge* edge1=(Edge*)pchart->GetFirstParse(Goal,rec);
  char ponct_fin[2]; CPV(ponct_fin,edge1,"R_FIN FIN","MOT");
  int compteur=1,sortie=FALSE;
  int nb_analyse_syntaxique=Je.compte_analyse_syntaxique(pchart);
  t_tab_prop tab_prop_semantik;
  CP(reponse,"");	// par defaut la reponse de l'agent est vide
  do {
    if (nb_analyse_syntaxique>1) 
      cout<<"\n##### ANALYSE NUMÉRO "<<compteur++<<" ######\n";
    Je.traite_enonce(edge1,tab_prop_semantik);
    //cout<<"traite_enonce:"<<tab_prop_semantik.nbr<<"\n";
    //cout<<tab_prop_semantik.nbr;
    if (!J.analyse_actes()) Je.transmet_tab_prop();
    sortie=Je.synthetise_ma_reponse(reponse,Mon.tab_prop);
//cout<<"\nsortie="<<sortie<<"\n";
    if (sortie==0){
      t_tab_prop tab_action_stop; // Arret du gestionnaire d'action qui
  			      //pourrait fonctionner pour certaines actions
      tab_action_stop.nbr=1;
      CP(tab_action_stop[0].gv.v.sens,"STOPPER_ACTION");
      tab_action_stop.transmettre(nom_dive);
    }
  } while (!sortie && (edge1=(Edge*)pchart->GetNextParse(rec))!=NULL);
  Je.parle(reponse);
  if (eg(ponct_fin,"*")){
    edge1=(Edge*)pchart->GetFirstParse(Goal,rec); 
    int nb_analyse=0;
    do {
      nb_analyse++;
      Je.traite_enonce(edge1,tab_prop_semantik);
      cout<<'\n'<<nb_analyse<<":\n";J.affiche_props(Mon.tab_prop);
    } while ((edge1=(Edge*)pchart->GetNextParse(rec))!=NULL);
  }
  else J.affiche_props(Mon.tab_prop);
  Je.gere_l_historique_du_dialogue(Mon.tab_prop);
  if (nb_analyse_syntaxique==1)
    J.ajoute_dans_mem_ling_commune(replik,tab_prop_semantik);

//  if (!eg(reponse,"Z")&&!eg(reponse,"")) 
//    Je.dit(reponse);
}

int Agent_virtuel::traite_enonce(char* replique,char *reponse)
{
  int sortie=FALSE;
  Mon.tab_prop.init();
  if (!exister_deja_verbe_comp(replique,Mon.tab_prop))
    return FALSE;
  cout<<replique<<'\n';
  if (Mon.tab_prop.derniere().gv.exister())
    Ma.mem_ling.dernier_gv=Mon.tab_prop.derniere().gv;
  cout<<"\nEn mémoire :\n";J.affiche_props(Mon.tab_prop);
  J.analyse_pragmatiquement(Mon.tab_prop);
  J.analyse_le_dialogue(Mon.tab_prop);
  if (!J.analyse_actes()) Je.transmet_tab_prop();
  sortie=Je.synthetise_ma_reponse(reponse,Mon.tab_prop);
  if (sortie==0){
      t_tab_prop tab_action_stop; // Arret du gestionnaire d'action qui
  			      //pourrait fonctionner pour certaines actions
      tab_action_stop.nbr=1;
      CP(tab_action_stop[0].gv.v.sens,"STOPPER_ACTION");
      tab_action_stop.transmettre(nom_dive);
  }
  Je.parle(reponse);
//  cout<<"\nEn mémoire :\n";J.affiche_props(Mon.tab_prop);
  Je.gere_l_historique_du_dialogue(Mon.tab_prop);
  return TRUE;
}

void Agent_virtuel::traite_enonce(Edge* PO, t_tab_prop &tab_prop_semantik)
{
  Mon.tab_prop.init();
  J.analyse_semantiquement(PO,tab_prop_semantik);
  J.analyse_semantiquement(tab_prop_semantik);
  Mon.tab_prop=tab_prop_semantik;
//cout<<"traite_enonce1:"<<Mon.tab_prop.nbr<<"\n";
  J.analyse_pragmatiquement(Mon.tab_prop);
//cout<<"traite_enonce2:"<<Mon.tab_prop.nbr<<"\n";
  J.analyse_le_dialogue(Mon.tab_prop);
//cout<<"traite_enonce3:"<<Mon.tab_prop.nbr<<"\n";
}

int Agent_virtuel::compte_analyse_syntaxique(Chart * pchart)
{
  NOEUD Goal; Goal["CAT"]="PH"; EdgeInfoRec rec;
  Edge* edge1=(Edge*)pchart->GetFirstParse(Goal,rec);
  int nb_analyse=0;
  do {
    nb_analyse++;
  } while ((edge1=(Edge*)pchart->GetNextParse(rec))!=NULL);
  return nb_analyse;
}

void Agent_virtuel::gere_l_historique_du_dialogue(t_tab_prop &tab)
{
  if (tab.nbr==1 && eg(tab[0].gv.v.sens,"STOPPER_ACTION")) return;
  Ma.mem_ling.tab_prop=tab;
}

/* Pour matthias
int Agent_virtuel::traite_enonce(Chart* pchart,char* replik,t_tab_prop &t, int nb_analyse)
{
  NOEUD Goal;Goal["CAT"]="PH";EdgeInfoRec rec;
  Edge* edge1=(Edge*)pchart->GetFirstParse(Goal,rec);
  t_tab_prop tab_prop_semantik;
  for(int i=1;i<nb_analyse;i++){
    cout<<'\n'<<i<<":\n";
    edge1=(Edge*)pchart->GetNextParse(rec);
  }
  if (edge1==NULL) return FALSE;
  Je.traite_enonce(edge1,tab_prop_semantik);
  Ma.mem_ling.tab_prop=Mon.tab_prop;
  if (Je.compte_analyse_syntaxique(pchart)==1)
    J.ajoute_dans_mem_ling_commune(replik,tab_prop_semantik);
  t=Mon.tab_prop;
  return TRUE;
}
*/

//**********************************************************************
//	ANALYSE DES ACTES EXECUTABLES PAR L'AGENT VIRTUEL D'ICI
//**********************************************************************
int Agent_virtuel::analyse_actes()
{
  int exec=0;
  for (int i=0;i<tab_prop.nbr;i++){
    if (eg(tab_prop[i].gv.v.sens,"RÉPÉTER")){
      exec=TRUE;
      char tmp[TAILLE_REPLIQUE];
      sprintf(tmp,"%s.",mem_ling.derniere_replique_orale);
      Je.dit(tmp);
    }
    else if (eg(tab_prop[i].gv.v.sens,"CREER")&&
	eg(tab_prop[i].gn_comp[0].n.sens,"AGENT")) 
	  Mon.nouveau_agent=TRUE;
  }
  return exec;
}

t_prop Agent_virtuel::cree_dire(char * texte)
{
  t_prop p;
  CP(p.gv.v.vinf,"DIRE");
  CP(p.gv.v.sens,"DIRE");
  CP(p.gv.contenu,"v");
  CP(p.categorie,"affirmation");
  CP(p.type,"proposition");
  t_gn gn; CP(gn.texte,texte); CP(gn.fonction,"COD");
  p.gn_comp.ajouter(gn);
  return p;
}

void Agent_virtuel::cree_dire(char * texte,t_tab_prop &phs)
{
  t_prop p=Je.cree_dire(texte);
  phs.ajouter(p);
}

//**********************************************************************
//	ENTREES
//**********************************************************************
char * Agent_virtuel::ecoute(char* entree)
{ 
   static char ligne[LONGUEUR_TEXTE_MAX]="";
    static char *pligne=ligne;
    if (strcmp(ligne,"")==0){
      FILE *f=NULL; 
      while ((f=fopen(nom_entree_carte_vocale,"r")) == NULL ){
        usleep(20000); 
      }
      if (J.ecoute_agent_suite(ligne,f)!=2){ //=2 => cf. Je.me_dis
        Je.parle(ligne);//DEB1 debn(ligne);DEB2
        //CP(ligne,"OK ."); // car probleme dans la lecture : bizarrerie
      }
      fclose(f);
      unlink(nom_entree_carte_vocale);
    }
    if (sscanf(pligne,"%s",entree)==-1 || strcmp(pligne,entree)==0) 
       {CP(ligne,"");pligne=ligne;}
    else{
      pligne=strstr(pligne,entree);
      for(int i=0;*(pligne++) == entree[i];i++);
      char tt[50];
      if (sscanf(pligne,"%s",tt)==-1) 
         {pligne=ligne;CP(ligne,"");}
    }
  Mon.buffer=strlen(ligne);
  return entree;
}

int Agent_virtuel::ecoute_agent(char* ligne)
{ 
  float temps=0; float tt=.9; // ou tt=.7 quand le vrai usleep fonctionne
  int bilan=1;
  FILE *f=NULL; 
  while ((f=fopen(nom_entree_carte_vocale,"r")) == NULL && temps<tt){
    usleep(100000); 
    temps+=.1;
  }
  if (temps>=tt) { // on suppose que ca a reussi
    cout<<"##### Pas de réponse de l\'agent virtuel :";
    CP(ligne,"Z");
  }
  else {
    cout<<"##### Réponse de l\'agent virtuel en "<<temps<<" seconde : "; 
    bilan=J.ecoute_agent_suite(ligne,f);
  }
  fclose(f);
  unlink(nom_entree_carte_vocale);
  return bilan;
}

int Agent_virtuel::ecoute_agent_suite(char* ligne,FILE* f)
{ 
//deb("debut ecoute_agent_suite ");
  int bilan=0,i=0;
  while (fgets(ligne,LONGUEUR_TEXTE_MAX,f)!=NULL
          && i++<NB_MAX_PROPOSITION+5){ //pour eviter les boucles infinies
    if (ligne[0]=='1' || ligne[0]=='0'|| ligne[0]=='2') {
      bilan=atoi(&ligne[0]);
      fgets(ligne,LONGUEUR_TEXTE_MAX,f);
      majusc(ligne);
      if (bilan==0) return bilan;
    }
/*debn("");
debn("-------");
deb("bilan=");debin(bilan);
deb(  "ecoute : ");
debn(ligne);
debn("-------");
*/
  }
  return bilan;
}

char* Agent_virtuel::parle()
{
  static char ligne[LONGUEUR_TEXTE_MAX]="";
  usleep(20000); 
  FILE *f=NULL; 
  if ((f=fopen(nom_entree_carte_vocale,"r")) == NULL  && Mon.buffer==0){
    fclose(f);
    CP(ligne,"");
  }
  else {
    fclose(f);
    lire_message(ligne,nom_entree_carte_vocale,2);
  }
//deb("agent:");debn(ligne);
  return ligne;
}


//**********************************************************************
//	SORTIES
//**********************************************************************
void Agent_virtuel::me_dis(char* enonce)
// en precedant la ligne par 2, ecoute_agent_suite et ecoute_agent le verra
{
  char tmp[500];
  sprintf(tmp,"2\n%s .",enonce);
//deb("\nJe me dis : ");debn(tmp);
  ecrire_message(tmp,nom_entree_carte_vocale);
}

void Agent_virtuel::dit(char* enonce)
{
  char tmp[500];
  sprintf(tmp,"1\n%s",enonce);
/*debn("");
debn("-------");
deb(  "dit : ");
debn(tmp);
debn("-------");
*/
  ecrire_message(tmp,nom_entree_carte_vocale);
}

void Agent_virtuel::parle(char* mes)
{
  char mes2[1000]="", commande[1000], machine[20];
  CP(machine,getenv("DISPLAY"));copy_jusque(machine,':');
  CP(commande,mes);majusc(commande);
  traiter_au_hasard(commande);
  enlever_char(commande,"\',-_.");
  Mon.sons->transfert(commande,mes2);
  sprintf(Ma.mem_ling.derniere_replique_orale,"%s",mes2);
  sprintf(commande,"rsh %s \'(cd %s ;play %s)\'>/dev/null&",machine,Mon.sons->chemin,mes2);
  system(commande);
  cout.flush();
}

