What this is about...

This blog is about how I spend some of my time with my computers.

Various topics on Computing, Operating Systems, Programming Languages, Computer Games, Internet and Communications

Monday, February 22, 2010

Source Code

import java.lang.reflect.Method;
import javax.swing.JOptionPane;
import java.util.Arrays;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Display; 
import org.eclipse.swt.widgets.Label; 
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Slider;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

enum P7_Suit { Diamonds, Clubs, Hearts, Spades  }
enum P7_Rank { Ace, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King }

class P7_Statistics {
    protected long GamesPlayed;
    protected long Successes;
    protected long Failures;
    protected long NumberOfGamesToPlay=-1;
    protected float pctSuccess() {
        if (GamesPlayed>0) {
            float F=(float)Successes/(float)GamesPlayed;
            return(F);
        } else
            return((float)0);
    }
    protected float pctFailures() {
        if (GamesPlayed>0) {
            float F=(float)Failures/(float)GamesPlayed; 
            return(F);
        } else
            return((float)0); }
    protected P7_Statistics() {
        GamesPlayed=0;
        Successes=0;
        Failures=0;
    } // end method constructor
} // End class P7_Statistics

class P7_ButtonData {
    int Pile;
    String Action;
    P7_ButtonData(int P, String A) {
        Pile=P;
        Action=A;
    } // end method constructor
} // end class P7_ButtonData

class P7_FixedElements {
    private static P7_GameController GCtl;
    private static P7_GameModel GModel;
    private static P7_GameView GView;
    protected P7_FixedElements setGameMVC(P7_GameModel M, P7_GameView V, P7_GameController C) {
        GCtl=C; GModel=M; GView=V; return(this);
    } // end method set MVC
    protected static P7_GameModel getModel() { return(GModel); }
    protected static P7_GameView getView() { return(GView); }
    protected static P7_GameController getCtl() { return(GCtl); }

/*
* Graphical elements & Constants-----------------------------------------------------------
*/
    class P7_TripletButtonGrid { // Creates the bottom button grid.
        Button[][] Choices= new Button[P7_FixedElements.SUMITEMS][P7_FixedElements.NUMBEROFPILES];
        P7_TripletButtonGrid(Shell s, P7_GameModel GM, P7_GameView GV) {
            int X=P7_FixedElements.PILEORIGINX,
                Y=P7_FixedElements.WINDOWHEIGHT-(P7_FixedElements.BUTTONHEIGHT*P7_FixedElements.SUMITEMS)-(4*P7_FixedElements.BORDERSIZE);
            for (int R=0; R<P7_FixedElements.SUMITEMS; ++R) {
                for (int C=0; C<P7_FixedElements.NUMBEROFPILES; ++C) {
//                    System.out.println("X->"+X+", Y->"+Y);
                    Choices[R][C]= new Button(s, SWT.CENTER|SWT.PUSH);
                    Choices[R][C].setLocation(new Point(X,Y));
                    Choices[R][C].setText(P7_FixedElements.ChoicesText[R]);
                    Choices[R][C].setSize(P7_FixedElements.CARDWIDTH, P7_FixedElements.BUTTONHEIGHT);
                    Choices[R][C].moveAbove(null);
                    Choices[R][C].setData(new P7_ButtonData(C, P7_FixedElements.ChoicesText[R]));
//                    Choices[R][C].setBackground(GameBackgoundColor);
                    X=X+P7_FixedElements.CARDWIDTH+P7_FixedElements.BORDERSIZE;
//                    final Button Bb=Choices[R][C];
                    Choices[R][C].addSelectionListener(new P7_PileButtonAction(Choices[R][C]));
                } // end for C
                X=P7_FixedElements.PILEORIGINX;
                Y=Y+P7_FixedElements.BUTTONHEIGHT; //+P7_FixedElements.BORDERSIZE;
            } // end for R
        } // end method constructor
    } // end class P7_TripletButtonGrid
    protected static Image PileIndicatorImage;
    protected static Color GameBackgoundColor, TextForegroundColor;
    protected static final int WINDOWWIDTH=800; //620
    protected static final int WINDOWHEIGHT=650; //450
    protected static final int CARDWIDTH=71;
    protected static final int CARDHEIGHT=96;
    protected static final int PILEDISTANCE=80;
    protected static final int PILEORIGINX=5; // Coordinate X of the drawing location of the 1st pile
    protected static final int PILEORIGINY=5; // Coordinate Y of the drawing location of the 1st pile
    protected static final int BORDERSIZE=10;
    protected static final int CARDVISIBILITYDIVISORY=4;
    protected static final int CARDVISIBILITYDIVISORX=3;
    protected static final int VISIBLECARDPARTY= CARDHEIGHT/CARDVISIBILITYDIVISORY;
    protected static final int NUMBEROFPILES= 7;
    protected static final int DECKXLOCATION=(BORDERSIZE+CARDWIDTH)*(NUMBEROFPILES)+BORDERSIZE;
    protected static final int MAINWINDOWINITIALX=50;
    protected static final int MAINWINDOWINITIALY=50;
    protected static final int BUTTONWIDTH=100;
    protected static final int BUTTONHEIGHT= 30;
    protected static final int BUTTONFONTSIZE= 10;
    protected static final int BUTTONSXLOCATION=WINDOWWIDTH-BUTTONWIDTH-BORDERSIZE;
    protected static final int BUTTONSYORIGIN=5;
    protected static final int MINIMUMSCREENHEIGHT= 480;
    protected static final int MINIMUMSCREENWIDTH=640;
    protected static final int MAXNONSTACKEDCARDS= (WINDOWHEIGHT-P7_FixedElements.BORDERSIZE-3*P7_FixedElements.BUTTONHEIGHT-(P7_FixedElements.CARDHEIGHT-P7_FixedElements.VISIBLECARDPARTY))/VISIBLECARDPARTY;
    protected static Display D;
    private static Shell shell, info, rulesW;
    private static Font font; // the larger button font & other uses...
    protected static Button DealB, ExitGameB, AutoPlayB, NewGameB, RulesB, BlogB;
    private static Label ClearPileArea;
    protected static Label PileIndicator, NumberOfCardsInDeck;
    protected static Slider Speed;
    protected static Label[] A= new Label[4];
    protected static Label[] T= new Label[4];
    protected static Text NumberOfGamesToPlayT;
    protected static P7_TripletButtonGrid Sel;
/*
* Game related Constants & Objects----------------------------------------------------------------
*/
    protected static Random Generator = new Random();
    protected static P7_PlayingDeck PlDk, Deck01, Deck02, Shfl;
    protected static P7_Statistics Stats;
    protected static int CardPoints[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10 };
    protected static boolean Autoplay=false;
    protected static boolean FirstTime=true;
    protected static final String CARDFILENAMEEXTENSION= ".gif";
    protected static final int MAXDIGITSINMAXNUMBEROFGAMES=7;
    protected static final int SUMITEMS= 3;
    protected static final int NUMBEROFCARDSINSUIT=13;
    protected static final int NUMBEROFCARDSINDECK = 52;
    protected static final int NUMBEROFALLCARDSINDECK = 54;
    protected static final int SUFFLINGTIME = 4000;
    protected static final int MAXTIMEDELAYFORAUTOPLAY=1500;
    protected static final int NUMBEROFSUITS=4;
    protected static final int TOPCARDSTODISPLAY= (MAXNONSTACKEDCARDS/2)-1;
    protected static final int BOTTOMCARDSTODISPLAY=MAXNONSTACKEDCARDS/2;
    protected static final boolean KEEPYPOSITION=false;
    protected static final boolean ADVANCEYPOSITION=true;
    protected static final Point Ll=new Point(DECKXLOCATION, PILEORIGINY);
    private static final String Commentary[]= {
         "Written during 1Q2010 by NPL (
http://100goto100.blogspot.com/)",
         "I wrote this game to learn the Eclipse IDE, Java, and SWT.",
         "Please go to my blog to discuss the program, ways to improve it",
         "and alternative ways to do it. i.e using threads for a better UI."
    };
    protected static final String GameName= "7 Columns Solitaire";
    protected static final String ChoicesText[]= { "B3", "T2B1", "T1B2" };
    protected static String Platform;
    protected static Boolean WindowsOS= true;
    protected static String PileIndicatorFileName, CardImageFilePrefix[]= {" ", " " };
    protected static final String PileIndicatorFileNameWindows="bin\\resources\\PileIndicator.gif"; 
    protected static String CardImageFilePrefixWindows[]= { "bin\\resources\\10", "bin\\resources\\1" };
    protected static final String PileIndicatorFileNameUnix="./resources/PileIndicator.gif";
    protected static String CardImageFilePrefixUnix[]= { "./resources/10", "./resources//1" };

