
import java.awt.*;
import java.util.*;

// definition d'une Carte : Nom et Image associee
class Carte {
/////////////////////////////////////////////////

  String nom;
  Image image;

  // constructeur
  public Carte( String n, Image i ) {
    nom = n;  image = i;
  }

  public String GetNom( )   { return nom; }
  public Image  GetImage( ) { return image; }

  public void Show(  ) {
    System.out.println(" Show image " + nom );
  }

  public Carte Clone( ) {
    return new Carte( nom, image );
  }

  public void Debug( ) {  Show();  }

}




// contient les 19 cartes types du jeux des mille bornes
class Unicite {
////////////////////////////////////////////////////////

  int    taille = 19;
  int[]  nombre = new int[ taille ];
  Carte  cartes[] = new Carte[ taille ];

  // constructeur : cree les 19 cartes types
  public Unicite(  ) {
    System.err.println("[Unicite::Unicite]");
    String Path = "/u/dessi3/esmel/SAR6/MilleBorne/Images/";
    // kilometres
    // cartes[i] = new Carte( "25", Toolkit.getDefaultToolkit().getImage(Path+"25"+"gif" ) );
    cartes[ 0] = new Carte(  "25", null );  nombre[0] = 10;
    cartes[ 1] = new Carte(  "50", null );  nombre[1] = 10 ;
    cartes[ 2] = new Carte(  "75", null );  nombre[2] = 10 ;
    cartes[ 3] = new Carte( "100", null ); nombre[3] = 12 ;
    cartes[ 4] = new Carte( "200", null ); nombre[4] =  4 ;
    // atouts
    cartes[ 5] = new Carte( "driv_ace", null ); nombre[5] = 1 ;
    cartes[ 6] = new Carte( "punc_prf", null ); nombre[6] = 1 ;
    cartes[ 7] = new Carte( "rightway", null ); nombre[7] = 1 ;
    cartes[ 8] = new Carte( "xtratank", null ); nombre[8] = 1 ;
    // start et stop
    cartes[ 9] = new Carte( "roll", null );  nombre[9] = 14 ;
    cartes[10] = new Carte( "stop", null ); nombre[10] = 5 ;
    // accidents
    cartes[11] = new Carte( "accident", null ); nombre[11] = 3 ;
    cartes[12] = new Carte(  "repair",  null );   nombre[12] = 6 ;
    // pneu creve
    cartes[13] = new Carte( "flattire", null ); nombre[13] = 3 ;
    cartes[14] = new Carte( "spartire", null ); nombre[14] = 6 ;
    // fuel
    cartes[15] = new Carte( "outofgaz", null ); nombre[15] = 3 ;
    cartes[16] = new Carte( "gasoline", null ); nombre[16] = 6 ;
    // limitation de vitesse
    cartes[17] = new Carte( "spdlimit", null ); nombre[17] = 4 ;
    cartes[18] = new Carte( "endlimit", null ); nombre[18] = 6 ;
  }
  

/*
  public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height){
    int cpt = 0;
    if ((infoflags & java.awt.image.ImageObserver.ALLBITS) != 0) {
      System.out.println( '[' + cpt++ + ']' ) ;
      if ( cpt == 19 )
	return false;
    }
    return true;
  }
*/

  public int   GetUniq ( )       { return taille;    }
  public int   GetNbre ( int i ) { return nombre[i]; }
  public Carte GetCarte( int i ) { return cartes[i]; }

}




// contient les 106 cartes du jeux des milles bornes
class Jeux {
////////////////////////////////////////////////////

  Unicite unicite;  /* les 19 cartes du jeux */
  static int taille = 106; /* 106 cartes ds le jeux */
  Carte jeux[] ; /* tableau des cartes    */

  // Association Handicap / Solution
  String Handicap[] = { "flattire" , "outofgaz", "spdlimit", "accident", null };
  String Solution[] = { "spartire" , "gasoline", "endlimit", "repair"  , null };

  // Association Atout / Handicap
  String Atout[]   = { "punc_prf"  , "xtratank", "rightway", "driv_ace", null };

