/*********************************************************************
 * Author: B. Alex Bridges                                           *
 * Login ID: brid0129                                                *
 * Class: CPSC-221, Winter 1999                                      *
 * Project: Programming Assignment 1                                 *
 * Description: This program uses a game tree to play order 4        *
 *              reversi.                                             *
 * Contents: Methods for dealing with the reversi game.              *
 *********************************************************************/

/* IMPORTS */
import java.io.*;


class Game
{
  /* CONSTANTS */
  final static boolean b_debug    = false;      // CONTROLS EXTRA DEBUG OUTPUT
  final static int i_squares      = 16;         // NUMBER OF SQUARES FOR BOARD
  final static String str_default = "empty";    // DEFAULT STRING VALUE
  final static String str_white   = "white";    // WHITE'S STRING VALUE
  final static String str_black   = "black";    // BLACK'S STRING VALUE
  final static String str_continue= "okay";     // CONTINUE'S STRING VALUE
  final static String str_holes   = "no holes"; // HOLE'S STRING VALUE
  final static String str_moves   = "no moves"; // MOVE'S STRING VALUE


  /* OBJECT VARIABLES */
  private static String[] strA_board =        // BOARD'S CURRENT STATE
    new String[i_squares];
  private static String str_player;           // CURRENT PLAYER'S COLOR
  private static int i_m_number;              // MOVE NUMBER
  private static boolean[] bA_moves =         // VALID NEXT MOVES
    new boolean[i_squares];
  private static float[] fA_payoff =          // PAYOFF FROM NEXT MOVES
    new float[i_squares];
  private static int i_sug;                   // SUGGESTED CELL FOR NEXT MOVE
  private static int i_m_cell;                // CELL FOR LAST MOVE
  private static boolean b_full = false;      // FULL BOARD


  /*************************************************************************
   * Method: board_score                                                   *
   * Purpose: Counts the number of squares occupied by white vs. black.    *
   * Input: --PARAMETERS--                                                 *
   *        => none                                                        *
   * Output: --RETURNS--                                                   *
   *        => none                                                        *
   *************************************************************************/
  private static void board_score()
  {
    /* LOCAL VARIABLES */
    int i;            // ARRAY INDEX
    int i_whites = 0; // WHITE SQUARES
    int i_blacks = 0; // BLACK SQUARES

    /* SCORING OF BOARD */
    for(i = 0; i < i_squares; i++)
    {
      if( strA_board[i].equals(str_white) )
        i_whites++;
      else if( strA_board[i].equals(str_black) )
        i_blacks++;
      else
        System.out.println(" ERROR: Square "+String.valueOf(i+1)+" should be either "+str_white+" or "+str_black+", but it is '"+strA_board[i]+"'.");
    } // for

    if(i_whites > i_blacks)
      System.out.println("  Congratulations White! You win by a score of "+i_whites+" to "+i_blacks+".\n");
    else if(i_whites < i_blacks)
      System.out.println("  Congratulations Black! You win by a score of "+i_blacks+" to "+i_whites+".\n");
    else
      System.out.println("  Draw! The score was "+i_whites+" white to "+i_blacks+" black.\n");
  } // method board_score

  /*************************************************************************
   * Method: board_print                                                   *
   * Purpose: Prints a textual representation of the board.                *
   * Input: --PARAMETERS--                                                 *
   *        => none                                                        *
   * Output: --RETURNS--                                                   *
   *        => none                                                        *
   *************************************************************************/
  private static void board_print()
  {
    /* LOCAL VARIABLES */
    int i;  // ARRAY INDEX

    /* PRINTING OF BOARD */
    for(i = 0; i < i_squares; i++)
    {
      if( strA_board[i].equals(str_default) )
        if(i <= 8)
          System.out.print( " "+String.valueOf(i+1)+"  " );
        else
          System.out.print( String.valueOf(i+1)+"  " );
      else if( strA_board[i].equals(str_white) )
        System.out.print(" W  ");
      else if( strA_board[i].equals(str_black) )
        System.out.print(" B  ");

      if( (i + 1) % 4 == 0 )
        System.out.println();
    } // for

    System.out.println();
  } // method board_print

