C:\upload\java\Life\source\java\HandleGamesEnd.java
/*******************************************************************
    This class is called when a game is over. Keep playing?
******************************************************************** */

import java.awt.*;
 
final class HandleGamesEnd implements Constants, Strings
{
    private Objects objects;
    private boolean gameChanged; /* This boolean tells the caller: if we decide
                                    to play again, do we change game settings.
                                 */
    private PopupWindow anotherGame, error; /* First asks, "Play again?",
                                               second is for errors that should
                                               not happen. */

/*******************************************************************
    Constructor follows:
******************************************************************** */

    HandleGamesEnd(Objects objects)
    {
        String errorString = (objects != null) ? 
                             NULL_STRING : "objects = " + objects;
        if (!errorString.equals(NULL_STRING))
        {
            System.out.println("Error, null pointer, HandleGamesEnd " + 
                                errorString);
            return;
        }
        this.objects = objects;

        // Question screen, "Do you wish to keep playing?"
        anotherGame = new PopupWindow(objects.GetParentFrame(),
                                      objects.GetScreenLocations(),
                                      KEEP_PLAYING_STRING);

        // For errors:
        error       = new PopupWindow(objects.GetParentFrame(),
                                      objects.GetScreenLocations(),
                                      ERROR_WINDOW_NAME);

        gameChanged = false; // At outset assume no changes.
    }

/* ******************************************************************
    Keep playing?

    Note this is overloaded.  The user may quit an initial game prior to the
    instantiation of 
    < HandleASingleGeneration singleGenerationThread > in the main code.
   ******************************************************************** */

/* ******************************************************************
    First version: before <HandleASingleGeneration singleGenerationThread >
    has been instantiated in the main code.
   ******************************************************************** */

    protected final boolean PlayAgain(int numberOfGames)
    {
        return playAgain(null, numberOfGames);  // "Compute next generation"
                                                // thread is null.
    }

/* ******************************************************************
    Next is overloaded: after <HandleASingleGeneration singleGenerationThread >
    has been instantiated in the main code.
   ******************************************************************** */

    protected final boolean PlayAgain(HandleASingleGeneration singleGenerationThread,
                                      int numberOfGames)
    {
        return playAgain(singleGenerationThread, numberOfGames);
    }

/* ******************************************************************
    Keep playing? The next utility routine does the real work.
   ******************************************************************** */

    private final boolean playAgain(HandleASingleGeneration singleGenerationThread,
                                    int numberOfGames)
    {
        String messageWhenTheGameIsOver = "";   /* Message when either all
                                                   are dead or the pattern repeats.
                                                   If we don't intialize it, we get
                                                   "may not have been initialized" 
                                                   compilation errors.
                                                */
        boolean playAgain;          // What we return.

        // Do we keep playing? Make and display the question:
        try
        {
            /* Explanation of below: if when seeing the first board, the user
               decides it's so horrible to quit the game from the outset, the
               parameter < singleGenerationThread > hasn't been instantiated yet
               in the main code. We have to pass something to this routine, so
               pass < null >. Thus the check.
            */
            if ((!objects.GetButtons().GetQuitButtonClicked()) && 
                (singleGenerationThread != null))                /* User didn't
                                                  quit. Game ended "naturally."
                                                  Get the how it ended from 
                                                  the thread 
                                                 < singleGenerationThread >. */
            {
                messageWhenTheGameIsOver = 
                        singleGenerationThread.GetGameEndString();
            }
            else    // User wanted out, or a parameter was nonsense.
            {
                messageWhenTheGameIsOver = GAME_STOPPED;  // User asked out.
            }
        }
        catch (NullPointerException e)  // Pointer null?!?!
        {
            error.ShowMessage(POINTER_NULL + " < singleGenerationThread > " +
                              IN + " < HandleGamesEnd playAgain() >?!?!", 
                              OK);              // Button
        }
        String [] msStr = {
                            messageWhenTheGameIsOver,
                            DO_YOU_WISH_TO_PLAY_GAME + 
                            (numberOfGames + 1) + "?"
                          };
        String [] questions = {YES_WITH_NO_MODIFICATIONS, 
                                YES_WITH_MODIFICATIONS, NO};

        anotherGame.ShowMessage(msStr,         // Ask: keep going?
                                questions);     /* We have the choice
                                                   of playing with no modifications,
                                                   with modifications, or not playing
                                                   again: see above < String [] buttons >.
                                                */
            // Was the answer "no?"
                            
        if (anotherGame.WhichButtonWasPressed().equals(NO))
        {
            playAgain = false;  // Get out.
        }
        // "Yes," but change settings from last game?

        else if (anotherGame.WhichButtonWasPressed().equals
                        (YES_WITH_MODIFICATIONS))
        {
            playAgain   = true;
            gameChanged = true;
        }
        // "Yes," no modifications from last game?

        else if (anotherGame.WhichButtonWasPressed().equals
                    (YES_WITH_NO_MODIFICATIONS))
        {
            /* We will keep all values. Re-setting them again 
                is a waste of CPU time, but this is small. 
            */
            playAgain   = true;
            gameChanged = false;
        }
        else    // Nonsense. We don't recognize the button? This shouldn't happen.
        {
            playAgain = false;
            error.ShowMessage("UNRECOGNIZED_BUTTON " + " " + IN + " " +
                              "< HandleGamesEnd anotherGame >.", 
                                OK);  // Button.
        }
        return(playAgain);
    }                   // End of routine < PlayAgain >.

/*******************************************************************
     Is the game to change from last?
******************************************************************** */

   protected final boolean GameChanged()
   {
        return (gameChanged);
   }
}       // End class < HandleGamesEnd >.