/*******************************************************************

    This class is a catch-all for utilities relating to the boards.

    These are generally short routines that do simple things.


    We generally do not pass in array bounds in Java, who knows these,

    but often we do not want to mess with the edges of the boards,

    as these are always zero ("dead"), or even waste CPU time on them.

******************************************************************** */


import java.awt.*;


final class BoardUtilities implements Constants, Strings

{

    private PopupWindow error;   // For exceptions.


/*******************************************************************

    Constructor follows:

******************************************************************** */      


    BoardUtilities(Frame parentFrame, ScreenLocations screenLocations)

    {

        String errorString = ((parentFrame != null) && (screenLocations != null)) ? 

                             NULL_STRING : "parentFrame = " + parentFrame +

                             " screenLocations = " + screenLocations;

        if (!errorString.equals(NULL_STRING))

        {

            System.out.println("error, null pointer, BoardUtilities " + errorString);

            return;

        }

        error = new PopupWindow(parentFrame, screenLocations, ERROR_WINDOW_NAME);

    }


/* ******************************************************************

    Next sets two boards equal to each other.

********************************************************************* */ 


    protected final void SetFirstToSecond(int [][] first, int [][] second, int rows, int columns)

    {

        int i = 0;

        int j = 0;    // Loop variables.


        try // Array bounds error happen. We are careful.

    

        // Note we don't care about the edges. Thus we pass in 

        // bounds -- don't waste CPU time on the edges.

        {

            for (i=1; i <= rows; i++)

            {

                for (j=1; j <= columns; j++)

                {

                    first[i][j] = second[i][j];

                }                   // End j - loop

            }                       // End i - loop

        }

        catch (ArrayIndexOutOfBoundsException e) // Array index out of

                                                 // bounds!?

        {

            String errorStr = e.getMessage();


            errorStr = errorStr + 

            

            

            ARRAY_BOUNDS_EXCEPTION + " SetAToB, object " +

                                  "BoardUtilities: rows = " + rows + 

                                  ", columns = " + columns +

                                  ", i = " + i + ", and j = " + j;

            error.ShowMessage(errorStr, OK);

        }

    }


/* ******************************************************************

    Tells the caller if any cell is alive; "true" means "someone is

    alive," "false" means "all dead."

********************************************************************* */ 


    protected final boolean Alive(int[][] board, int rows, int columns)

    {

        int i = 0;  // Avoid "may not have been initialized"

        int j = 0;  // errors in try-catch clause.


        boolean alive = false; // Assume everyone is dead initially.


          try     // We are careful.

        {

            // Note we don't care about the edges. Thus we pass in

            // bounds -- don't waste CPU time on the edges.


            iLoop: for (i = 1; i <= rows; i++)

            {

                for(j = 1; j <= columns; j++)

                {

                    if (board[i][j] == 1)

                    {

                        return true;   // Someone is alive. Get out.

                    }

                }

            }

        }

        catch (ArrayIndexOutOfBoundsException e)    // Array index out

                                                    // of bounds!?

        {

            String errorStr = e.getMessage();


            errorStr = errorStr + " " + ARRAY_BOUNDS_EXCEPTION + " routine " +

                                  "Alive: ROWS = " + rows + 

                        ", COLUMNS = " + columns +

                        ", i = " + i + ", and j = " + j;

            error.ShowMessage(errorStr, OK);

        }

        return(alive);

    }


/*******************************************************************

    The next takes indices of a given cell, and tells the caller if

    the cell will be alive in the next generation; the return is an

    int, *not* a boolean, as the board contains integers (1 = alive;

    0 = dead).


    This routine gets called an awful lot: once for every cell, every

    generation. It is also called when we paint the board, to find if

    a given cell is alive in the next generation or not.


    Hence the code is not "pretty" -- I am maximizing speed.

******************************************************************** */


    protected final boolean AliveInNext(int [][] board, int i, int j)

    {

    switch(board[i-1][j-1] + board[i-1][j]    + board[i-1][j+1] + // row below

           board[i]  [j-1] + /* Cell here! */   board[i]  [j+1] + // same row

           board[i+1][j-1] + board[i+1][j]    + board[i+1][j+1]) // row above

        {

        case 0:       // Here the next generation's (i, j) spot is dead

        case 1:       // due to either loneliness (zero or one)

        case 4:       // or overcrowding (four --> eight); whether it

        case 5:       // was alive or not in the first place doesn't

        case 6:       // here matter.

        case 7:

        case 8: {

                return false;  // Dead in the next generation.

                }

        case 2: {

                return (board[i][j] == 1); // If alive, stays alive.

                                           // If dead, remains dead.

                }

        case 3: {             // If board[i][j] is dead, it comes to life.

                return true; // If board[i][j] is alive, it remains alive.

                }             // We follow with an exception routine. This

                            // should *never* execute.

        default: 

                {

                int neighbors = board[i-1][j-1] + board[i-1][j] + board[i-1][j+1]+ 

                                board[i]  [j-1] + board[i]  [j+1] +

                                board[i+1][j-1] + board[i+1][j] + board[i+1][j+1];

           

                error.ShowMessage(UNRECOVERABLE_ERROR + " board[" + i + ", " +

                            j + "] + HAS + " + neighbors + " " + LIVING_NEIGHBORS, 

                            OK);   // Button.

                return false;

             }

        }                  // End of < switch > statement.

    }                       // End of routine AliveInNext

}   // End of class BoardUtilities