  /*************************************************************************
   * Method: board_reset                                                   *
   * Purpose: Resets the game so that all board squares are empty, the move*
   *          number is 1, and the current player is white.                *
   * Input: --PARAMETERS--                                                 *
   *        => none                                                        *
   * Output: --RETURNS--                                                   *
   *        => none                                                        *
   *************************************************************************/
  private static void board_reset()
  {
    /* LOCAL VARIABLES */
    int i;  // ARRAY INDEX

    /* EMPTY SQUARES*/
    for(i = 0; i < i_squares; i++)
    {
        strA_board[i] = str_default;
    } // for

    /* RESETTING OF MOVE NUMBER */
    i_m_number = 1;

    /* WHITE'S TURN */
    str_player = str_white;
  } // method board_reset

  /*************************************************************************
   * Method: check_bounds                                                  *
   * Purpose: Checks bounds of index to see if still within board.         *
   * Input: --PARAMETERS--                                                 *
   *        => i_index = The index which is in question                    *
   * Output: --RETURNS--                                                   *
   *        => Boolean of validity as index.                               *
   *************************************************************************/
  private static boolean check_bounds(int i_index)
  {
    /* LOCAL VARIABLES */
    // => NONE

    /* BOUNDS CHECKING */
    if( (0 <= i_index) && ( i_index <= (i_squares - 1) ) )
      return true;
    else
      return false;
  } // method check_bounds