    private static final String BlogAddress= "http://100GOTO100.blogspot.com";
    private static final String Rules=
    "Player shuffles the deck. (Done automatcally in the game) \n"+
    "Player deals one by one cards in 7 vertical piles from the Deck.\n"+
    "While dealing the third row, for any 3 combo (as per below) that adds up to 10 or 20 or 30,\n"+
    "the player is free to move the three cards from the pile to the bottom of the deck.\n"+
    "There can be more than one combinations of valid triplets, and the player must choose\n"+
    "which triplet to remove. If after removing the cards there are still valid triplets in\n"+
    "the pile, the player is free to move them to the deck too, until no valid triplet exists anymore.\n"+
    "To deal a card from the deck, the player can hit the deal button, or double click on the deck,\n"+
    "or double click inside the window in any free area.\n\n"+
    "Once a card is dealt, the next one will be dealt to the next non-empty pile.\n"+
    "This is indicated with a small three-coloured box beneath the bottom row of buttons.\n"+
    "For any (non-empty, of course) pile, the player can double click on a card to select:\n\n"+
    " a) the 3 bottom cards (double click on the third card from the bottom), or\n"+
    " b) the 2 top cards and the 1 bottom card (double click on the bottom card), or\n"+
    " c) the top 1 card and the 2 bottom cards (double click on the second card from the bottom).\n\n"+
    "The sum of these cards must be 10, or 20 or 30. Nothing will happen otherwise.\n"+
    "If, after dealing a card, a pile contains only 3 cards with the correct sum (10, 20, or 30)\n"+
    "then removing the cards will leave the pile empty (which moves the player closer to winning),\n"+
    "and will be skipped (will not be dealt to) for the rest of the game.\n\n"+
    "Player wins when all the cards return to the deck.\n"+
    "Player loses when the deck becomes empty (all cards are dealt to the piles, and\n"+
    "no eligible triplets can be lifted from any pile).\n"+
    "If autoplay is checked, dealing will become automatic, and the table will update\n"+
    "at the speed selected by the slider. While in normal mode, the user can enter a number of games\n"+
    "in the text field indected as such. When Autoplay is selected, the game will try to play this\n"+
    "number of games, while updating the statistics. The textbox becomes inactive but counts down the\n"+
    "number of games still left to be played. Please be aware that the game can become 'stuck', i.e.\n"+
    "it can play the same moves forever (for now, until I can figure a way to detect this), and so never\n"+
    "terminate. If this happens, the user can interfere by going into normal (manual) mode and dealing\n"+
    "the cards without removing them from the piles. When the deck is out of cards, the games will be\n"+
    "marked as lost. At that point the user can re-check the autoplay and resume the statistics.\n";
/*
* Constructors ------------------------------------------------------------------------
*/
    protected P7_FixedElements() { // constructor
        D= new Display();
        shell= new Shell(P7_FixedElements.D, SWT.CLOSE | SWT.TITLE | SWT.MIN | SWT.MAX);
        info= new Shell(P7_FixedElements.D, SWT.TITLE);
        rulesW= new Shell(info, SWT.CLOSE | SWT.TITLE | SWT.MIN | SWT.MAX);
        GameBackgoundColor= P7_FixedElements.D.getSystemColor(SWT.COLOR_DARK_GREEN);
        TextForegroundColor= P7_FixedElements.D.getSystemColor(SWT.COLOR_WHITE);
//         Create a larger font for the buttons
        FontData[] fd = shell.getFont().getFontData();
        for (int i = 0; i < fd.length; i++) {
            fd[i].setHeight(P7_FixedElements.BUTTONFONTSIZE);
        } // end for i
        font = new Font(P7_FixedElements.D,fd);
        try {
            Platform= SWT.getPlatform();
            if (Platform.startsWith("win")) {
                WindowsOS=true;
                P7_FixedElements.PileIndicatorFileName=P7_FixedElements.PileIndicatorFileNameWindows;
            } else {
                WindowsOS=false;
                P7_FixedElements.PileIndicatorFileName=P7_FixedElements.PileIndicatorFileNameUnix;
            } // end else
            FileInputStream fis = new FileInputStream(PileIndicatorFileName);
            PileIndicatorImage= new Image(D, PileIndicatorFileName);
        }
        catch (FileNotFoundException ex) {
            abortApplication("Indicator Image File: "+PileIndicatorFileName+" not found. Abrupt end of program!");
        } // end catch
        Deck01=new P7_PlayingDeck(Ll, false);
        Deck02=Deck01.copy();
        PlDk= Deck01; // Start Playing with deck01
        Shfl= Deck02;  // Assign Deck02 to be shuffled while playing
        Stats= new P7_Statistics();
        setupGraphicalElements();
        // call the D.getBounds or the D.getClientArea to determine if the screen has enough room to show the game
    } //end constructor P7_FixedElements
    protected static Shell getMainWindow() { return(shell); }
    protected static Shell getInfoWindow() { return(info); }
    protected static Shell getRulesWindow() { return(rulesW); }
    protected void cleanUp() { // cleanup/dispose of SWT Objects
//        rulesW.dispose();
        info.dispose();
        shell.dispose();
        D.dispose();
    } // end of View.cleanUp
    private void setUpMainWindowAttributesAndListeners() {
        shell.setText("NPL's PatienJava (V0.1) "+GameName+" - Running under "+SWT.getPlatform()+", and SWT Version "+SWT.getVersion());
        shell.setLocation(P7_FixedElements.MAINWINDOWINITIALX, P7_FixedElements.MAINWINDOWINITIALY);
        shell.setBounds(P7_FixedElements.MAINWINDOWINITIALX, P7_FixedElements.MAINWINDOWINITIALY, P7_FixedElements.WINDOWWIDTH, P7_FixedElements.WINDOWHEIGHT);
        shell.setBackground(GameBackgoundColor);
        shell.addMouseListener(new MouseListener() { // Double clicking anywhere in the window deals a card
                public void mouseDown(MouseEvent e) {}
                public void mouseUp(MouseEvent e) {} // Label l = new Label(s, SWT.FLAT); l.setText("Mouse Button up at:" + e.x + " " + e.y); l.setBounds(e.x, e.y, 150, 15);
                public void mouseDoubleClick(MouseEvent e) {
                        (P7_FixedElements.getCtl()).processDealButton();
                }
              });
        shell.addListener(SWT.Close, new Listener() {
            public void handleEvent(Event event) {
                if (areUSure()) {
                    (P7_FixedElements.getCtl()).processUserExitRequest();
                    event.doit=true;
                    cleanUp();
                } // end if
                else event.doit=false; // System.out.println("returning to game...");
            }
          });
    } // end method setUp MainWindowListeners
    private void checkScreenSize() {
        // Get screen size info
        Rectangle R= P7_FixedElements.D.getBounds();
        int ScreenHeight= R.height;
        int ScreenWidth= R.width;
        if (ScreenHeight<P7_FixedElements.MINIMUMSCREENHEIGHT)
            popUpAbortDialog("Screen height is too small for this game.");
        if (ScreenWidth<P7_FixedElements.MINIMUMSCREENWIDTH)
            popUpAbortDialog("Screen width is too small for this game.");
    } // end method check screen size
    private void popUpAbortDialog(String Message) {
        MessageBox messageBox = new MessageBox(getMainWindow(), SWT.OK);
        messageBox.setMessage(Message);
        messageBox.setText("Bummer!");
        messageBox.open();
        cleanUp();
        System.exit(1);
    } // end method popUpAbortDialog
    protected static boolean betterLuckNextTime() {
        MessageBox messageBox = new MessageBox(getMainWindow(), SWT.OK|SWT.CANCEL);
        messageBox.setMessage("Sorry! Press [OK] to play again or [Cancel] to exit.");
        messageBox.setText("Bummer!");
        if (messageBox.open() == SWT.OK) { return(false); } //endif
//        else P7_FixedElements.abortApplication("Goodbye! Thanks for playing...");
        return(true);
    } //betterLuckNextTime
    protected static boolean congrats() {
        MessageBox messageBox = new MessageBox(getMainWindow(), SWT.OK|SWT.CANCEL);
        messageBox.setText("U r a winner!");
        messageBox.setMessage("Bravo! This time it worked! Press [OK] to play again or [Cancel] to exit.");
        if (messageBox.open() == SWT.OK) return(false); //endif
        return(true);
    } //congrats
    private boolean areUSure() {
        MessageBox messageBox = new MessageBox(getMainWindow(), SWT.OK|SWT.CANCEL);
        messageBox.setText("Confirmation of Exit");
        messageBox.setMessage("Are you sure you want to exit the game?\n Press OK to exit or Cancel to go back.");
        if (messageBox.open() == SWT.OK) {
            messageBox.setMessage("Goodbye! Thanks for playing...");
            return(true);
        } // endif
        else {
            messageBox.setMessage("Returning...");
            return(false);
        } // end else
    }// end method areUSure
    private Button createDealButton() {
        Point Location= new Point(BUTTONSXLOCATION,BUTTONSYORIGIN);
        Button DealButton= new Button(getMainWindow(), SWT.CENTER| SWT.PUSH);
        DealButton.setFont(font);
        DealButton.setLocation(Location);
        DealButton.setText("Deal");
        DealButton.setSize(BUTTONWIDTH, BUTTONHEIGHT);
        P7_DealButtonSelectionAdapter AS= new P7_DealButtonSelectionAdapter();
        DealButton.addSelectionListener(AS);
        return(DealButton);
    } // end method createDealButton
    private Button createAutoplayCheck() {
        int Y=BUTTONSYORIGIN+2*(BUTTONHEIGHT+(BORDERSIZE/2));
        Point Location= new Point(BUTTONSXLOCATION,Y);
        Button AutoPlay= new Button(getMainWindow(), SWT.LEFT| SWT.CHECK);
        AutoPlay.setFont(font);
        AutoPlay.setLocation(Location);
        AutoPlay.setText("Autoplay");
        AutoPlay.setSize(BUTTONWIDTH, BUTTONHEIGHT);
        AutoPlay.setBackground(GameBackgoundColor);
        AutoPlay.setForeground(TextForegroundColor);
        AutoPlay.setEnabled(true);
        AutoPlay.setSelection(Autoplay);
        AutoPlay.addSelectionListener(new SelectionAdapter() {
              public void widgetSelected(SelectionEvent event) {
                  boolean Selected=false;
                  Button X= (Button) event.widget;
                  if (X==null) abortApplication("Check box null!");
                  X.setRedraw(true);
                  Selected=X.getSelection();
                  Autoplay=Selected;
                  if (Autoplay) {
                      DealB.setEnabled(false); // disable deal button
                      NewGameB.setEnabled(false); // disable  new game button
                      NumberOfGamesToPlayT.setEnabled(false);
                      Speed.setEnabled(true);
                  } else {
                      DealB.setEnabled(true); // enable deal button
                      NewGameB.setEnabled(true); // enable  new game button
                      NumberOfGamesToPlayT.setEnabled(true);
                      Speed.setEnabled(false);
                  } // end else
                  try {
                       String S= NumberOfGamesToPlayT.getText();
                       long lo = Long.parseLong(S.trim());
//                       System.out.println("long l = " + lo);
                       P7_FixedElements.Stats.NumberOfGamesToPlay=lo;
                      } catch (NumberFormatException nfe) {
//                         System.out.println("NumberFormatException: " + nfe.getMessage());
                          NumberOfGamesToPlayT.setText("-1");
                      }
                  event.doit=true;
                  // GM.setStopGame();
              }
            });
        return(AutoPlay);
    } // end method createAutoplayCheck
    private Slider createSpeedSlider() {
        int Y=BUTTONSYORIGIN+SUMITEMS*(BUTTONHEIGHT+(BORDERSIZE/2));
        Point Location= new Point(BUTTONSXLOCATION,Y);
        Slider Speed= new Slider(getMainWindow(), SWT.HORIZONTAL);
        Speed.setLocation(Location);
        Speed.setSize(BUTTONWIDTH, BUTTONHEIGHT);
        Speed.setEnabled(true);
        Speed.setMinimum(0); Speed.setMaximum(MAXTIMEDELAYFORAUTOPLAY);
        Speed.setSelection(0);
        Speed.setBackground(GameBackgoundColor);
        Speed.addSelectionListener(new SelectionAdapter() {
              public void widgetSelected(SelectionEvent event) { // When the button is clicked, exit app
                  getModel().GS.AutoPlayDelay= ((Slider)(event.widget)).getSelection();
              }
            });
        return(Speed);
    } // end method createSpeedSlider
    private void createLabelNumberOfGames() {
        int Y=BUTTONSYORIGIN+5*(BUTTONHEIGHT+(BORDERSIZE/2));
        Point Location= new Point(BUTTONSXLOCATION,Y);
        Label NoOfGames= new Label(getMainWindow(), SWT.LEFT|SWT.HORIZONTAL|SWT.SHADOW_IN);
        NoOfGames.setFont(font);
        NoOfGames.setLocation(Location);
        NoOfGames.setText("# of games");
        NoOfGames.setSize(BUTTONWIDTH, BUTTONHEIGHT);   
        NoOfGames.setBackground(GameBackgoundColor);
        NoOfGames.setForeground(TextForegroundColor);
    } // end method createLabelNumberOfGames
    private Text createTextInputNumberOfGames() {
        int Y=BUTTONSYORIGIN+6*(BUTTONHEIGHT+(BORDERSIZE/2));
        Point Location= new Point(BUTTONSXLOCATION,Y);
        Text NoOfGames= new Text(getMainWindow(), SWT.SINGLE|SWT.BORDER|SWT.LEFT);
        NoOfGames.setFont(font);
        NoOfGames.setLocation(Location);
        NoOfGames.setSize(BUTTONWIDTH, BUTTONHEIGHT);
//        NoOfGames.setBackground(GameBackgoundColor);
        NoOfGames.setForeground(TextForegroundColor);
        NoOfGames.addSelectionListener(new SelectionAdapter() {
              public void widgetSelected(SelectionEvent event) {
                  Text T=((Text)(event.widget));
                  String S= T.getText();
                  try {
                       long lo = Long.parseLong(S.trim());
//                       System.out.println("long l = " + lo);
                       P7_FixedElements.Stats.NumberOfGamesToPlay=lo;
                      } catch (NumberFormatException nfe) {
//                         System.out.println("NumberFormatException: " + nfe.getMessage());
                         T.setText("-1");
                      }
                      event.doit=true;
              }
            });

        return(NoOfGames);
    } // end method createTextInputNumberOfGames
    private Button createNewGameButton() {
        int Y=BUTTONSYORIGIN+7*(BUTTONHEIGHT+(BORDERSIZE/2));
        Point Location= new Point(BUTTONSXLOCATION, Y);
        Button NewGameButton= new Button(getMainWindow(), SWT.CENTER| SWT.PUSH);
        NewGameButton.setFont(font);
        NewGameButton.setLocation(Location);
        NewGameButton.setText("New Game");
        NewGameButton.setSize(BUTTONWIDTH, BUTTONHEIGHT);
        NewGameButton.addSelectionListener(new SelectionAdapter() {
              public void widgetSelected(SelectionEvent event) { // When the button is clicked, exit app
                  P7_FixedElements.getModel().GS.StopGame=true;
              }
            });
        return(NewGameButton);
    } // end method createNewGameButton
    private Button createExitGameButton() {
        int Y= WINDOWHEIGHT-BUTTONHEIGHT-4*BORDERSIZE;
        Point Location= new Point(BUTTONSXLOCATION, Y);
        Button ExitGameButton= new Button(getMainWindow(), SWT.CENTER| SWT.PUSH);
        ExitGameButton.setFont(font);
        ExitGameButton.setLocation(Location);
        ExitGameButton.setText("Exit Game");
        ExitGameButton.setSize(BUTTONWIDTH, BUTTONHEIGHT);
        ExitGameButton.addSelectionListener(new SelectionAdapter() {
              public void widgetSelected(SelectionEvent event) { // When the button is clicked, exit app
                  boolean Confirmation=areUSure();
                  if (Confirmation) {
                     getCtl().processUserExitRequest();
                     event.doit=true;
                     cleanUp();
                    } // end if
              }
            });
        return(ExitGameButton);
    } // end createExitGameButton
    private Label createNumberOfCardsInDeck() {
        int Y=BUTTONSYORIGIN+3*(BUTTONHEIGHT+(BORDERSIZE/2));
        Point L= new Point(DECKXLOCATION, Y);
        Label NOC= new Label(getMainWindow(), SWT.CENTER);
        NOC.setFont(font);
        NOC.setText("Deck:");
        NOC.setSize(CARDWIDTH, CARDHEIGHT/2);
        NOC.setBackground(GameBackgoundColor);
        NOC.setForeground(TextForegroundColor);
        NOC.setLocation(L);
        return(NOC);
    } // end method create number of cards in deck label
    private void createInfoWindow() {
        getInfoWindow().setText("Statistics for PatientzaJ");
        getInfoWindow().setLocation(MAINWINDOWINITIALX+850, MAINWINDOWINITIALY+100);
        FillLayout L= new FillLayout(SWT.VERTICAL);
        getInfoWindow().setLayout(L);
        String Losses= "Games Lost: "+Long.toString(Stats.Failures);
        A[0]= new Label(getInfoWindow(), SWT.CENTER|SWT.HORIZONTAL|SWT.SHADOW_IN);
        A[0].setText(Losses.toString());
        String Wins= "Games Won :"+Long.toString(Stats.Successes);
        A[1]= new Label(getInfoWindow(), SWT.CENTER|SWT.HORIZONTAL|SWT.SHADOW_IN);
        A[1].setText(Wins);
        String TotalGames= "Total Games Played: "+Long.toString(Stats.GamesPlayed);
        A[2]= new Label(getInfoWindow(), SWT.CENTER|SWT.HORIZONTAL|SWT.SHADOW_IN);
        A[2].setText(TotalGames);
        String Pctgs= "Percentages: Successes("+Float.toString(Stats.pctSuccess())+"%, Failures("+Float.toString(Stats.pctFailures())+")";
        A[3]= new Label(getInfoWindow(), SWT.CENTER|SWT.HORIZONTAL|SWT.SHADOW_IN);
        A[3].setText(Pctgs);
        T[0]= new Label(getInfoWindow(), SWT.CENTER|SWT.HORIZONTAL|SWT.SHADOW_IN);
//        T[0].setFont(font);
        T[0].setText(P7_FixedElements.Commentary[0]);
        T[1]= new Label(getInfoWindow(), SWT.CENTER|SWT.HORIZONTAL|SWT.SHADOW_IN);
        T[1].setText(P7_FixedElements.Commentary[1]);
        T[2]= new Label(getInfoWindow(), SWT.CENTER|SWT.HORIZONTAL|SWT.SHADOW_IN);
        T[2].setText(P7_FixedElements.Commentary[2]);
        T[3]= new Label(getInfoWindow(), SWT.CENTER|SWT.HORIZONTAL|SWT.SHADOW_IN);
        T[3].setText(P7_FixedElements.Commentary[3]);
        getInfoWindow().pack();
    } // end method createInfoWindow
    private Button createRulesOfTheGameButton() {
        final Button RulesButton= new Button(getInfoWindow(), SWT.CENTER| SWT.PUSH);
        RulesB= RulesButton;
        RulesButton.setText("So, what are the rules?");
        RulesButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent event) {
                rulesW= new Shell(getInfoWindow(), SWT.CLOSE | SWT.TITLE | SWT.MIN | SWT.MAX);
                rulesW.setText("PatientzaJ Rules");
                rulesW.setLocation(MAINWINDOWINITIALX, MAINWINDOWINITIALY);
                rulesW.setLayout(new GridLayout());
                Label Descr= new Label(getRulesWindow(), SWT.LEFT | SWT.HORIZONTAL | SWT.SHADOW_IN);
                Descr.setText(Rules);
                RulesB.setEnabled(false);
                rulesW.pack();
                rulesW.open();
                rulesW.addDisposeListener(new DisposeListener() {
                      public void widgetDisposed(DisposeEvent event) {
                         RulesB.setEnabled(true);
                      } // end method widgetDisposed
                });
              }
            });
        return(RulesButton);
    } // end method createRulesOfTheGameButton
    private Button createGotoBlogButton() {
        Button GotoNPLBlog= new Button(getInfoWindow(), SWT.CENTER| SWT.PUSH);
        GotoNPLBlog.setText("Visit my blog for the source code!");
        GotoNPLBlog.setSize(BUTTONWIDTH, BUTTONHEIGHT);       
        final String url= "
http://100goto100.blogspot.com/";
        GotoNPLBlog.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent event) {
                     BareBonesBrowserLaunch.openURL(url);
            }
        });
        return(GotoNPLBlog);
    } // end method createGotoBlogButton
    private void createPileIndicator() {
        Rectangle R=PileIndicatorImage.getBounds();
        PileIndicator= new Label(getMainWindow(), SWT.CENTER);
        PileIndicator.setImage(PileIndicatorImage);
        PileIndicator.setSize(CARDWIDTH, R.height);
        PileIndicator.setBackground(GameBackgoundColor);
    }
    private P7_FixedElements transferCardsToMainWindow() {
        int Index;
        int DeckSize=PlDk.depth();
        for (Index=0; Index<DeckSize; ++Index) {
            Label Temp=PlDk.referenceCard(Index).getLabel();
            Temp.setParent(getMainWindow());
            Temp.redraw();
        } // end for Index
        return(this);
    } // end method transfer cards to main window
    protected P7_FixedElements createPileGraphics() {
        ClearPileArea=new Label(getMainWindow(), SWT.CENTER);
        ClearPileArea.setText("");
        return(this);
    } // end method createPileGraphics
    private P7_FixedElements setupGraphicalElements() {
        checkScreenSize();    //  Game can abort at this point if screen is not sufficient. If it is, next line is executed.
        // Setup window title, location and layout. Put the buttons
        setUpMainWindowAttributesAndListeners();
        DealB=createDealButton();
        AutoPlayB=createAutoplayCheck();
        Speed=createSpeedSlider();
        createLabelNumberOfGames();
        NumberOfGamesToPlayT=createTextInputNumberOfGames();
        NumberOfGamesToPlayT.setTextLimit(MAXDIGITSINMAXNUMBEROFGAMES);
        NumberOfGamesToPlayT.setText("-1");
        NewGameB=createNewGameButton();
        ExitGameB=createExitGameButton();
        NumberOfCardsInDeck=createNumberOfCardsInDeck();
        createInfoWindow();
        RulesB=createRulesOfTheGameButton();
        BlogB=createGotoBlogButton();
        Sel= new P7_TripletButtonGrid(getMainWindow(), getModel(), getView());
        createPileIndicator();
        transferCardsToMainWindow();
        P7_FixedElements.PlDk.resetCardsLocation();
        P7_FixedElements.Shfl.resetCardsLocation();
        // getMainWindow().open();
        // getInfoWindow().open();
        return(this);
    } //end method setUpgraphicalElemets
