/*
    Copyright (C) 2004 Aymeric Augustin

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

import java.io.*;

class Carte {

    private int v;
    private int c;

    Carte(int val, int coul) {
        v = val;
        c = coul;
    }

    public String couleur() {
        String s;
        switch (c) {
        case 0:
            s = "trefle";
            break;
        case 1:
            s = "carreau";
            break;
        case 2:
            s = "coeur";
            break;
        case 3:
            s = "pique";
            break;
        default:
            s = "";
        }
        return s;
    }

    public String valeur() {
        String s;
        switch (v) {
        case 12:
            s = "As";
            break;
        case 9:
            s = "Valet";
            break;
        case 10:
            s = "Dame";
            break;
        case 11:
            s = "Roi";
            break;
        default:
            s = (v + 2) + "";
        }
        return s;
    }

    public String nom() {
        return valeur() + " de " + couleur();
    }

    public String toString() {
        return nom();
    }

    public boolean estEgale(Carte autreCarte) {
        return (v == autreCarte.v && c == autreCarte.c);
    }

    public boolean estAussiForteQue(Carte autreCarte) {
        return (v == autreCarte.v);
    }

    public boolean estPlusForteQue(Carte autreCarte) {
        return (v > autreCarte.v);
    }
}

class FileDeCartes {

    private Carte[] cartes;
    private int debut;
    private int fin;

    FileDeCartes() {
        cartes = new Carte[53];
        debut = 0;
        fin = 52;
    }

    public Carte pop() {
        Carte c = cartes[debut];
        debut = (debut + 1) % 53;
        return c;
    }

    public void push(Carte c) {
        fin = (fin + 1) % 53;
        cartes[fin] = c;
    }

    public void push(FileDeCartes f) {
        while (!f.estVide()) {
            push(f.pop());
        }
    }

    public boolean estVide() {
        return longueur() == 0;
    }

    public int longueur() {
        return (fin + 54 - debut) % 53;
    }

    public Carte readLast() {
        return cartes[fin];
    }

    public boolean estEgal(FileDeCartes f) {
        if (longueur() == f.longueur()) {
            for (int i = 0; i < longueur(); i++)
                if (!cartes[(debut + i) % 53].estEgale(f.cartes[(f.debut + i) % 53]))
                    return false;
            return true;
        }
        else return false;
    }

    public FileDeCartes copy() {
        FileDeCartes f = new FileDeCartes();
        for (int i = 0; i < 53; i++)
            f.cartes[i] = cartes[i];
        f.debut = debut;
        f.fin = fin;
        return f;
    }

    public static FileDeCartes jeuTrie() {
        FileDeCartes jeu  = new FileDeCartes();
        for (int c = 0; c < 4; c++) 
            for (int v = 0; v < 13; v++)
                jeu.cartes[13 * c + v] = new Carte (v, c);
        jeu.debut = 0;
        jeu.fin = 51;
        return jeu;
    }

    static int randInt(int i, int j) {
        return i + (int) ((j - i) * Math.random());
    }

    public static FileDeCartes jeuMelange() {
        FileDeCartes jeu  = jeuTrie();
        for (int i = 0; i < 52; i++) {
            int j = randInt(i, 52);
            Carte c = jeu.cartes[i];
            jeu.cartes[i] = jeu.cartes[j];
            jeu.cartes[j] = c;
        }
        jeu.debut = 0;
        jeu.fin = 51;
        return jeu;
    }

}

class Bataille {

    boolean enCours, poserCarte;
    int niveauDeBataille, duree;
    FileDeCartes jeu1, jeu2, jeu1ini, jeu2ini, pile1, pile2;

    Bataille () {
        enCours = true;
        poserCarte = true;
        niveauDeBataille = 0;
        jeu1 = new FileDeCartes();
        pile1 = new FileDeCartes();
        jeu2 = new FileDeCartes();
        pile2 = new FileDeCartes();
        FileDeCartes jeuMelange = FileDeCartes.jeuMelange();
        for (int i = 0; i < 26; i++) {
            jeu1.push(jeuMelange.pop());
            jeu2.push(jeuMelange.pop());
        }
        jeu1ini = jeu1.copy();
        jeu2ini = jeu2.copy();
    }

    public String addSpacesBefore(String s, int i) {
        for (int j = s.length(); j < i; j++)
            s = " " + s;
        return s;
    }

    public String addSpacesAfter(String s, int i) {
        for (int j = s.length(); j < i; j++)
            s = s + " ";
        return s;
    }

    public String jouerCoup() {
        if (enCours) {
            if (poserCarte) {
                if (jeu1.estEgal(jeu1ini) && jeu2.estEgal(jeu2ini) && duree > 0) {
                    enCours = false;
                    return "Cycle d'une longueur de " + duree + " coups.";
                }
                else {
                    for (int i = 0; i < niveauDeBataille + 1; i++) {
                        if (jeu1.estVide()) {
                            if (jeu2.estVide()) {
                                enCours = false;
                                return "Egalite au bout de " + duree + " coups.";
                            }
                            else {
                                enCours = false;
                                return "Victoire du joueur 2 en " + duree + " coups.";
                            }
                        }
                        else if (jeu2.estVide()) {
                            enCours = false;
                            return "Victoire du joueur 1 en " + duree + " coups.";
                        }
                        else {
                            pile1.push(jeu1.pop());
                            pile2.push(jeu2.pop());
                        }
                    }
                    poserCarte = false;
                    duree++;
                    return "("+ addSpacesBefore(jeu1.longueur() + "", 3) + " )"
                        + addSpacesBefore(pile1.readLast().nom(), 20) + "  -  "
                        + addSpacesAfter(pile2.readLast().nom(), 20)
                        + "("+ addSpacesBefore(jeu2.longueur() + "", 3) + " )";
                }
            }
            else {
                poserCarte = true;
                if (pile1.readLast().estAussiForteQue(pile2.readLast())) {
                    niveauDeBataille++;
                    return "("+ addSpacesBefore(jeu1.longueur() + "", 3) + " )"
                        + addSpacesAfter("            Bataille de niveau " + niveauDeBataille + ".      ", 45)
                        + "("+ addSpacesBefore(jeu2.longueur() + "", 3) + " )";
                }
                else if (pile1.readLast().estPlusForteQue(pile2.readLast())) {
                    jeu1.push(pile1);
                    jeu1.push(pile2);
                    niveauDeBataille = 0;
                return "("+ addSpacesBefore(jeu1.longueur() + "", 3) + " )"
                    + "            Le joueur 1 prend.               "
                    + "("+ addSpacesBefore(jeu2.longueur() + "", 3) + " )";
                }
                else {
                    jeu2.push(pile2);
                    jeu2.push(pile1);
                    niveauDeBataille = 0;
                return "("+ addSpacesBefore(jeu1.longueur() + "", 3) + " )"
                    + "            Le joueur 2 prend.               "
                    + "("+ addSpacesBefore(jeu2.longueur() + "", 3) + " )";
                }
            }
        }
        else return "Bataille terminee.";
    }

    public String jouerCoupRapide() {
        if (enCours) {
            if (poserCarte) {
                if (jeu1.estEgal(jeu1ini) && jeu2.estEgal(jeu2ini) && duree > 0) {
                    enCours = false;
                    return "Cycle d'une longueur de " + duree + " coups.";
                }
                else {
                    for (int i = 0; i < niveauDeBataille + 1; i++) {
                        if (jeu1.estVide()) {
                            if (jeu2.estVide()) {
                                enCours = false;
                                return "Egalite au bout de " + duree + " coups.";
                            }
                            else {
                                enCours = false;
                                return "Victoire du joueur 2 en " + duree + " coups.";
                            }
                        }
                        else if (jeu2.estVide()) {
                            enCours = false;
                            return "Victoire du joueur 1 en " + duree + " coups.";
                        }
                        else {
                            pile1.push(jeu1.pop());
                            pile2.push(jeu2.pop());
                        }
                    }
                    poserCarte = false;
                    duree++;
                    return "";
                }
            }
            else {
                poserCarte = true;
                if (pile1.readLast().estAussiForteQue(pile2.readLast())) {
                    niveauDeBataille++;
                    return "";
                }
                else if (pile1.readLast().estPlusForteQue(pile2.readLast())) {
                    jeu1.push(pile1);
                    jeu1.push(pile2);
                    niveauDeBataille = 0;
                    return "";
                }
                else {
                    jeu2.push(pile2);
                    jeu2.push(pile1);
                    niveauDeBataille = 0;
                    return "";
                }
            }
        }
        else return "Bataille terminee.";
    }

    public int jouerCoupTresRapide() {
        if (enCours) {
            if (poserCarte) {
                if (jeu1.estEgal(jeu1ini) && jeu2.estEgal(jeu2ini) && duree > 0) {
                    enCours = false;
                    return -duree;
                }
                else {
                    for (int i = 0; i < niveauDeBataille + 1; i++) {
                        if (jeu1.estVide() || jeu2.estVide()) {
                            enCours = false;
                        }
                        else {
                            pile1.push(jeu1.pop());
                            pile2.push(jeu2.pop());
                        }
                    }
                    poserCarte = false;
                    duree++;
                }
            }
            else {
                poserCarte = true;
                if (pile1.readLast().estAussiForteQue(pile2.readLast())) {
                    niveauDeBataille++;
                }
                else if (pile1.readLast().estPlusForteQue(pile2.readLast())) {
                    jeu1.push(pile1);
                    jeu1.push(pile2);
                    niveauDeBataille = 0;
                }
                else {
                    jeu2.push(pile2);
                    jeu2.push(pile1);
                    niveauDeBataille = 0;
                }
            }
        }
        return duree;
    }

}


class JouerUneBataille {

    public static void main (String[] args) throws IOException {
        if (args.length == 0) {
            System.err.println("Argument requis : nom du fichier a ecrire.");
            System.exit(1);
        }
        else {
            String fileName = args[0];
            FileWriter fw = new FileWriter(fileName);
            Bataille b = new Bataille ();
            while (b.enCours) {
                fw.write(b.jouerCoup() + "\n");
            }
            fw.close();
        }
    }

}

class JouerDesBatailles {

    public static void main (String[] args) throws IOException {
        if (args.length < 2) {
            System.err.println("Arguments requis : nom du fichier a ecrire, nombre de batailles a jouer.");
            System.exit(1);
        }
        else {
            String fileName = args[0];
            int n = Integer.parseInt(args[1]);
            FileWriter fw = new FileWriter(fileName);
            for (int i = 0; i < n; i++) {
                String s = "";
                Bataille b = new Bataille ();
                while (b.enCours) {
                    s = b.jouerCoupRapide();
                }
                fw.write(s + "\n");
            }
            fw.close();
        }
    }

}

class StatistiquesBatailles {

    public static void main (String[] args) throws IOException {
        if (args.length < 2) {
            System.err.println("Arguments requis : nom du fichier a ecrire, nombre de batailles a jouer.");
            System.exit(1);
        }
        else {
            String fileName = args[0];
            int n = Integer.parseInt(args[1]);
            int[] resultats = new int[5001];
            FileWriter fw = new FileWriter(fileName);
            fw.write("Cycles :\n");
            for (int i = 0; i < n; i++) {
                if (i % 1000000 == 0)
                    System.out.println(i);
                int d = 0;
                Bataille b = new Bataille ();
                while (b.enCours) {
                    d = b.jouerCoupTresRapide();
                }
                if (d < 0) {
                    fw.write((-d) + "\n");
                }
                else {
                    resultats[d]++;
                }
            }
            fw.write("\nParties terminées :\n");
            for (int i = 0; i < 5001; i++) {
                fw.write(resultats[i]+"\n");
            }
            fw.close();
        }
    }

}