  /*************************************************************************
   * Method: check_line                                                    *
   * Purpose: Checks along along each line for opposite then same color.   *
   * Input: --PARAMETERS--                                                 *
   *        => i_start = The index from which to begin checking.           *
   * Output: --RETURNS--                                                   *
   *        => Boolean of validity as next move.                           *
   *************************************************************************/
  private static boolean check_line(int i_start)
  {
    /* LOCAL VARIABLES */
    String str_opp; // OPPOSITE PLAYER'S COLOR
    int i_adj1;     // THE INDEX'S ADJACENT CELL
    int i_adj2;     // THE ADJACENT'S ADJACENT CELL

    /* CREATE OPPOSITE COLOR */
    if( str_player.equals(str_white) )
      str_opp = str_black;
    else
      str_opp = str_white;

    /* ADJACENCY CHECKING */
    // => UPPER,LEFT-HAND CORNER
    if( Game.check_bounds(i_adj1 = i_start - 5) )
      if( str_opp.compareTo(strA_board[i_adj1]) == 0) // OPPOSITE COLOR
        if( Game.check_bounds(i_adj2 = i_adj1 - 5) )
          if( str_player.compareTo(strA_board[i_adj2]) == 0) // SAME COLOR
          {
            if(b_debug)
            {
              System.out.println(String.valueOf(i_start+1)+" - UPPER,LEFT-HAND CORNER ["+String.valueOf(i_adj1+1)+","+String.valueOf(i_adj2+1)+"]");
              return true;
            } // if
            else
              return true;
          } // if

    // => TOP
    if( Game.check_bounds(i_adj1 = i_start - 4) )
      if( str_opp.compareTo(strA_board[i_adj1]) == 0) // OPPOSITE COLOR
        if( Game.check_bounds(i_adj2 = i_adj1 - 4) )
          if( str_player.compareTo(strA_board[i_adj2]) == 0) // SAME COLOR
          {
            if(b_debug)
            {
              System.out.println(String.valueOf(i_start+1)+" - TOP ["+String.valueOf(i_adj1+1)+","+String.valueOf(i_adj2+1)+"]");
              return true;
            } // if
            else
              return true;
          } // if

    // => UPPER,RIGHT-HAND CORNER
    if( Game.check_bounds(i_adj1 = i_start - 3) )
      if( str_opp.compareTo(strA_board[i_adj1]) == 0) // OPPOSITE COLOR
        if( Game.check_bounds(i_adj2 = i_adj1 - 3) )
          if( str_player.compareTo(strA_board[i_adj2]) == 0) // SAME COLOR
          {
            if(b_debug)
            {
              System.out.println(String.valueOf(i_start+1)+" - UPPER,RIGHT-HAND CORNER ["+String.valueOf(i_adj1+1)+","+String.valueOf(i_adj2+1)+"]");
              return true;
            } // if
            else
              return true;
          } // if

    // => RIGHT
    if( Game.check_bounds(i_adj1 = i_start + 1) )
      if( str_opp.compareTo(strA_board[i_adj1]) == 0) // OPPOSITE COLOR
        if( Game.check_bounds(i_adj2 = i_adj1 + 1) )
          if( str_player.compareTo(strA_board[i_adj2]) == 0) // SAME COLOR
          {
            if(b_debug)
            {
              System.out.println(String.valueOf(i_start+1)+" - RIGHT ["+String.valueOf(i_adj1+1)+","+String.valueOf(i_adj2+1)+"]");
              return true;
            } // if
            else
              return true;
          } // if

    // => LOWER,RIGHT-HAND CORNER
    if( Game.check_bounds(i_adj1 = i_start + 5) )
      if( str_opp.compareTo(strA_board[i_adj1]) == 0) // OPPOSITE COLOR
        if( Game.check_bounds(i_adj2 = i_adj1 + 5) )
          if( str_player.compareTo(strA_board[i_adj2]) == 0) // SAME COLOR
          {
            if(b_debug)
            {
              System.out.println(String.valueOf(i_start+1)+" - LOWER,RIGHT-HAND CORNER ["+String.valueOf(i_adj1+1)+","+String.valueOf(i_adj2+1)+"]");
              return true;
            } // if
            else
              return true;
          } // if

    // => BOTTOM
    if( Game.check_bounds(i_adj1 = i_start + 4) )
      if( str_opp.compareTo(strA_board[i_adj1]) == 0) // OPPOSITE COLOR
        if( Game.check_bounds(i_adj2 = i_adj1 + 4) )
          if( str_player.compareTo(strA_board[i_adj2]) == 0) // SAME COLOR
          {
            if(b_debug)
            {
              System.out.println(String.valueOf(i_start+1)+" - BOTTOM ["+String.valueOf(i_adj1+1)+","+String.valueOf(i_adj2+1)+"]");
              return true;
            } // if
            else
              return true;
          } // if

    // => LOWER,LEFT-HAND CORNER
    if( Game.check_bounds(i_adj1 = i_start + 3) )
      if( str_opp.compareTo(strA_board[i_adj1]) == 0) // OPPOSITE COLOR
        if( Game.check_bounds(i_adj2 = i_adj1 + 3) )
          if( str_player.compareTo(strA_board[i_adj2]) == 0) // SAME COLOR
          {
            if(b_debug)
            {
              System.out.println(String.valueOf(i_start+1)+" - LOWER,LEFT-HAND CORNER ["+String.valueOf(i_adj1+1)+","+String.valueOf(i_adj2+1)+"]");
              return true;
            } // if
            else
              return true;
          } // if

    // => LEFT
    if( Game.check_bounds(i_adj1 = i_start - 1) )
      if( str_opp.compareTo(strA_board[i_adj1]) == 0) // OPPOSITE COLOR
        if( Game.check_bounds(i_adj2 = i_adj1 - 1) )
          if( str_player.compareTo(strA_board[i_adj2]) == 0) // SAME COLOR
          {
            if(b_debug)
            {
              System.out.println(String.valueOf(i_start+1)+" - LEFT ["+String.valueOf(i_adj1+1)+","+String.valueOf(i_adj2+1)+"]");
              return true;
            } // if
            else
              return true;
          } // if

    // => IF GOT TO HERE, ALL CHECKS ABOVE WERE INAVLID, SO THE MOVE IS INVALID
    if(b_debug)
    {
      System.out.println(String.valueOf(i_start+1)+" - NONE");
      return false;
    } // if
    else
      return false;
  } // method check_line

  /*************************************************************************
   * Method: move_adjust                                                   *
   * Purpose: Does the actual adjustments for move_initial and move_later. *
   * Input: --PARAMETERS--                                                 *
   *        => none                                                        *
   * Output: --RETURNS--                                                   *
   *        => none                                                        *
   *************************************************************************/
  public static void move_adjust()
  {
    /* LOCAL VARIABLES */
    // => NONE

    /* ADJUSTMENTS */
    // => ALTERNATE CURRENT PLAYER
    if( str_player.equals(str_white) )
      str_player = str_black;
    else
      str_player = str_white;
 } // method move_adjust