// Various debug methods
    protected static void abortApplication(String S) {
        System.out.println(S);
        System.exit(1);
    } //end method abortApplication
    protected static void outputPoint(Point P) {
        System.out.println("X("+P.x+") Y("+P.y+")");
    } // end method outputPoint
    protected static void pressAnyKey() {
        try
        {
            BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
            int ch = stdin.read();
            if(ch ==-1)    return;
        } // end try
        catch(IOException io) {
            System.out.println("ERROR" + io);
        } // end catch
    } // end method pressanykey

} // end class P7_FixedElements

/*
* VIEW Classes----------------------------------------------------------------
*/

class P7_GameView {
    private P7_GameModel GM;
    protected P7_GameView(P7_GameModel G) { GM=G; } //end view constructor
    protected void updateGraphicalElements() {
        showStats(P7_FixedElements.A, P7_FixedElements.Stats);
        showDeck(GM.deck());
        showAllPiles();
        } //end method updategraphicalElemets
    protected P7_GameView showDeckAndPile(P7_PlayingDeck Dk, P7_Pile Pl) { showPile(Pl); showDeck(Dk); return(this);}
    protected P7_GameView showTheWindows() {
        P7_FixedElements.getMainWindow().open();
        P7_FixedElements.getInfoWindow().open();
        P7_FixedElements.getInfoWindow().pack();
        return(this);
    } // end method initial setup
    protected P7_GameView showCard(P7_PlayingCard PC) {
        if (PC.isVisible())
            PC.Lb.moveAbove(null);
        P7_FixedElements.D.update();
        return(this);
    } //end View.showCard
    protected P7_GameView showPile(P7_Pile P) {
        int I= P.depth();
        P.correctYValues();
        for (int J=0; J<I; ++J) showCard(P.referenceCard(J));
        return(this);
    } // end method show pile
    protected P7_GameView showStats(Label[] Aa, P7_Statistics Stats) {
        String Losses= "Games Lost: "+ Long.toString(Stats.Failures);
        if (Aa[0]==null) P7_FixedElements.abortApplication("Aa[0] is null!, Losses string is: "+Losses);
            Aa[0].setText(Losses);
        String Wins= "Games Won :"+ Long.toString(Stats.Successes);
        Aa[1].setText(Wins);
        String TotalGames= "Total Games Played: "+Long.toString(Stats.GamesPlayed);
        Aa[2].setText(TotalGames);
        String Pctgs= "Successes: "+Float.toString(Stats.pctSuccess()*100)+
                       "%, Failures: "+Float.toString(Stats.pctFailures()*100)+"%";
        Aa[3].setText(Pctgs);
        P7_FixedElements.getInfoWindow().pack();
        return(this);
    } // End showStats   
    protected P7_GameView showAllPiles() {
        for (int I=0; I<P7_FixedElements.NUMBEROFPILES; ++I)
            showPile(GM.Piles[I]);
        return(this);
    } // end method showAllPiles
    protected void showCurrentPileIndicator() {
        Button K=P7_FixedElements.Sel.Choices[2][1];
        Point Pp= GM.currentPile().getLocation();
        P7_FixedElements.PileIndicator.setLocation(Pp.x, K.getLocation().y+P7_FixedElements.BUTTONHEIGHT);
        P7_FixedElements.PileIndicator.moveAbove(null);
    } // end method showCurrentPileIndicator
    protected void showDeck(P7_PlayingDeck D) {
        int I= D.depth();
        P7_FixedElements.NumberOfCardsInDeck.setText("Left: "+Integer.toString(I));
        P7_FixedElements.NumberOfCardsInDeck.moveAbove(null);
        if (I==0) return;
        showCard(D.referenceCard(0));
        showCurrentPileIndicator();
    } // end method showDeck
} // End class View
/*
* CONTROLLER classes-----------------------------------------------------------------
*
*/
class P7_DealButtonSelectionAdapter extends SelectionAdapter {
    public void widgetSelected(SelectionEvent event) {
        P7_FixedElements.getCtl().processDealButton();
    } // widgetSelected
} // end class SelAdpt

