C:\upload\java\Life\source\java\RepeatPattern.java
/*******************************************************************
   This class, *RepeatPattern*, has a routine < DoesThePatternRepeat >
   which compares the present board with the boards of as far as 
   NUMBER_OF_OLDBOARDS generations ago to see if they are the same. If
   so, it returns true, otherwise false.

   This class has two routines: one to determine if we are in a repeating
   pattern, and another to set up the graphics telling the user that we
   are in a repeating pattern.
******************************************************************** */

import java.awt.Graphics;
import java.awt.*;
import java.awt.event.*;

final class RepeatPattern implements Constants, Strings
{
    private Vars vars;
    private int period; /* When a repeating pattern is
                           found, this will hold the
                           period of the pattern. 
                        */
    private PopupWindow error;   // For exceptions.

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

    RepeatPattern(Frame parentFrame, Objects objects)
    {
        String errorString = ((parentFrame != null) && 
                              (objects != null)) ? 
                             NULL_STRING : "parentFrame = " + parentFrame +
                             " objects = " + objects;
        if (!errorString.equals(NULL_STRING))
        {
            System.out.println("Error, null pointer, RepeatPattern " 
                              + errorString);
            return;
        }
        this.vars = vars;
        error = new PopupWindow(parentFrame, objects.GetScreenLocations(), ERROR_WINDOW_NAME);

        period = PATTERN_DOES_NOT_REPEAT; // If used, it will change.
    }

/*******************************************************************
   The next boolean function, < DoesThePatternRepeat >, compares 
   the present board with the boards of as far as NUMBER_OF_OLDBOARDS
   generations ago to see if they are the same. If so, it returns a 
   "true"; if not, a "false."

   Because of the modular arithmetic, this is one of the
   harder-to-understand routines. Read carefully. 
******************************************************************** */

    protected final boolean DoesThePatternRepeat(int [][][] oldBoards,
                                                 int [][] currentBoard,
                                                 int generation,
                                                 int rows,
                                                 int columns)
    {
        period = PATTERN_DOES_NOT_REPEAT; // If used, will change.

        int i, j, k;   /* Loop variables. We need three of them, as
                         < k > will loop through old boards stored in
                          the array < oldboards >, and the others will
                          loop through < currentBoard > comparing it to the current
                          old board under consideration.
                       */
        i = j = k = 0;  /* Avoid "not initialized" hassles
                           with the below try-catch clause.
                        */

        boolean repeat = true; /* What we ultimately return.
                                  Avoid "not initialized" hassles
                                  with the below try-catch clause.
                               */
    /* We loop on kIndex (see k) through all
       the old boards  stored in the 3-D array  */

        int kIndex = 0; /* The loop really goes from 
                           1 -- 99, then 0. See below note.
                        */
        try // We are referencing several arrays. Be careful.

        {               // Note below test!
                        //       ||
                        //       ||
                        //       \/
            kLoop: for (k = 1; k <= oldBoards.length; k++)// See next comment.

            /* Note loop goes to oldboards.length. This seemingly obvious
               "Programming 101" error is no error at all: we do not use
               k for oldboard's index; we use < kIndex > and
               oldboards.length will become kIndex = 0 (zero) (see next line). */
            {
            kIndex = k % oldBoards.length;/* See above comment on the 
                                             "Programming 101" error.   */

            repeat = true;       // Assume the pattern repeats. Set 
                                 // false if no match 
                                 // in oldboards[k][][].

            iLoop: for (i = 1; i  <= rows; i++)   // Loop starts at 1.
                {
                    for (j = 1; j <= columns; j++)   // Loop starts at 1.
                    {
                    if (oldBoards[kIndex][i][j] != currentBoard[i][j])// Difference?
                        {
                            repeat = false; /* We initially assume the 
                                               pattern repeating. We
                                               have found a difference.
                                            */
                            break iLoop;    /* Doesn't repeat. Don't
                                               waste CPU time going 
                                               further.
                                            */
                        }   // End "if (there is a difference)" clause.
                    }       // End j-loop
                }           // End i-loop
                if (repeat) // The last pattern was found repeating.
                {
                    break kLoop;  // Get out. The pattern repeats.
                }
            }                       // End k-loop
        }                           // End try clause
        catch (ArrayIndexOutOfBoundsException e)    // Array index out of 
                                                    // bounds!?
        {
            String errorStr = e.getMessage();
            errorStr = errorStr + ARRAY_BOUNDS_EXCEPTION + ", routine " +
                                  "DoesThePatternRepeat: " + ROWS + " = " + rows +
                        ", " + COLUMNS + " = " + columns +
                        ", i = " + i + ", " + AND + " j = " + j;
            error.ShowMessage(errorStr, OK);
        }
        if (repeat)  /* If the result is false, then the current pattern
                        at least hasn't been found to be repeating and the
                        next block is not executed; otherwise it repeats.    */
        {
                /*  If we execute this code we know the pattern to be
                    repeating, and it's the kIndex-th board of array
                    *oldboards*.

                    However, we have to determine the period of the
                    pattern.
                */

    /* Now to document what's happening in the next line. We do the
       example of < oldBoards.length = 5 >.

       Spit out some generation numbers followed by their
       remainders mod 5 (the boards where those generations are held):

       Assume a pattern repeats every three boards.

           generation: 1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 ...

       kIndex, and
       rem. (mod 5):   1  2  3  4  0  1  2  3  4  0  1  2  3  4  0  1  2  3  ...

       Assume we are on the 4th board. The last the repetition was board 1. 
       We set < period > = 4 - 1 = 3.

       If we are on the 15th board, the last repetition was the 12th. This
       means that it is stored in *oldboards*[2][][]; see above numbers; < kIndex > = 2.
       Thus 15%5 = 0; 12 + 3 = 15.

       If we are on the 11th board, the last repetition was on the 8th board
       (kIndex = 3).

       Think about it.

       All other examples are similar.            */

            int count;
            for (count = 1; count <= oldBoards.length; count++)
            {
                if ((kIndex + count)%oldBoards.length == generation%oldBoards.length)
                {
                    break;
                }
            }
            if (count == oldBoards.length + 1)
            {
                error.ShowMessage(UNRECOVERABLE_ERROR + " in " +
                                  " < RepeatPattern DoesThePatternRepeat() >: " +
                                  PERIOD_NOT_PROPERLY_SET, OK);
            }
            else
            {
                period = count;
            }
    /* Parameter < period > is returned to
       caller in routine < GetPeriod() > below.
    */
        }

        return repeat;  // Does the pattern repeat? Tell caller.

    }   // End of the routine < DoesThePatternRepeat >.

/*******************************************************************
   The next routine, < getPeriod >, tells the caller the period of
   a repeating pattern.
******************************************************************** */

    protected final int GetPeriod()
    {
        return period;
    }    
}       // End class < RepeatPattern >