  /*************************************************************************
   * Method: move_adjust                                                   *
   * Purpose: Does the actual adjustments for move_initial and move_later. *
   * Input: --PARAMETERS--                                                 *
   *        => i_move = The cell in which the piece will be played.        *
   * Output: --RETURNS--                                                   *
   *        => none                                                        *
   *************************************************************************/
  public static void move_adjust(int i_move)
  {
    /* LOCAL VARIABLES */
    String str_opp; // OPPOSITE PLAYER'S COLOR
    int i_adj1;     // THE REQUESTED CELL'S ADJACENT CELL
    int i_adj2;     // THE ADJACENT'S ADJACENT CELL

    /* CREATE OPPOSITE COLOR */
    if( str_player.equals(str_white) )
      str_opp = str_black;
    else
      str_opp = str_white;

    /* ADJUSTMENTS */
    // => COPY MOVE PARAMETER TO CLASS VARIABLE
    i_m_cell = i_move;

    // => OCCUPY REQUESTED CELL WITH PLAYER'S COLOR
    strA_board[i_m_cell - 1] = str_player;

    // => FLIP APPROPRIATE TILES
    // => UPPER,LEFT-HAND CORNER
    if( Game.check_bounds(i_adj1 = i_m_cell - 1 - 5) )
      if( str_opp.compareTo(strA_board[i_adj1]) == 0) // OPPOSITE COLOR
        if( Game.check_bounds(i_adj2 = i_adj1 - 5) )
          if( str_player.compareTo(strA_board[i_adj2]) == 0) // SAME COLOR
          {
            if(b_debug)
            {
              System.out.println(String.valueOf(i_move+1)+" - UPPER,LEFT-HAND CORNER ["+String.valueOf(i_adj1+1)+","+String.valueOf(i_adj2+1)+"]");
              strA_board[i_adj1] = str_player;
            } // if
            else
              strA_board[i_adj1] = str_player;
          } // if

    // => TOP
    if( Game.check_bounds(i_adj1 = i_m_cell - 1 - 4) )
      if( str_opp.compareTo(strA_board[i_adj1]) == 0) // OPPOSITE COLOR
        if( Game.check_bounds(i_adj2 = i_adj1 - 4) )
          if( str_player.compareTo(strA_board[i_adj2]) == 0) // SAME COLOR
          {
            if(b_debug)
            {
              System.out.println(String.valueOf(i_move+1)+" - TOP ["+String.valueOf(i_adj1+1)+","+String.valueOf(i_adj2+1)+"]");
              strA_board[i_adj1] = str_player;
            } // if
            else
              strA_board[i_adj1] = str_player;
          } // if

    // => UPPER,RIGHT-HAND CORNER
    if( Game.check_bounds(i_adj1 = i_m_cell - 1 - 3) )
      if( str_opp.compareTo(strA_board[i_adj1]) == 0) // OPPOSITE COLOR
        if( Game.check_bounds(i_adj2 = i_adj1 - 3) )
          if( str_player.compareTo(strA_board[i_adj2]) == 0) // SAME COLOR
          {
            if(b_debug)
            {
              System.out.println(String.valueOf(i_move+1)+" - UPPER,RIGHT-HAND CORNER ["+String.valueOf(i_adj1+1)+","+String.valueOf(i_adj2+1)+"]");
              strA_board[i_adj1] = str_player;
            } // if
            else
              strA_board[i_adj1] = str_player;
          } // if

    // => RIGHT
    if( Game.check_bounds(i_adj1 = i_m_cell - 1 + 1) )
      if( str_opp.compareTo(strA_board[i_adj1]) == 0) // OPPOSITE COLOR
        if( Game.check_bounds(i_adj2 = i_adj1 + 1) )
          if( str_player.compareTo(strA_board[i_adj2]) == 0) // SAME COLOR
          {
            if(b_debug)
            {
              System.out.println(String.valueOf(i_move+1)+" - RIGHT ["+String.valueOf(i_adj1+1)+","+String.valueOf(i_adj2+1)+"]");
              strA_board[i_adj1] = str_player;
            } // if
            else
              strA_board[i_adj1] = str_player;
          } // if

    // => LOWER,RIGHT-HAND CORNER
    if( Game.check_bounds(i_adj1 = i_m_cell - 1 + 5) )
      if( str_opp.compareTo(strA_board[i_adj1]) == 0) // OPPOSITE COLOR
        if( Game.check_bounds(i_adj2 = i_adj1 + 5) )
          if( str_player.compareTo(strA_board[i_adj2]) == 0) // SAME COLOR
          {
            if(b_debug)
            {
              System.out.println(String.valueOf(i_move+1)+" - LOWER,RIGHT-HAND CORNER ["+String.valueOf(i_adj1+1)+","+String.valueOf(i_adj2+1)+"]");
              strA_board[i_adj1] = str_player;
            } // if
            else
              strA_board[i_adj1] = str_player;
          } // if

    // => BOTTOM
    if( Game.check_bounds(i_adj1 = i_m_cell - 1 + 4) )
      if( str_opp.compareTo(strA_board[i_adj1]) == 0) // OPPOSITE COLOR
        if( Game.check_bounds(i_adj2 = i_adj1 + 4) )
          if( str_player.compareTo(strA_board[i_adj2]) == 0) // SAME COLOR
          {
            if(b_debug)
            {
              System.out.println(String.valueOf(i_move+1)+" - BOTTOM ["+String.valueOf(i_adj1+1)+","+String.valueOf(i_adj2+1)+"]");
              strA_board[i_adj1] = str_player;
            } // if
            else
              strA_board[i_adj1] = str_player;
          } // if

    // => LOWER,LEFT-HAND CORNER
    if( Game.check_bounds(i_adj1 = i_m_cell - 1 + 3) )
      if( str_opp.compareTo(strA_board[i_adj1]) == 0) // OPPOSITE COLOR
        if( Game.check_bounds(i_adj2 = i_adj1 + 3) )
          if( str_player.compareTo(strA_board[i_adj2]) == 0) // SAME COLOR
          {
            if(b_debug)
            {
              System.out.println(String.valueOf(i_move+1)+" - LOWER,LEFT-HAND CORNER ["+String.valueOf(i_adj1+1)+","+String.valueOf(i_adj2+1)+"]");
              strA_board[i_adj1] = str_player;
            } // if
            else
              strA_board[i_adj1] = str_player;
          } // if

    // => LEFT
    if( Game.check_bounds(i_adj1 = i_m_cell - 1 - 1) )
      if( str_opp.compareTo(strA_board[i_adj1]) == 0) // OPPOSITE COLOR
        if( Game.check_bounds(i_adj2 = i_adj1 - 1) )
          if( str_player.compareTo(strA_board[i_adj2]) == 0) // SAME COLOR
          {
            if(b_debug)
            {
              System.out.println(String.valueOf(i_move+1)+" - LEFT ["+String.valueOf(i_adj1+1)+","+String.valueOf(i_adj2+1)+"]");
              strA_board[i_adj1] = str_player;
            } // if
            else
              strA_board[i_adj1] = str_player;
          } // if

    // => PRINT MOVE STATEMENT AND BOARD'S CURRENT STATE
    Game.move_print();
    Game.board_print();

    // => INCREMENT MOVE NUMBER
    i_m_number++;

    // => ALTERNATE CURRENT PLAYER
    if( str_player.equals(str_white) )
      str_player = str_black;
    else
      str_player = str_white;
 } // method move_adjust