class P7_PileButtonAction extends SelectionAdapter {
    Button Bb;
    P7_PileButtonAction(Button X) {
        Bb=X;
    } // end method constructor
    public void widgetSelected(SelectionEvent event) {
        whatAndWhere();
        P7_ButtonData X=(P7_ButtonData)Bb.getData();
        P7_FixedElements.getView().showDeckAndPile(P7_FixedElements.PlDk, P7_FixedElements.getModel().Piles[X.Pile]);
      } // end method widget selected
    protected void whatAndWhere() {
        P7_ButtonData BD= (P7_ButtonData) Bb.getData();
        int ButtonPile= BD.Pile;
        P7_Pile TempPile= P7_FixedElements.getModel().Piles[ButtonPile];
        if (ButtonPile<0 || ButtonPile>=P7_FixedElements.NUMBEROFPILES) { P7_FixedElements.abortApplication("Invalid Pile Number! Aborting"); }
        if (BD.Action.equals(P7_FixedElements.ChoicesText[0])) { // B3 cards
            if (TempPile.checkForB3Sum()) P7_FixedElements.getModel().removeB3(ButtonPile);
        } // end if
        else if (BD.Action.equals(P7_FixedElements.ChoicesText[1])) { // T2B1 cards
            if (TempPile.checkForT2B1Sum()) P7_FixedElements.getModel().removeT2B1(ButtonPile);
        }
        else if (BD.Action.equals(P7_FixedElements.ChoicesText[2])) { // T1B2 cards
            if (TempPile.checkForT1B2Sum()) P7_FixedElements.getModel().removeT1B2(ButtonPile);
        }
        else P7_FixedElements.abortApplication("Error. Action String other than accepted values ("+BD.Action+")");
        // Decide if the Pile will be avoided from now on
//        if (TempPile.depth()==0)
//            TempPile.avoid();
//        float Pile= L.x/X;
//        System.out.println("Calculated pile: "+Float.toString(Pile)+" Stored Pile: "+BD.Pile+" Action: "+BD.Action);
    } // end method what and where
} // end class P7_PileButtonAction

class P7_DeckCardMouseAdapter extends MouseAdapter {
      public void mouseDown(MouseEvent e) {}
      public void mouseUp(MouseEvent e) {} /* Label l = new Label(s, SWT.FLAT); l.setText("Mouse Button up at:" + e.x + " " + e.y); l.setBounds(e.x, e.y, 150, 15); */
      public void mouseDoubleClick(MouseEvent e) {
//             System.out.println("Got double-click on deck!"); // DEBUG
             (P7_FixedElements.getCtl()).processDealButton();
      } // end method mouseDoubleClick
} // end class P7_DeckCardMouseAdapter

class P7_PileCardMouseAdapter extends MouseAdapter {
      public void mouseDown(MouseEvent e) {}
      public void mouseUp(MouseEvent e) {} /* Label l = new Label(s, SWT.FLAT); l.setText("Mouse Button up at:" + e.x + " " + e.y); l.setBounds(e.x, e.y, 150, 15); */
      public void mouseDoubleClick(MouseEvent e) {
             (P7_FixedElements.getCtl()).processPileClick((Label) e.widget);
      } // end method mouseDoubleClick   
} // end class P7_PileCardMouseAdapter