  // constructeur
  public Jeux( ) {
    System.err.println("[Jeux::Jeux]");
    unicite = new Unicite();
    jeux = new Carte[ taille ];
    // allocation du tableau des cartes
    int cpt = 0;
    for ( int i=0 ; i < unicite.GetUniq() ; i++ ) // chacune des 19 cartes
      for ( int j=0 ; j < unicite.GetNbre( i ) ; j++ )
	jeux[ cpt++ ] = (unicite.GetCarte( i )).Clone() ;
  }

  // accesseurs / modifiers
  public int GetTaille( ) { return taille; }

  // retourne la carte dont le nom est name
   public Carte GetCarte( String name ) {
    int i;
    for( i=0 ; i < unicite.GetUniq() ; i++ )
      if ( name.compareTo( (unicite.GetCarte(i)).GetNom() ) == 0 )
	break;
    return unicite.GetCarte(i);
  }

  // cree une pioche (Vector de String), a partir du jeu de cartes
  public Vector CreerPioche( ) {
    System.err.println("[Jeux::CreerPioche]");
    Vector pioche = new Vector( taille );
    for ( int i=0 ; i < taille ; i++ )
      pioche.addElement( jeux[ i ].GetNom() );
    return pioche;
  }


  // retourne la valeur, en points, d'une carte
  // remarque : seules les cartes 25, 50, 75, 100 et 200 ont une valeur
  public int GetValeurCarte( String nomCarte ) {
    if ( nomCarte.compareTo(  "25" ) == 0 )  return 25;
    if ( nomCarte.compareTo(  "50" ) == 0 )  return 50;
    if ( nomCarte.compareTo(  "75" ) == 0 )  return 75;
    if ( nomCarte.compareTo( "100" ) == 0 )  return 100;
    if ( nomCarte.compareTo( "200" ) == 0 )  return 200;
    return 0;
  }


  // teste si la carte est un Atout
  public boolean EstUnAtout( String nomCarte ) {
    for ( int i=0 ; Atout[i] != null ; i++ )
      if ( Atout[i].compareTo( nomCarte ) == 0 )
	return true;
    return false;
  }

  // teste si la carte est une carte Handicap
  public boolean EstUnHandicap( String nomCarte ) {
    for( int i=0 ; Handicap[ i ] != null ; i++ )
      if ( Handicap[ i ].compareTo( nomCarte ) == 0 )
	  return true;
    return false;
  }

  // teste si la carte est une carte solution a un handicap
  public boolean EstSolution( String nomCarte ) {
    for ( int i = 0 ; Solution[ i ] != null ; i++ )
      if ( nomCarte.compareTo( Solution[ i ] ) == 0 )
	return true;
    return false;
  }


  // teste si l'atout est solution de l'handicap
  // auquel cas l'handicap est leve
  public boolean AtoutEstSolution( String nomAtout, String nomHandicap ) {
    for( int i=0 ; Atout[i] != null ; i++ )
       if ( nomAtout.compareTo( Atout[i] ) == 0 )
	 if ( nomHandicap.compareTo( Handicap[i] ) == 0 )
	   return true;
    return false;
  }


  // teste si la carte est le feux vert
  public boolean EstUnFeuxVert( String nomCarte ) {
    if ( nomCarte.compareTo( "roll" ) == 0 )
      return true;
    return false;
  }

  // teste si la carte est le STOP
  public boolean EstUnStop( String nomCarte ) {
    if ( nomCarte.compareTo( "stop" ) == 0 )
	return true;
    return false;
  }


  // teste si l'on peut handicaper
  public boolean Handicaper( String handicap, String[] Atouts ) {
    System.err.println("[Jeux::Handicaper?("+handicap+")]");
    // 1 - recherche l'atout relatif a l'handicap (ex: punc_prf -> flattire)
    int i = -1;
    while ( Handicap[++i] != null )
      if ( Handicap[i].compareTo( handicap ) == 0 )
	break;
    // 2 - recherche l'atout ds Atouts[]
    int j=-1;
    while ( Atouts[++j] != null )
      if ( Atouts[j].compareTo( Atout[i] ) == 0 )
	return false; // on ne peut pas handicaper
    return true; // on peut handicaper
  }