  /*************************************************************************
   * Method: move_initial                                                  *
   * Purpose: Makes the initial 4 moves.                                   *
   * Input: --PARAMETERS--                                                 *
   *        => none                                                        *
   * Output: --RETURNS--                                                   *
   *        => none                                                        *
   *************************************************************************/
  private static void move_initial()
  {
    /* LOCAL VARIABLES */
    double db_random; // RESULT FROM RANDOM NUMBER GENERATOR

    /* RESET GAME */
    Game.board_reset();
    Game.board_print();

    /* GENERATE RANDOM NUMBER */
    db_random = Math.random();

    /* SELECTION AN INITIAL SETUP */
    // => POSSIBILITY #1
    //        W W
    //        B B
    if(db_random <= 0.16)
    {
      Game.move_adjust(06);  // WHITE TO CELL 06
      Game.move_adjust(10);  // BLACK TO CELL 10
      Game.move_adjust(07);  // WHITE TO CELL 07
      Game.move_adjust(11);  // BLACK TO CELL 11
    } // if

    // => POSSIBILITY #2
    //        B W
    //        B W
    else if(db_random <= 0.32)
    {
      Game.move_adjust(06);  // WHITE TO CELL 06
      Game.move_adjust(10);  // BLACK TO CELL 10
      Game.move_adjust(07);  // WHITE TO CELL 07
      Game.move_adjust(11);  // BLACK TO CELL 11
    } // if

    // => POSSIBILITY #3
    //        B B
    //        W W
    else if(db_random <= 0.48)
    {
      Game.move_adjust(10);  // WHITE TO CELL 10
      Game.move_adjust(06);  // BLACK TO CELL 06
      Game.move_adjust(11);  // WHITE TO CELL 11
      Game.move_adjust(07);  // BLACK TO CELL 07
    } // if

    // => POSSIBILITY #4
    //        W B
    //        W B
    else if(db_random <= 0.64)
    {
      Game.move_adjust(06);  // WHITE TO CELL 06
      Game.move_adjust(07);  // BLACK TO CELL 07
      Game.move_adjust(10);  // WHITE TO CELL 10
      Game.move_adjust(11);  // BLACK TO CELL 11
    } // if

    // => POSSIBILITY #5
    //        W B
    //        B W
    else if(db_random <= 0.80)
    {
      Game.move_adjust(06);  // WHITE TO CELL 06
      Game.move_adjust(07);  // BLACK TO CELL 07
      Game.move_adjust(11);  // WHITE TO CELL 11
      Game.move_adjust(10);  // BLACK TO CELL 10
    } // if

    // => POSSIBILITY #6
    //        B W
    //        W B
    else
    {
      Game.move_adjust(07);  // WHITE TO CELL 07
      Game.move_adjust(06);  // BLACK TO CELL 06
      Game.move_adjust(10);  // WHITE TO CELL 10
      Game.move_adjust(11);  // BLACK TO CELL 11
    } // else
  } // method move_initial