class P7_GameController {
    private P7_GameView GV;
    private P7_GameModel GM;
    protected P7_GameController(P7_FixedElements F, P7_GameView GView, P7_GameModel GModel) { GV=GView; GM=GModel; }
    protected void initialSetup() {
        if (P7_FixedElements.FirstTime) {
            P7_FixedElements.FirstTime=false;
            P7_FixedElements.PlDk.shuffle(-1);
        }
        // Deal 2 rows by 7 columns before the main processing of the triplets begins
        for (int C=0; C<2; ++C) { //Rows
            for (int C2=0; C2<P7_FixedElements.NUMBEROFPILES; ++C2) { //Columns
                if (P7_FixedElements.PlDk.isEmpty()==false) {
                    P7_PlayingCard T= P7_FixedElements.PlDk.deal();
                    T.setOpen();
                    T.pileMouseAdapter();
                    GM.Piles[C2].appendCard(T, P7_FixedElements.ADVANCEYPOSITION);
                } //if
                else P7_FixedElements.abortApplication("Deck run out during initialization phase, something is terribly wrong!");
//                System.out.println("["+C2+"] ");
            } // endfor C2
        } //endfor C
    } //initialSetup
    protected P7_PlayingCard locateCard(Label Source) {
        P7_PlayingCard Result= P7_FixedElements.PlDk.lookUp(Source); // look in the Deck first
        if (Result==null) { // card not in the deck
            int PileIndex;
            // Now look in the piles
            for (PileIndex=0; PileIndex<P7_FixedElements.NUMBEROFPILES; ++PileIndex) {
                Result= GM.Piles[PileIndex].lookUp(Source);
                if (Result!=null)
                    return(Result); // Card found, return result
            } // end for
        } // end card not in deck   
        return(Result); // return either null or Card from deck
    } // end method locate card from Label reference
    protected P7_GameController processDealButton() {
//        System.out.println("Gotta deal!"); // DEBUG       
        P7_Pile Temp=GM.currentPile();
        boolean Goon= GM.deal2Pile();
        GV.showDeckAndPile(GM.deck(), Temp);
        if (Goon)
            return(this); // we are done, game is proceeding
        else {
                GM.GS.StopGame=true;
                if (P7_FixedElements.Autoplay) /*RETURN HERE */ ;
                else if (GM.areAllPilesEmpty()) GM.GS.GameOver=P7_FixedElements.congrats();
                     else GM.GS.GameOver=P7_FixedElements.betterLuckNextTime();
        }
        return(this);
    } // end method processDealButton
    protected P7_GameController processPiles(P7_Pile PreviousPile) {
        Random FiftyFifty= new Random();
        int Toss=0, NoOfPossibles=0, Pile2CheckIndex;
        boolean B3, T1B2, T2B1;
        P7_Pile PileToCheck= PreviousPile;
        Pile2CheckIndex=PileToCheck.getIndex();
        LinkedList<Integer> Choser = new LinkedList<Integer>();
        do {
              B3=   PileToCheck.checkForB3Sum();
              T1B2= PileToCheck.checkForT1B2Sum();
              T2B1= PileToCheck.checkForT2B1Sum();
            Choser.clear();
             NoOfPossibles=0;
              if (B3)   { ++NoOfPossibles; Choser.add(1); } else Choser.add(0);
              if (T1B2) { ++NoOfPossibles; Choser.add(1); } else Choser.add(0);
             if (T2B1) { ++NoOfPossibles; Choser.add(1); } else Choser.add(0);
//              System.out.println("Pile is: "+Pile2CheckIndex+" size("+PileToCheck.depth()+")"+" Deck size: "+GM.numberOfCardsInDeck()+", Hits:"+NoOfPossibles); // DEBUG
              switch (NoOfPossibles) {
              case 0: break; // Nothing to remove, return
              case 1: if (B3) GM.removeB3(Pile2CheckIndex);
                      else if (T1B2) GM.removeT1B2(Pile2CheckIndex);
                           else if (T2B1) GM.removeT2B1(Pile2CheckIndex);
                           else P7_FixedElements.abortApplication("Impossible: you said one would be true!"+ NoOfPossibles + T1B2 + T2B1+ B3);
                      break;
             case 2: Toss= FiftyFifty.nextInt(NoOfPossibles-1);
                      if (Toss==0) {
                          if (Choser.get(2)==1) GM.removeT2B1(Pile2CheckIndex);
                          else GM.removeT1B2(Pile2CheckIndex);
                      } //if
                     else {
                         if (Choser.get(0)==1) GM.removeB3(Pile2CheckIndex);
                         else GM.removeT1B2(Pile2CheckIndex);
                     } //else
                     break;
             case 3: Toss= FiftyFifty.nextInt(NoOfPossibles-1);
                     switch (Toss) {
                             case 0: GM.removeB3(Pile2CheckIndex); break;
                             case 1: GM.removeT1B2(Pile2CheckIndex); break;
                             case 2: GM.removeT2B1(Pile2CheckIndex); break;
                             default: P7_FixedElements.abortApplication("Impossible: Toss="+ NoOfPossibles + T1B2 + T2B1+ B3);
                     } // switch Toss
                    break;
                default: P7_FixedElements.abortApplication("Impossible: "+ NoOfPossibles+ " should be up to 3");
              } //switch NoOfPossibles
              if (NoOfPossibles>0)
                  PileToCheck.correctYValues();
        } while (B3 || T1B2 || T2B1); // end do
        P7_FixedElements.D.update();
        return(this);
    } // end method processPiles
    protected P7_GameController processPileClick(Label Source) {
        P7_PlayingCard PC= this.locateCard(Source);
        if (PC==null)
            P7_FixedElements.abortApplication("Could not identify the card from its label...");
        else {
//            System.out.print("Found Card: "); PC.outputP7_PlayingCard(); // DEBUG
            int Row=PC.getRow();
            int Column= PC.getColumn();
            if (Column<0)
                P7_FixedElements.abortApplication("Trying to handle pile click on deck object");
            P7_Pile TempPile= GM.Piles[Column];
            int PileDepth=TempPile.depth();
            if (PileDepth<P7_FixedElements.SUMITEMS) // Pile has less than 3 cards, return
                ;//return(this);
            else if (Row<(PileDepth-3) && Row>1) // do nothing user clicked on card that cannot be part of a calculation
                  ; //return(this);
                 else if (PileDepth==P7_FixedElements.SUMITEMS) { // Pile has exactly 3 cards, so use B3 for any card double click
//                           System.out.println(" Checking B3");
                           if (TempPile.checkForB3Sum()) GM.removeB3(Column); }
                       else if (Row==(PileDepth-3)) {
//                                 System.out.println(" Checking B3");
                                 if (TempPile.checkForB3Sum()) GM.removeB3(Column); }
                              else if (Row==(PileDepth-1) || Row==1) { // user wants to check option T2B1
//                                         System.out.println(" Checking T2B1");
                                         if (TempPile.checkForT2B1Sum()) GM.removeT2B1(Column); }
                                      else if (Row==(PileDepth-2) || Row==0) { // user wants to check option T1B2
//                                              System.out.println(" Checking T1B2");
                                              if (TempPile.checkForT1B2Sum()) GM.removeT1B2(Column);
                                           }
            GV.showDeckAndPile(GM.deck(), TempPile);
        } // end else
        return(this);
    } // end method process pile click
    protected P7_GameController processUserExitRequest() {
        GM.setStopGame(true);
        GM.GS.GameOver=true;
        System.out.println("Goodbye!"); //DEBUG
        return(this);
    } // end method processUserExitRequest
    protected P7_GameController runIt() {   
//        System.out.println("Automated run: "+R); // DEBUG
        if (P7_FixedElements.Autoplay && !GM.GS.StopGame) {
//            System.out.println("Automated dealing ("+R+")"); // DEBUG
            P7_Pile Prev=GM.currentPile();
            this.processDealButton();
            try {
                Thread.sleep(P7_FixedElements.getModel().GS.AutoPlayDelay);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
//                e.printStackTrace();
                GM.GS.StopGame=true;
                return(this);
            }
            this.processPiles(Prev);
            try {
                Thread.sleep(P7_FixedElements.getModel().GS.AutoPlayDelay);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
//                e.printStackTrace();
                GM.GS.StopGame=true;
                return(this);
            }
            int Sh=P7_FixedElements.Generator.nextInt(P7_FixedElements.SUMITEMS+1);
            P7_FixedElements.Shfl.shuffle(Sh);
//            ++R; // DEBUG
        } // end if
        return(this);
    } // end method runIt (for Autoplay)
    protected boolean play() {
        initialSetup();
        GV.showTheWindows();
        GV.updateGraphicalElements();

        boolean Dispatched=false;
        while (GM.getStopGame()==false) {
             Dispatched=P7_FixedElements.D.readAndDispatch();
             if (!Dispatched) {
                 if (P7_FixedElements.Autoplay)
                     this.runIt();
                 else P7_FixedElements.D.sleep();
             }
        } //  end while
        if (P7_FixedElements.D!=null && GM.GS.GameOver!=true) {
            P7_FixedElements.getView().updateGraphicalElements();
            GM.initializeGame();
            P7_FixedElements.getView().updateGraphicalElements();
            GM.setStopGame(false);
            GM.swapDecks();
            if (P7_FixedElements.Autoplay) {
                if (P7_FixedElements.Stats.NumberOfGamesToPlay>0) {
                    GM.subtractGameCounter();
                    if (P7_FixedElements.Stats.NumberOfGamesToPlay==0) {
                        P7_FixedElements.Autoplay=false;
                        P7_FixedElements.AutoPlayB.setSelection(false);
                        P7_FixedElements.Speed.setEnabled(false);
                        P7_FixedElements.NumberOfGamesToPlayT.setText("-1");
                        P7_FixedElements.NewGameB.setEnabled(true);
                        P7_FixedElements.DealB.setEnabled(true);
                        P7_FixedElements.NumberOfGamesToPlayT.setEnabled(true);
                    }
                } // end if
            }
        } // end if
        return(GM.GS.GameOver);
    } // end method play       
} // endclass Controller

/*
* MODEL ---------------------------------------------------------------------------
*
* Every Game has the following objects: 1 Deck , 7 Piles, A set of statistics
* */