  // teste si la carte soluce peut lever l'handicap
  public boolean LeveHandicap( String handicap, String soluce ) {
    System.err.println("[Jeux::LeveHandicap?("+handicap+","+soluce+")]");
    int i = -1;
    while ( Handicap[++i] != null )
      if ( Handicap[i].compareTo( handicap ) == 0 ) {
	if ( Solution[i].compareTo( soluce ) == 0 )
	  return true;
	else
	  return false;
      }
    return false;
  }


  // debuggage
  public void Debug( ) {
    System.err.println("[Jeux::Debug]");
    // affiche le jeux de carte
    for ( int i=0 ; i < taille ; i++ )
      jeux[i].Debug();    
  }

}




// Definition d'une Pioche
class Pioche {
/////////////////////////////////////////////////

  Jeux jeux;

  int    nbre_cartes; // contenue de la pioche
  Vector pioche;

  // constructeurs
  // cree une pioche vide
  public Pioche( ) {
    System.err.println("[Pioche::Pioche()]");
    nbre_cartes = 0;
    pioche = new Vector();
  }
  // cree une pioche contenant toutes les cartes du jeux
  public Pioche( Jeux j ) {
    System.err.println("[Pioche::Pioche( Jeux )]");
    jeux = j;
    pioche = j.CreerPioche();
    nbre_cartes = j.GetTaille();
  }

  // retourne TRUE si la pioche est vide
  public boolean EstVide( ) {
    return pioche.isEmpty();
  }

  // retourne la carte prealablement retiree de la pioche
  public String GetCarte( ) {
    String c = null;
    int    r;
    while( ( c = (String)pioche.elementAt( r = (int)(java.lang.Math.random()*nbre_cartes) ) ) == null ) {}
    pioche.removeElementAt( r );
    nbre_cartes--;
    return c;
  }


  // ajoute une carte a la pioche
  public void AjouteCarte( String nomCarte ) {
    System.err.println("[Pioche::AjouteCarte( "+nomCarte+" )]");
    nbre_cartes++;
    pioche.addElement( nomCarte );
  }


  // retourne la derniere carte ajoutee a la pioche
  // la carte disparait de la pioche
  public String GetDerniereCarteAjoutee( ) {
    System.err.println("[Pioche::GetDerniereCarteAjoutee()]");
    String s = null;
    if ( pioche.size() > 0 ) {
      s = (String)pioche.lastElement();
      pioche.removeElement( s );
    }
    return s;
  }

  // debuggage : vide la pioche, carte par carte
  public void Debug( ) {
    System.err.println("[Pioche::Debug]");
    int i=0;
    while ( ! pioche.isEmpty() ) {
      System.out.print( " pioche carte no " + ++i + " : " ); jeux.GetCarte( GetCarte() ).Debug();
    }
  }

}




public class TCD {

  static Jeux jeux;
  static Pioche pioche;
  static Pioche pioche_vide;

  // constructeur
  public TCD( ) {
    jeux = new Jeux();
    pioche = new Pioche( jeux ); // la pioche est creee a partir d'un jeu
    pioche_vide = new Pioche();  // la pioche ne contient aucune carte
    Debug();
  }

  // debuggage : teste les composants du TCD
  public static void Debug( ) {
    System.out.println(" Le jeux de carte (ordre de creation) : ");
    jeux.Debug();
    System.out.println(" Les cartes retirees de la pioche (ordre aleatoire) :");
    pioche.Debug();
    System.out.println(" Test des concordances entre types de cartes :");
    {
      System.out.print("Handicaper  punc_prf drv_ace rightway  avec  outofgaz ??? :");
      String Atouts[] = { "punc_prf","drv_ace","rightway", null };
      System.out.println( jeux.Handicaper( "outofgaz",  Atouts ) );
    }
    {
      System.out.print("Handicaper  punc_prf drv_ace xtratank rightway  avec  outofgaz ??? :");
      String Atouts[] = { "punc_prf","drv_ace","rightway", "xtratank", null };
      System.out.println( jeux.Handicaper( "outofgaz",  Atouts ) );
    }
    System.out.print("Lever handicap flattire avec spartire ??? :");
    System.out.println( jeux.LeveHandicap( "flattire",  "spartire" ) );
  }
  
  // prog principal
  public static void main(String argv[]) {
    TCD p = new TCD();
    System.out.println(" Fin du test du TCD ");
  }

}