  /*************************************************************************
   * Method: move_later                                                    *
   * Purpose: Makes the later moves.                                       *
   * Input: --PARAMETERS--                                                 *
   *        => none                                                        *
   * Output: --RETURNS--                                                   *
   *        => none                                                        *
   *************************************************************************/
  private static void move_later()
  {
    /* LOCAL VARIABLES */
    int i_new;        // THE NEW CELL WHICH TO OCCUPY
    String str_valid; // move_valid's STRING RESULT

    try
    {
      /* STANDARD TEXT INPUT STREAM SETUP */
      BufferedReader br_std_in = new BufferedReader( new InputStreamReader(System.in) );

      /* CONTINUE TO MAKE MOVES UNTIL NO SPACES AVAILABLE */
      while( ( str_valid = Game.move_valid() ).compareTo(str_holes) != 0 )
      {
        /* MOVE */
        if( str_valid.compareTo(str_moves) != 0 )
        {
          // => MANUALLY
          if(b_debug)
          {

            System.out.print("Please enter one of the above moves: ");
            System.out.flush();
            i_new = Integer.parseInt( br_std_in.readLine() );
            System.out.println("");

            Game.move_adjust(i_new);
          } // if
          // => AUTOMATIC
          else
          {
            System.out.println("");

            Game.move_adjust(i_sug);
          } // else
        } // if
        // => UNABLE
        else
        {
          System.out.println(" Sorry, but no moves are available at this time.\n");

          Game.move_adjust();
        } // else
      } // while

      Game.board_score();
    } // try
    /* EXCEPTION HANDLING */
    catch(IOException exception)
    {
      System.out.println(" FATAL EXCEPTION: Standard input problem.");
      System.exit(-1);
    } // catch
    catch(NumberFormatException exception)
    {
      System.out.println(" EXCEPTION: Invalid move.");
    } // catch
  } // method move_later