class P7_PlayingCard {
    private int Column, Row;
    private MouseAdapter MA;
    private int Points;
    protected static Shell ParentWindow= new Shell();
    protected static MouseAdapter DefaultMouseAdapter= new P7_DeckCardMouseAdapter(); // Set the mouse listener to the default deck handling (i.e. double click deals card)
    protected static MouseAdapter PileMouseAdapter= new P7_PileCardMouseAdapter();
    protected static P7_PlayingCard TempHold= new P7_PlayingCard();
    protected P7_Suit S;
    protected P7_Rank V;
    protected Image Face, Back;
    protected Label Lb;
    protected Point Location;
    protected boolean Visible, Hidden;
    protected P7_PlayingCard() {
            Face=null; Back=null; Lb=null; MA=null;
            S=P7_Suit.Hearts; V=P7_Rank.Ace; Points=0;
            Visible=false; Hidden=false;
            Location= new Point(0,0);
            Column=-1; // -1 signifies the deck, actual column number can be set later
            Row=0; // First row
    } // end default constructor
    protected P7_PlayingCard(P7_Suit Ss, P7_Rank Rr, int PointsValue, Image Front, Image BackDesign) {
        S=Ss;
        V=Rr;
        Points=PointsValue;
        Face= Front;
        Back= BackDesign;
        Location= new Point(0,0);
        Column= -1;  // -1 signifies the deck, actual column number can be set later
        Row=0; // First row
        Visible=true;
        Hidden=false;
        MA= DefaultMouseAdapter;
        Lb= new Label(ParentWindow, SWT.CENTER);
        Lb.setSize(P7_FixedElements.CARDWIDTH, P7_FixedElements.CARDHEIGHT);
        Lb.addMouseListener(MA);
        Lb.setImage(Face);
        Lb.setBackground(P7_FixedElements.GameBackgoundColor);
//        if (hidden()) Lb.setImage(getBack());
//        else Lb.setImage(getFace());
    } // end constructor
    protected P7_PlayingCard assign(P7_PlayingCard Other) { // does not do a deep copy of the images!
        this.S=Other.S;
        this.V=Other.V;
        this.Points=Other.Points;
        this.Face=Other.Face;
        this.Back=Other.Back;
        this.Visible=Other.Visible;
        this.Hidden=Other.Hidden;
        this.Location.x=Other.Location.x;
        this.Location.y=Other.Location.y;
        this.Column=Other.Column;
        this.Row=Other.Row;
        this.Lb=Other.Lb;
        this.MA= Other.MA;
        return(this);
    } // end method assign
    protected P7_PlayingCard copy() {
        P7_PlayingCard New= new P7_PlayingCard();
        New.assign(this);
        return(New);
    } // end method copy
    protected void setSuit(P7_Suit NewS) { S=NewS; }
    protected P7_Suit getSuit() { return(S); }
    protected void setRank(P7_Rank NewV) { V=NewV; }
    protected P7_Rank getRank() { return(V); }
    protected void setPoints(int P) { Points=P; }
    protected int getPoints() { return(Points); }
    protected void setLocation(Point P) { Location.x= P.x; Location.y=P.y;  Lb.setLocation(P); }
    protected Point getLocation() { return(Location); }
    protected P7_PlayingCard setRow(int R) { this.Row=R; return(this); }
    protected int getRow() { return(this.Row); }
    protected P7_PlayingCard setColumn(int C) { this.Column=C; return(this); }
    protected int getColumn() { return(this.Column); }
    protected void setVisible() { Visible=true; }
    protected void setInvisible() { Visible=false; }
    protected boolean isVisible() { return(Visible); }
    protected void setHidden() { Hidden=true; Lb.setImage(Back); }
    protected void setOpen() { Hidden=false; Lb.setImage(Face); }
    protected boolean isHidden() { return(Hidden); }
    protected Image getFace() { return(Face); }
    protected Image getBack() { return(Back); }
    protected Label getLabel() { return(Lb); }
    P7_PlayingCard setLabel(Label L) { Lb=L; return(this); }
    protected P7_PlayingCard lookUpLabel(Label L) {
        if (L==Lb) return(this);
        else return(null);
    } // end method lookUp Label
    protected boolean switchCard(P7_PlayingCard Other) {
        if (this==null || Other == null) return(false);
        TempHold.assign(this);
        this.assign(Other);
        Other.assign(TempHold);
        return(true);
    } // end method switchCard
    P7_PlayingCard setMouseAdapter(MouseAdapter ML) { MA=ML; return(this); } // set what to do on double click
    protected P7_PlayingCard resetMouseAdapter() {
        Lb.removeMouseListener(MA);
        MA=DefaultMouseAdapter;
        Lb.addMouseListener(MA);
        return(this);
    } // set default behaviour i.e. deal card
    protected P7_PlayingCard pileMouseAdapter() {
        Lb.removeMouseListener(MA);
        MA=PileMouseAdapter;
        Lb.addMouseListener(MA);
        return(this);
    } // end method pileMouseAdapter
    protected void outputP7_PlayingCard() {
        System.out.print("["+S+", "+V+"]("+Location.x+", "+Location.y+"), Visible("+
                         Visible+"), Hidden("+Hidden+"), Pile: "+Column+", Row: "+Row+" W:"+ParentWindow+
                         " Face:"+Face+" Back:"+Back);
    } //outputP7_PlayingCard
} // end class P7_PlayingCard

class P7_Pile {
    private int Index=0;
    protected Point Location= new Point(0,0);
    protected LinkedList<P7_PlayingCard> LL = new LinkedList<P7_PlayingCard>();
    protected P7_Pile(Point L, int I) {
        Location.x=L.x; Location.y=L.y;
        Index=I;
    } // end method constructor P7_Pile
    protected void copyListInto(P7_Pile Duplicate, boolean AdvanceY) { // deep copy of cards!
        if (this.isEmpty())
            return;
        else {
            int D=this.depth();
            for (int K=0; K<D; ++K) {
                P7_PlayingCard TPC=(this.LL.get(K)).copy();
                Duplicate.appendCard(TPC, AdvanceY);
            } // end for
        } // end else
    } // end method copyListInto
    protected boolean isEmpty() {    return(LL.isEmpty()); } // has no cards
    protected int depth() { return(LL.size()); }
//    P7_Pile avoid() { Avoid=true; return(this); }
//    P7_Pile engaged() { Avoid=false; return(this); }
    protected void appendCard(P7_PlayingCard PC, boolean AdvanceYPosition) {
/* appending a card to a P7_Pile can either change the cards location or not
* depending on whether we are stacking (i.e. a deck) or spreading the cards to see their faces.
* the AdvanceYPosition flag is used for this descrimination
*/
        Point Pp= new Point(0,0);
        Pp.x=Location.x;
        if (AdvanceYPosition) Pp.y=Location.y+depth()*P7_FixedElements.VISIBLECARDPARTY;
        else Pp.y= Location.y;
        PC.setLocation(Pp);        // Store the card's location in the window
        PC.setRow(LL.size());     // Store the card's Row
        PC.setColumn(this.getIndex());    // Store the card's P7_Pile
        LL.addLast(PC);
    }
    protected P7_PlayingCard getCardFromPosition(int Position) {
        /*
         * Removes the card from the list and returns its reference to the caller.
         * Used when we want to move the card from one cardlist to another.
         */
        return(LL.remove(Position));
    } // removeCard
    protected P7_PlayingCard referenceCard(int Pos) {
        /*
         * Returns a reference of the card to the caller WITHOUT removing it from the list.
         * Used when we want to change some aspect of the P7_PlayingCard in place.
         */
        return(LL.get(Pos));
    } // end method referenceCard
    protected boolean checkForT1B2Sum() {
        if (LL.size()<P7_FixedElements.SUMITEMS) return(false);
        else {
            int C= LL.getFirst().getPoints()+ LL.getLast().getPoints()+ LL.get(LL.size()-2).getPoints();
            if (C==10 || C==20 || C==30) return(true);
            else return(false);
        } //else
    } //checkForT2B1Sum
    protected boolean checkForT2B1Sum() {
        if (LL.size()<P7_FixedElements.SUMITEMS) return(false);
        else {
            int C= LL.getFirst().getPoints()+ LL.getLast().getPoints()+ LL.get(1).getPoints();
            if (C==10 || C==20 || C==30) return(true);
            else return(false);
        }
    } // checkForT2B1Sum
    protected boolean checkForB3Sum() {
            if (LL.size()<P7_FixedElements.SUMITEMS) return(false);
            else {
                int C= LL.getLast().getPoints()+ LL.get(LL.size()-2).getPoints()+ LL.get(LL.size()-3).getPoints();
                if (C==10 || C==20 || C==30) return(true);
                else return(false);
            } //if
    } // checkForB3Sum
    protected void outputPile() {
        System.out.print("Pile: ");
        for (P7_PlayingCard T : LL)
            T.outputP7_PlayingCard();
        System.out.println();
        System.out.println("------");
    } //outputPile
    protected void setLocation(Point P) { Location.x= P.x; Location.y=P.y; }
    protected Point getLocation() { return(Location); }
    protected P7_PlayingCard lookUp(Label Source) {
        int Max=LL.size();
        for (int I=0; I<Max; ++I) {
            P7_PlayingCard Current=LL.get(I);
            if (Current.lookUpLabel(Source)!=null)
                return(Current);
        } // end for
        return(null);
    } // end method lookUp
    protected P7_PlayingCard lookUp(P7_Rank R, P7_Suit S) {
        int I=0; int D=this.depth();
        for (I=0; I<D; ++I) {
            P7_PlayingCard TPC= this.referenceCard(I);
            if (TPC.S==S)
                if (TPC.V==R)
                    return(TPC);
        } // end for
        return(null);
    } // end lookup find card based on values
    protected int getIndex() { return(Index); }
    protected void swap(int I, int J) {
        P7_PlayingCard T1= LL.get(I);
        P7_PlayingCard T2= LL.get(J);
        T1.switchCard(T2);
    } // end method swap list locations
    protected void correctYValues() { // After a change in a pile, put the proper x,y to the cards and the correct row.
        int I=this.depth();
        if (I==0) return;
        P7_PlayingCard CrRf;
        int J;
        if (I<P7_FixedElements.MAXNONSTACKEDCARDS) {
            Point T= new Point(this.Location.x,this.Location.y);
            for (J=0; J<I; ++J) {
                CrRf=referenceCard(J);   
                CrRf.setRow(J); // set proper row values
                T.y=this.Location.y+P7_FixedElements.VISIBLECARDPARTY*J;
                CrRf.setLocation(T);
                CrRf.setOpen();
            } // for
        } // end if no need to stack
        else {
            Point T= new Point(this.Location.x, this.Location.y);
            //+P7_FixedElements.VISIBLECARDPARTY*(P7_FixedElements.TOPCARDSTODISPLAY+1));
            for (J=0; J<P7_FixedElements.TOPCARDSTODISPLAY; ++J) {
                CrRf=referenceCard(J);
                CrRf.setRow(J);
                T.y=this.Location.y+P7_FixedElements.VISIBLECARDPARTY*J;
                CrRf.setOpen();
                CrRf.setLocation(T);
            } // end for top cards
            T.y=this.Location.y+P7_FixedElements.VISIBLECARDPARTY*(P7_FixedElements.TOPCARDSTODISPLAY);
            for (J=P7_FixedElements.TOPCARDSTODISPLAY; J<I-P7_FixedElements.BOTTOMCARDSTODISPLAY; ++J) {
                CrRf=referenceCard(J);
                CrRf.setRow(J);
                CrRf.setHidden();
                CrRf.setLocation(T);
            } // end for J
            T.y=T.y+P7_FixedElements.VISIBLECARDPARTY;
            for (J=I-P7_FixedElements.BOTTOMCARDSTODISPLAY;
                 /* T.y=this.Location.y+P7_FixedElements.VISIBLECARDPARTY*(Rebase+P7_FixedElements.TOPCARDSTODISPLAY) */
                 J<I;
                 ++J, T.y=T.y+P7_FixedElements.VISIBLECARDPARTY) {
                CrRf=referenceCard(J);
                CrRf.setRow(J);
                CrRf.setOpen();
                CrRf.setLocation(T);
            } // end for the low cards
//            System.out.println("Deck ("+Location.x+", "+Location.y+") CardY("+T.y+") "); // DEBUG
        } // end need to stack
    } // end method correctPileYValues
} // end class Pile

class P7_PileIterator {
    private int CurrentPile=0;
    private int equate(P7_PileIterator A) { CurrentPile=A.CurrentPile; return(CurrentPile); }
    private int equate(int A){
        if (A<0) CurrentPile=0;
        else if (A>=P7_FixedElements.NUMBEROFPILES)
            CurrentPile=P7_FixedElements.NUMBEROFPILES-1;
        else CurrentPile=A;
        return(CurrentPile);
    }
    protected P7_PileIterator() { CurrentPile=0; }
    protected P7_PileIterator(P7_PileIterator A) { CurrentPile=A.CurrentPile; }
    protected int reset() { CurrentPile=0;  return(CurrentPile); }
    protected int first() { return(reset()); }
    protected int last() { CurrentPile=P7_FixedElements.NUMBEROFPILES-1; return(CurrentPile); }
    protected int current() { return(CurrentPile); }
    protected int next() {
        int T= CurrentPile+1;
        if (T==P7_FixedElements.NUMBEROFPILES) return(0);
        else return(T);
    } // end method next
    protected int previous() {
        int T=CurrentPile-1;
        if ((T)<0) return(P7_FixedElements.NUMBEROFPILES-1);
        else return(T);
    } // previous
    protected void gotoNextPile() {
        ++CurrentPile;
        if (CurrentPile==P7_FixedElements.NUMBEROFPILES)
            CurrentPile=0;
    } // end method gotoNextPile
    protected void gotoPreviousPile() {
        --CurrentPile;
        if (CurrentPile<0)
            CurrentPile=P7_FixedElements.NUMBEROFPILES-1;
    } // end method gotoPreviousPile
} // end class P7_PileIterator

class P7_PlayingDeck extends P7_Pile {
    protected P7_PlayingDeck(Point L, boolean ForCopy) { // constructor
        super(L, -1);
        super.Location= new Point(0,0);
        Location.x=L.x; Location.y=L.y;
        if (ForCopy)
            return;
        String FileName=null, FinalPrefix, CardBackFileName;
        FileInputStream fis;
//        String Prefix[]= { "bin\\resources\\10", "bin\\resources\\1" };
        System.out.println("Loading card images."); // DEBUG
        Point CardLocation= new Point(0,0);
        Image Face, CardBack;
        if (P7_FixedElements.WindowsOS) {
            P7_FixedElements.CardImageFilePrefix[0]=P7_FixedElements.CardImageFilePrefixWindows[0];
            P7_FixedElements.CardImageFilePrefix[1]=P7_FixedElements.CardImageFilePrefixWindows[1];
        } else {
            P7_FixedElements.CardImageFilePrefix[0]=P7_FixedElements.CardImageFilePrefixUnix[0];
            P7_FixedElements.CardImageFilePrefix[1]=P7_FixedElements.CardImageFilePrefixUnix[1];
        } // end else
        CardBackFileName=P7_FixedElements.CardImageFilePrefix[1]+"55"+P7_FixedElements.CARDFILENAMEEXTENSION;
        int II=0;
        for (P7_Suit suit : P7_Suit.values())
             for (P7_Rank rank : P7_Rank.values()) {
                 if (II<9) FinalPrefix=P7_FixedElements.CardImageFilePrefix[0];
                 else FinalPrefix=P7_FixedElements.CardImageFilePrefix[1];
                 FileName= FinalPrefix+Integer.toString(II+1)+P7_FixedElements.CARDFILENAMEEXTENSION;
                 try {
//                     System.out.println("Working Directory is: "+System.getProperty("user.dir")+" Card Filename: "+FileName); //DEBUG
                     fis = new FileInputStream(FileName);
                     Face= new Image(P7_FixedElements.D, FileName);
                    fis = new FileInputStream(CardBackFileName);
                    CardBack= new Image(P7_FixedElements.D, CardBackFileName); // for double click to work, I have to have a listener!
                    P7_PlayingCard TempCard=new P7_PlayingCard(suit, rank, lookupValue(rank), Face, CardBack);
                    CardLocation.x=Location.x;
                    CardLocation.y=P7_FixedElements.PILEORIGINY; // Location.y+P7_FixedElements.VISIBLECARDPARTY*II;
//                    System.out.println("Card location is:"+CardLocation.x+":"+CardLocation.y); 
                    TempCard.setLocation(CardLocation);
                    TempCard.setHidden();
                    this.appendCard(TempCard, P7_FixedElements.KEEPYPOSITION);
                } // end try
                 catch (FileNotFoundException ex) {
                     P7_FixedElements.abortApplication("Card Image File: "+FileName+" not found. Abrupt end of program!");
                 } // end catch
                ++II;
             } // for Rank
            System.out.println("Done Loading card images."); // DEBUG
//            P7_FixedElements.pressAnyKey(); //DEBUG
    } //end constructor
    protected P7_PlayingDeck copy() {
        P7_PlayingDeck TPD=new P7_PlayingDeck(this.Location, true);
        copyListInto(TPD, P7_FixedElements.KEEPYPOSITION);
        return(TPD);
    } // end method copy deck
    protected P7_PlayingDeck resetCardsLocation() {
        Point P= new Point(Location.x, Location.y);
        P7_PlayingCard TempC;
        int D=this.depth();
        for (int Index=0; Index<D; ++Index) {
            TempC=this.referenceCard(Index);
            TempC.setHidden();
            TempC.setLocation(P);
        } // end for
        return(this);
    }
    protected P7_PlayingDeck shuffle(int Times) {
        int FirstCardLocation, SecondCardLocation, I;
        if (Times<0) {
            long StartTime= System.currentTimeMillis();
            System.out.println("First Time Shuffling..."); // DEBUG
            while (System.currentTimeMillis()< (StartTime+P7_FixedElements.SUFFLINGTIME)) {
                FirstCardLocation= (P7_FixedElements.Generator.nextInt(P7_FixedElements.NUMBEROFCARDSINDECK));
                SecondCardLocation= (P7_FixedElements.Generator.nextInt(P7_FixedElements.NUMBEROFCARDSINDECK));
                swap(FirstCardLocation, SecondCardLocation);
//                P7_FixedElements.getView().displayCards();
            } //while
    /*        System.out.println("Finished Shuffling");
            Print the shuffled Deck
            for (int i=0; i<P7_FixedElements.NUMBEROFCARDSINDECK; ++i) {
                LL.get(i).outputP7_PlayingCard();
                System.out.println("["+i+"], Deck Depth: "+LL.size());
            } // for
*/        } else {
            for (I=0; I<Times; ++I) {
                FirstCardLocation= (P7_FixedElements.Generator.nextInt(P7_FixedElements.NUMBEROFCARDSINDECK));
                SecondCardLocation= (P7_FixedElements.Generator.nextInt(P7_FixedElements.NUMBEROFCARDSINDECK));
                swap(FirstCardLocation, SecondCardLocation);
//                if (Ret<30) { ++Ret; System.out.print(">"); }  // DEBUG
//                else { Ret=0; System.out.println("."); } // DEBUG
//                P7_FixedElements.getView().displayCards();
            } // end for
        } // end else
        return(this);
    } //shuffle
    protected P7_PlayingCard deal() {
        if (LL.isEmpty()) {
            System.out.println("cannot deal, deck is empty... check for deck size before calling.. Aborting Application");
            System.exit(0);
        } // if
        P7_PlayingCard X=LL.pop();
        return(X);
    } //deal
    protected boolean deckIsHealthy() {
        for (P7_Suit suit : P7_Suit.values())
             for (P7_Rank rank : P7_Rank.values()) {
                 P7_PlayingCard Tt= lookUp(rank, suit);
                 if (Tt==null) return(false);
             }
        return(true);
    } // end method deckIsHealthy
    protected static int lookupValue(P7_Rank R)    {
        switch (R) {
        case Ace: return(P7_FixedElements.CardPoints[0]);
        case Two: return(P7_FixedElements.CardPoints[1]);
        case Three: return(P7_FixedElements.CardPoints[2]);
        case Four: return(P7_FixedElements.CardPoints[3]);
        case Five: return(P7_FixedElements.CardPoints[4]);
        case Six: return(P7_FixedElements.CardPoints[5]);
        case Seven: return(P7_FixedElements.CardPoints[6]);
        case Eight: return(P7_FixedElements.CardPoints[7]);
        case Nine: return(P7_FixedElements.CardPoints[8]);
        case Ten: return(P7_FixedElements.CardPoints[9]);
        case Jack:  return(P7_FixedElements.CardPoints[10]);
        case Queen: return(P7_FixedElements.CardPoints[11]);
        case King: return(P7_FixedElements.CardPoints[12]);
        default: P7_FixedElements.abortApplication("Could not locate rank in point lookup... Serious error!");
        } //switch
        return(0);
    } //lookup

} //class P7_PlayingDeck

class P7_GameState {
    protected boolean StopGame;
    protected boolean GameOver;
    protected int AutoPlayDelay;
    protected P7_PileIterator CurrentPile;
    protected P7_GameState() {
        StopGame=false;
        GameOver=false;
//        NumberOfGamesToPlay=-1;
        CurrentPile= new P7_PileIterator();
        AutoPlayDelay=0; // max speed
    } // end constructor P7_GameState
} //end class P7_GameState