  /*************************************************************************
   * Method: move_payoff                                                   *
   * Purpose: Calculates the payoff of each valid move and makes the       *
   *          appropriate suggestion.                                      *
   * Input: --PARAMETERS--                                                 *
   *        => none                                                        *
   * Output: --RETURNS--                                                   *
   *        => none                                                        *
   *************************************************************************/
  private static void move_payoff()
  {
    /* LOCAL VARIABLES */
    int i;            // ARRAY INDEX
    float f_max = -2; // MAX. POSSIBLE PAYOFF

    /* PAYOFF CHECKING */
    for(i = 0; i < i_squares; i++)
    {
      if( bA_moves[i] )
      {
        // => CORNERS
        if( (i == 1 - 1) | (i == 4 - 1) | (i == 13 - 1) | (i == 16 - 1) )
          fA_payoff[i] = (float) +1.0;
        // => SIDE
        else
          fA_payoff[i] = (float) +0.5;
      } // if
      else
        fA_payoff[i] = (float) -1.0;
    } // for

    /* SUGGESTED MOVE */
    for(i = 0; i < i_squares; i++)
    {
      if( fA_payoff[i] >= f_max )
      {
        f_max = fA_payoff[i];
        i_sug = i + 1;
      } // if
    } // for

    if(b_debug)
      System.out.println("Suggested move:  "+String.valueOf(i_sug)+" ("+fA_payoff[i_sug - 1]+"), ");
  } // method move_payoff

  /*************************************************************************
   * Method: move_print                                                    *
   * Purpose: Prints statement explaining the current move.                *
   * Input: --PARAMETERS--                                                 *
   *        => none                                                        *
   * Output: --RETURNS--                                                   *
   *        => none                                                        *
   *************************************************************************/
  private static void move_print()
  {
    /* LOCAL VARIABLES */
    // => NONE

    /* PRINTS MOVE'S STATEMENT */
    System.out.println("MOVE NUMBER <"+i_m_number+">:  <"+str_player+"> MOVES TO <"+i_m_cell+">.");

  } // method move_print

  /*************************************************************************
   * Method: move_valid                                                    *
   * Purpose: Determines the next moves which are valid.                   *
   * Input: --PARAMETERS--                                                 *
   *        => none                                                        *
   * Output: --RETURNS--                                                   *
   *        => str_holes = No spaces available.                            *
   *        => str_moves = No moves available.                             *
   *        => str_continue = Both items available.                        *
   *************************************************************************/
  private static String move_valid()
  {
    /* LOCAL VARIABLES */
    int i;            // ARRAY INDEX
    int i_holes = 0;  // HOLE COUNTER
    int i_moves = 0;  // MOVE COUNTER

    /* FIND HOLES AND CHECK ADJACENCY */
    for(i = 0; i < i_squares; i++)
    {
      if( strA_board[i].equals(str_default) )
      {
        i_holes++;
        if( Game.check_line(i) )
        {
          i_moves++;
          bA_moves[i] = true;
        } // if
        else
          bA_moves[i] = false;
      } // if
      else
        bA_moves[i] = false;
    } // for

    /* DETERMINE PAYOFFS */
    Game.move_payoff();

    /* PRINTING OF VALID MOVES AND RESPECTIVE PAYOFFS */
    if(i_holes != 0)
    {
      System.out.print(str_player+"'s moves and respective payoffs:  ");
      for(i = 0; i < i_squares; i++)
      {
        if( bA_moves[i])
          System.out.print(String.valueOf(i+1)+" ("+fA_payoff[i]+"), ");
      } // for
      System.out.println();
    } // if

    /* AVAILABILITY */
    if(i_holes == 0)
      return str_holes;
    if(i_moves == 0)
      return str_moves;
    else
      return str_continue;
  } // method move_valid

  /*************************************************************************
   * Method: play                                                          *
   * Purpose: Calls the appropriate private methods to play the game.      *
   * Input: --PARAMETERS--                                                 *
   *        => none                                                        *
   * Output: --RETURNS--                                                   *
   *        => none                                                        *
   *************************************************************************/
  public static void play()
  {
    /* LOCAL VARIABLES */
    // => NONE

    Game.move_initial();
    Game.move_later();
  } // method play
} // class Game