class P7_GameModel {
    protected P7_GameState GS;
    protected P7_Pile[] Piles;
    protected P7_GameModel(P7_FixedElements FEs) {
        GS= new P7_GameState();
//        FEls=FEs;
        Piles= new P7_Pile[P7_FixedElements.NUMBEROFPILES];
        int X=P7_FixedElements.PILEORIGINX, Y=P7_FixedElements.PILEORIGINY;
        for (int C=0; C<P7_FixedElements.NUMBEROFPILES; ++C) {
            Point L=new Point(X, Y);
            Piles[C]= new P7_Pile(L, C);
            X=X+P7_FixedElements.BORDERSIZE+P7_FixedElements.CARDWIDTH;
        } // end for
    } // end constructor Game
    protected int numberOfCardsInDeck() { return(P7_FixedElements.PlDk.depth()); }
    private P7_GameModel returnAllCardsToTheDeck() {
//        System.out.println("Start: Return cards to the deck --> "); // DEBUG
        P7_PlayingCard TempCard;
        for (int P=0; P<P7_FixedElements.NUMBEROFPILES; ++P) {
//            System.out.println("Pile is ["+P+"]"); // DEBUG
            while (!Piles[P].isEmpty()) {
                TempCard=Piles[P].getCardFromPosition(0);
                TempCard.setLocation(P7_FixedElements.Ll);
                TempCard.setHidden();
                TempCard.resetMouseAdapter();
                P7_FixedElements.PlDk.appendCard(TempCard, false);
            } // end while
        } // end for P
//        System.out.println("All cards back in the playing deck. Size is again: "+P7_FixedElements.PlDk.depth()+
//                           " Shadow Deck ["+P7_FixedElements.Shfl.depth()+"]"); // DEBUG
//        System.out.println("Playing deck health: "+P7_FixedElements.PlDk.deckIsHealthy()); //P7_FixedElements.PlDk.outputPile();
//        System.out.println("Shuffle deck health: "+P7_FixedElements.Shfl.deckIsHealthy()); //P7_FixedElements.Shfl.outputPile();
        return(this);
    } // end method returnAllCardsToTheDeck
    protected P7_GameModel initializeGame() {
        returnAllCardsToTheDeck();
        GS.StopGame=false;
        GS.CurrentPile.reset();
        GS.GameOver=false;
        return(this);
    }
    protected P7_GameModel subtractGameCounter() {
        --P7_FixedElements.Stats.NumberOfGamesToPlay;
        P7_FixedElements.NumberOfGamesToPlayT.setText(Long.toString(P7_FixedElements.Stats.NumberOfGamesToPlay));
        return(this);
    }
    protected P7_PlayingDeck deck() { return(P7_FixedElements.PlDk); }
    protected P7_Pile currentPile() { return(Piles[GS.CurrentPile.current()]); }
    protected int currentPileNo() { return(GS.CurrentPile.current()); }
    protected void setStopGame(boolean B) { GS.StopGame=B;    } // end method setStopGame
    protected boolean getStopGame() {    return(GS.StopGame); } // end method getStopGame
    protected boolean areAllPilesEmpty() { // Check for win
        for (int C=0; C<P7_FixedElements.NUMBEROFPILES; ++C) {
            if (Piles[C].isEmpty()==false)
                return(false);
        } //endfor
        this.processSuccess();
        return(true);
    } //end of areAllPilesEmpty
    protected P7_GameModel processSuccess() { ++P7_FixedElements.Stats.Successes; ++P7_FixedElements.Stats.GamesPlayed; return(this); }
    protected P7_GameModel processFailure() { ++P7_FixedElements.Stats.Failures; ++P7_FixedElements.Stats.GamesPlayed; return(this); }
    protected P7_GameModel fromPile2Deck(P7_PlayingCard PC, boolean MoveCardsYLocation) {
        PC.setHidden();
        PC.resetMouseAdapter();        // going back to the deck so set the double click to deck handling
        P7_FixedElements.PlDk.appendCard(PC, MoveCardsYLocation);
        return(this);
    } // end method fromPile2Deck
    protected P7_GameModel removeB3(int PileI) { // Case of 3 bottom cards
        P7_Pile CurrentPile=Piles[PileI];
        P7_PlayingCard PC=CurrentPile.getCardFromPosition(CurrentPile.depth()-3);
        fromPile2Deck(PC, P7_FixedElements.KEEPYPOSITION);
        PC=CurrentPile.getCardFromPosition(CurrentPile.depth()-2);
        fromPile2Deck(PC, P7_FixedElements.KEEPYPOSITION);
        PC=CurrentPile.getCardFromPosition(CurrentPile.depth()-1);
        fromPile2Deck(PC, P7_FixedElements.KEEPYPOSITION);
        return(this);
    } //removeB3
    protected P7_GameModel removeB3(P7_PileIterator Pi) { // Case of 3 bottom cards
        int J=Pi.current();
        return(removeB3(J));
    } //removeB3
    protected P7_GameModel removeT1B2(int PileI) { // Case of 1 top and 2 bottom cards
        P7_Pile CurrentPile=Piles[PileI];

        P7_PlayingCard PC=CurrentPile.getCardFromPosition(CurrentPile.depth()-2);       
        fromPile2Deck(PC, P7_FixedElements.KEEPYPOSITION);
        PC=CurrentPile.getCardFromPosition(CurrentPile.depth()-1);
        fromPile2Deck(PC, P7_FixedElements.KEEPYPOSITION);
        PC=CurrentPile.getCardFromPosition(0);
        fromPile2Deck(PC, P7_FixedElements.KEEPYPOSITION);
        return(this);
    } //removeT1B2
    protected P7_GameModel removeT1B2(P7_PileIterator Pi) { // Case of 1 top and 2 bottom cards
        int J=Pi.current();
        return(removeT1B2(J));
    } //removeT1B2
    protected P7_GameModel removeT2B1(int PileI) { // Case of 2 top and 1 bottom card
        P7_Pile CurrentPile=Piles[PileI];

        P7_PlayingCard PC=CurrentPile.getCardFromPosition(CurrentPile.depth()-1);
        fromPile2Deck(PC, P7_FixedElements.KEEPYPOSITION);
        PC=CurrentPile.getCardFromPosition(0);
        fromPile2Deck(PC, P7_FixedElements.KEEPYPOSITION);
        PC=CurrentPile.getCardFromPosition(0);
        fromPile2Deck(PC, P7_FixedElements.KEEPYPOSITION);
        return(this);
    } //removeT2B1
    protected P7_GameModel removeT2B1(P7_PileIterator Pi) { // Case of 2 top and 1 bottom card
        int J=Pi.current();
        return(removeT2B1(J));
    } //removeT2B1
    protected boolean deal2Pile() {
        if (areAllPilesEmpty()) { // Do not deal anything, game is over, user has won
//            this.processSuccess(); this is done in areAllPilesEmpty, no need to do it here
            return(false); // game is over
        }
        // There are still cards in piles continue with dealing
        if (P7_FixedElements.PlDk.depth()>0) { // Still have cards to deal, game is continuing
            P7_PlayingCard Card= P7_FixedElements.PlDk.deal();
            Card.setOpen();            // Make sure card is face up
            Card.pileMouseAdapter();    // Set the mouse adapter of the card to handle pile double clicks instead of deck double clicks
            Piles[GS.CurrentPile.current()].appendCard(Card, P7_FixedElements.ADVANCEYPOSITION);
            // move deal focus to next non empty pile
            if (findNextValidPile())
                return(true); // everything OK, move dealing point to the next valid pile
            else {
                P7_FixedElements.abortApplication("Should never have reached this! method(deal) class(P7_GameModel)");
                return(false);
            } // end else
        } //endif
        else  { // No more cards, everything is on the piles, user has lost
            this.processFailure();
            return(false);
        } // end else game over, user lost
    } // end method deal
    protected boolean findNextValidPile() {
        GS.CurrentPile.gotoNextPile();
        int Count=0;
        while (Piles[GS.CurrentPile.current()].isEmpty() && Count<P7_FixedElements.NUMBEROFPILES) {
            ++Count;
            GS.CurrentPile.gotoNextPile();
        } // end while
        if (Count>=P7_FixedElements.NUMBEROFPILES) return(false);
        return(true);
    } // end method findNextValidPile
    protected P7_GameModel swapDecks() {
        P7_PlayingDeck TPD;
        TPD=P7_FixedElements.PlDk;
        P7_FixedElements.PlDk=P7_FixedElements.Shfl;
        P7_FixedElements.Shfl=TPD;
        return(this);
    } // end method swapDecks
} // endclass P7_GameModel

public class PatienJava {
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        P7_FixedElements Konsts= new P7_FixedElements(); // must create this in order to initialize stuff before anything else
        P7_GameModel M= new P7_GameModel(Konsts);
        P7_GameView V= new P7_GameView(M);
        P7_GameController C= new P7_GameController(Konsts, V, M);
        Konsts.setGameMVC(M, V, C);
        boolean Continue=true;
        while (Continue) {
            Continue=!C.play(); // returns GameOver flag if true the user wants to exit, false if he wants to continue
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } // end while       
        P7_FixedElements.D.dispose();
    } // end main()
} ///endclass PatientzaJ

/////////////////////////////////////////////////////////
// Bare Bones Browser Launch //
// Version 2.0 (May 26, 2009) //
// By Dem Pilafian //
// Supports: //
// Mac OS X, GNU/Linux, Unix, Windows XP/Vista //
// Example Usage: //
// String url = "
http://www.centerkey.com/"; //
// BareBonesBrowserLaunch.openURL(url); //
// Public Domain Software -- Free to Use as You Like //
/////////////////////////////////////////////////////////
class BareBonesBrowserLaunch {
    protected static final String[] browsers = { "firefox", "opera", "konqueror", "epiphany", "seamonkey", "galeon", "kazehakase", "mozilla", "netscape" };
    protected static void openURL(String url) {
        String osName = System.getProperty("os.name");
        try {
            if (osName.startsWith("Mac OS")) {
                Class<?> fileMgr = Class.forName("com.apple.eio.FileManager");
                Method openURL = fileMgr.getDeclaredMethod("openURL", new Class[] {String.class});
                openURL.invoke(null, new Object[] {url});
            } else if (osName.startsWith("Windows"))
                    Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + url);
                    else { //assume Unix or Linux
                            boolean found = false;
                            for (String browser : browsers)
                                if (!found) {
                                    found = Runtime.getRuntime().exec( new String[] {
                                            "which", browser}).waitFor() == 0;
                                            if (found) Runtime.getRuntime().exec(new String[] {
                                                    browser, url});
                                }
                            if (!found) throw new Exception(Arrays.toString(browsers));
                         } // end else
        } //end try
        catch (Exception e) {
            JOptionPane.showMessageDialog(null, "Error attempting to launch web browser\n" + e.toString());
        } // end catch
    } // end openURL
}  // end BareBonesBrowserLaunch

1 comment:

  1. very interesting your reference to Alexander's "growing" approach to coding. Looking fwd to more posts!

    ReplyDelete