/* '='='=' '@' '='='='='='='='='=' '@' '='='='='='='='='=' '@' '='='='| */
/* ='='=' '@'@' '='='='='='='='=' '@'@' '='='='='='='='=' '@'@' '='='=| */
/* '='=' '@':'@' '='='='='='='=' '@':'@' '='='='='='='=' '@':'@' '='='| */
/* ='=' '@':':'@' '='='='='='=' '@':':'@' '='='='='='=' '@':':'@' '='=| */
/* '=' '@':':':'@' '='='='='=' '@':':':'@' '='='='='=' '@':':':'@' '='| */
/* =' '@':':':':'@' '='='='=' '@':':':':'@' '='='='=' '@':':':':'@' '=| */
/* ' '@':'                                                       '@' '| */
/*  '@'         3rd Year Project - ROY SCHESTOWITZ - 2002          @' | */
/* '@                                                               @'| */
/* @':':':':':':':':'@' ' '@':':':':':':':':'@' ' '@':':':':':':':':'@| */
/* ':':':':':':':':':'@' '@':':':':':':':':':'@' '@':':':':':':':':':'| */
/* :':':':':':':':':':'@'@':':':':':':':':':':'@'@':':':':':':':':':':| */
/* ':':':': : :':':':':'@':':':':': : :':':':':'@':':':':': : :':':':'| */
/*  -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
/*              Name:           loaders.c                               */
/*              Version:        0.6.6                                   */
/*              Date:           12/2/2003                               */
/*                                                                      */
/*      The callback functions                                          */
/*                                                                      */
/*  -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */

#include "callbacks.h"
#include "computation.c"
#include "misc.h"

/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* load - the load game submenu callback function                             */
/* inputs: the callback value                                                 */
/*                                                                            */
/*                                                                            */


void
load ( int menuentry )
{
  if ( load_game ( menuentry - 20 ) == FALSE )	/* mask just to get slot number     */
    if ( VERBOSE )		/* e.g. slot one corresponds to 21  */
      printf ( "Could not load the game. Loading operation aborted.\n" );
}

/*                                                                            */
/*                                                                            */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/******************************************************************************/



/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* save - the save game submenu callback function                             */
/* inputs: the callback value                                                 */
/*                                                                            */
/*                                                                            */


void
save ( int menuentry )
{
  if ( save_game ( menuentry - 10 ) == FALSE )	/* mask just to get slot number    */
    if ( VERBOSE )		/* e.g. slot one corresponds to 21 */
      printf ( "Could not save the game. Saving operation aborted.\n" );
}

/*                                                                            */
/*                                                                            */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/******************************************************************************/





/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* determinism_callback - the determinism callback function                   */
/*                                                                            */
/*                                                                            */


void
determinism_callback ( int menuentry )
{
  switch ( menuentry )
    {
    case DETERMINISM_ON:	// deterministic
      non_determinism = FALSE;	/* set the appropriate state global          */
      if ( VERBOSE )
	printf ( "Deterministic computation enabled.\n" );
      break;

    case DETERMINISM_OFF:	// non-deterministic
      non_determinism = TRUE;	/* set the appropriate state global          */
      if ( VERBOSE )
	printf ( "Non-deterministic computation enabled.\n" );
      break;

    default:			/* should never happen. Here for safety only */
      if ( VERBOSE )
	printf
	  ( "Error with menu entries. Invalid callback value has been passed.\n" );
      break;
    }
}

/*                                                                            */
/*                                                                            */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/******************************************************************************/






/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* edit_board_callback - board editing submenu callback function              */
/* inputs: the callback value                                                 */
/*                                                                            */
/*                                                                            */

void
edit_board_callback ( int menuentry )
{
  switch ( menuentry )
    {
    case EDIT_START:		// START EDIT
      enable_edit = TRUE;	/* start the editing                */
      edit_element = NONE;	/* initilaise the type of placement */
      break;

    case EDIT_END:		// END EDIT
      enable_edit = FALSE;	/* end the editing         */
      break;

    case EDIT_RED:		// RED PLACEMENT
      edit_element = RED;	/* choose red placement         */
      break;

    case EDIT_BLACK:		// BLACK PLACEMENT
      edit_element = BLACK;	/* choose black placement         */
      break;

    case EDIT_NONE:		// EMPTY PLACEMENT
      edit_element = NONE;	/* choose empty placement         */
      break;

    }
}


/*                                                                            */
/*                                                                            */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/******************************************************************************/




/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* log_file_callback - customised computation submenu callback function       */
/* inputs: the callback value                                                 */
/*                                                                            */
/*                                                                            */

void
customise_callback ( int menuentry )
{
  switch ( menuentry )
    {
    case CUSTOMISED_LINE:	// ACTIVATE/DEACTIVATE LINE EVALUATION
      enable_line_eval = !enable_line_eval;	/* inverse state         */
      if ( VERBOSE )
	{
	  if ( enable_line_eval )
	    printf ( "Line evaluation Enabled\n" );
	  else
	    printf ( "Line evaluation Disabled\n" );
	}
      break;

    case CUSTOMISED_SCORE:	// ACTIVATE/DEACTIVATE SCORE EVALUATION
      enable_score_eval = !enable_score_eval;	/* inverse state         */
      if ( VERBOSE )
	{
	  if ( enable_score_eval )
	    printf ( "Score evaluation Enabled\n" );
	  else
	    printf ( "Score evaluation Disabled\n" );
	}
      break;

    case CUSTOMISED_MOBILITY:	// ACTIVATE/DEACTIVATE MOBILITY EVALUATION
      enable_mobility_eval = !enable_mobility_eval;	/* inverse state         */
      if ( VERBOSE )
	{
	  if ( enable_mobility_eval )
	    printf ( "Mobility evaluation Enabled\n" );
	  else
	    printf ( "Mobility evaluation Disabled\n" );
	}
      break;

    case CUSTOMISED_POSITION:	// ACTIVATE/DEACTIVATE POSITION EVALUATION
      enable_position_eval = !enable_position_eval;	/* inverse state         */
      if ( VERBOSE )
	{
	  if ( enable_position_eval )
	    printf ( "Position evaluation Enabled\n" );
	  else
	    printf ( "Position evaluation Disabled\n" );
	}
      break;


    default:			/* should never happen. Here for safety only */
      if ( VERBOSE )
	printf
	  ( "Error with menu entries. Invalid callback value has been passed.\n" );
      break;
    }
}

/*                                                                            */
/*                                                                            */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/******************************************************************************/




/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* open_report - opens the file where a game report would be appended         */
/*                                                                            */
/*                                                                            */

void
open_report ( char *filename )
{

  report_file = fopen ( filename, "a" );	/* open the given filename and point */
  /* end of data in order to append a  */
  /* report entry                      */
  if ( !report_file )		/* if a report file has not been     */
    {				/* opened yet                        */
      if ( VERBOSE )
	printf ( "Could not create report file %s.\n", filename );
      return;
    }
  add_to_report_file = TRUE;	/* set global to indicate logging    */
  if ( VERBOSE )
    printf ( "Report file %s opened successfully.\n", filename );



}

/*                                                                            */
/*                                                                            */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/******************************************************************************/



/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* open_log_file - opens a log file displaying some initial information       */
/* inputs: the name of the log file to be created                             */
/*                                                                            */
/*                                                                            */

void
open_log_file ( char *filename )
{

  log_file = fopen ( filename, "w" );	/* open the given file for writing */
  if ( !log_file )		/* if the pointer is NULL i.e.     */
    {				/* file could not be opened        */
      if ( VERBOSE )
	printf ( "Could not create log file %s.\n", filename );
      return;			/* abort logging                   */
    }

  keep_log_file = TRUE;		/* set global flag                 */
  if ( VERBOSE )
    printf ( "Creating log file %s.\n", filename );
  /* the following is initial information that is written to the file */
  fprintf ( log_file, "Othello Master game log\n" );
  fprintf ( log_file, "=======================\n\n" );

  fprintf ( log_file, "Filename: %s\n\n", filename );

  if ( gather_statistics == TRUE )	/* RED is CPU */
    {				/* the following inspects the current difficulty */
      if ( stat_mode_difficulty == BEGINNER )
	fprintf ( log_file, "RED is CPU at level beginner\n\n" );
      else if ( stat_mode_difficulty == NOVICE )
	fprintf ( log_file, "RED is CPU at level novice\n\n" );
      else if ( stat_mode_difficulty == EXPERT )
	fprintf ( log_file, "RED is CPU at level expert\n\n" );
      else if ( stat_mode_difficulty == PRE_MASTER )
	fprintf ( log_file, "RED is CPU at level pre-master\n\n" );
      else if ( stat_mode_difficulty == MASTER )
	fprintf ( log_file, "RED is CPU at level master\n\n" );
    }
  else				/* RED is player/human */
    fprintf ( log_file, "RED is human called %s\n\n", player_name );

  if ( playing_against_cpu == FALSE )	/* BLACK is human player */
    fprintf ( log_file, "BLACK is human\n\n" );

  else				/* BLACK is CPU */
    {				/* inspect the difficulty of this player */
      if ( difficulty == BEGINNER )
	fprintf ( log_file, "BLACK is CPU at level beginner\n\n" );
      else if ( difficulty == NOVICE )
	fprintf ( log_file, "BLACK is CPU at level novice\n\n" );
      else if ( difficulty == EXPERT )
	fprintf ( log_file, "BLACK is CPU at level expert\n\n" );
      else if ( difficulty == PRE_MASTER )
	fprintf ( log_file, "BLACK is CPU at level pre-master\n\n" );
      else if ( difficulty == MASTER )
	fprintf ( log_file, "BLACK is CPU at level master\n\n" );
    }

}

/*                                                                            */
/*                                                                            */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/******************************************************************************/




/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* opening library_callback - the opening moves library submenu callback      */
/* function                                                                   */
/* inputs: the callback value                                                 */
/*                                                                            */
/*                                                                            */


void
opening_library_callback ( int menuentry )
{
  switch ( menuentry )
    {
    case LIBRARY_ON:		// ENABLE LIBRARY
      if ( use_opening_library == TRUE )	/* if the game is already using   */
	/* opening library                */
	printf ( "This game is already uses opening library.\n" );
      else
	{
	  use_opening_library = TRUE;	/* set the game to use library          */
	  if ( VERBOSE )
	    printf
	      ( "This game will now initlialise the opening library.\n" );
	  init_opening_library (  );
	}
      break;

    case LIBRARY_OFF:		// DISABLE LIBRARY
      use_opening_library = FALSE;	/* set the game to cease using library     */
      if ( VERBOSE )
	printf ( "This game will not use the opening library.\n" );
      break;

    default:			/* here for safety and debugging pusposes only */
      if ( VERBOSE )
	printf
	  ( "Error with menu entries. Invalid callback value has been passed.\n" );
      break;
    }
}

/*                                                                            */
/*                                                                            */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/******************************************************************************/






/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* report_callback - the report generation submenu callback function          */
/* inputs: the callback value                                                 */
/*                                                                            */
/*                                                                            */


void
report_callback ( int menuentry )
{
  switch ( menuentry )
    {
    case REPORT_ON:		// ADD TO DEAFULT REPORT
      if ( add_to_report_file == TRUE )	/* if the game is already recorded */
	printf ( "This game is already recorded.\n" );
      else
	{
	  add_to_report_file = TRUE;	/* set the game to be recorded           */
	  open_report ( "default.rep" );	/* open a default report file        */
	  if ( VERBOSE )
	    printf ( "This game will be recorded in file default.rep.\n" );
	}
      break;

    case REPORT_OFF:		// DEACTIVATE REPORT FILE
      add_to_report_file = FALSE;	/* set the game to cease being recorded     */
      if ( VERBOSE )
	printf ( "This game will not be recorded.\n" );
      break;

    default:			/* here for safety and debugging pusposes only */
      if ( VERBOSE )
	printf
	  ( "Error with menu entries. Invalid callback value has been passed.\n" );
      break;
    }
}

/*                                                                            */
/*                                                                            */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/******************************************************************************/



/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* log_file_callback - the log file submenu callback function                 */
/* inputs: the callback value                                                 */
/*                                                                            */
/*                                                                            */


void
log_file_callback ( int menuentry )
{
  switch ( menuentry )
    {
    case LOGGING_ACTIVATE:	// ACTIVATE LOGGING
      if ( !keep_log_file )	/* if no log file is already open          */
	open_log_file ( "omlog.log" );	/* open a default log file          */
      break;

    case LOGGING_DEACTIVATE:	// DEACTIVATE LOGGING
      keep_log_file = FALSE;	/* stop logging to a file                  */
      break;

    default:			/* here for safety and debugging pusposes only */
      if ( VERBOSE )
	printf
	  ( "Error with menu entries. Invalid callback value has been passed.\n" );
      break;
    }
}

/*                                                                            */
/*                                                                            */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/******************************************************************************/




/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* difficulty_description callback - the difficulty description submenu       */
/* callback function                                                          */
/* inputs: the callback value                                                 */
/*                                                                            */
/*                                                                            */


void
difficulty_description_callback ( int menuentry )
{
  void set_difficulty_description_view (  )
  {
    eyex = 0;			/* set view position                   */
    eyez = -40;
    eyey = 0;
    upx = 0.0;			/* Set up direction to be the +Y axis  */
    upy = 1.0;
    upz = 0.0;
    centerz = -50;		/* set centre of attention             */
    centery = 0;
    centerx = 0;
  }

  set_difficulty_description_view (  );
  switch ( menuentry )		/* will set the difficulty view according to  */
    /* the callback value                         */
    {
    case DIF_DESC_CALLBACK_BEGINNER:	// DIFFICULTY - BEGINNER
      view = BEGINNER_VIEW;
      break;

    case DIF_DESC_CALLBACK_NOVICE:	// DIFFICULTY - NOVICE
      view = NOVICE_VIEW;
      break;

    case DIF_DESC_CALLBACK_EXPERT:	// DIFFICULTY - EXPERT
      view = EXPERT_VIEW;
      break;

    case DIF_DESC_CALLBACK_PREMASTER:	// DIFFICULTY - PRE-MASTER
      view = PREMASTER_VIEW;
      break;

    case DIF_DESC_CALLBACK_MASTER:	// DIFFICULTY - MASTER
      view = MASTER_VIEW;
      break;



    default:			/* here for safety and debugging pusposes only */
      if ( VERBOSE )
	printf
	  ( "Error with menu entries. Invalid callback value has been passed.\n" );
      break;
    }
}






/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* difficulty_callback - the difficulty submenu callback function             */
/* inputs: the callback value                                                 */
/*                                                                            */
/*                                                                            */


void
difficulty_callback ( int menuentry )
{
  switch ( menuentry )		/* will set the diffculty according to the    */
    /* callback value                             */
    {
    case DIF_CALLBACK_BEGINNER:	// DIFFICULTY - BEGINNER
      difficulty = BEGINNER;
      break;

    case DIF_CALLBACK_NOVICE:	// DIFFICULTY - NOVICE
      difficulty = NOVICE;
      break;

    case DIF_CALLBACK_EXPERT:	// DIFFICULTY - EXPERT
      difficulty = EXPERT;
      break;

    case DIF_CALLBACK_PREMASTER:	// DIFFICULTY - PRE-MASTER
      difficulty = PRE_MASTER;
      break;

    case DIF_CALLBACK_MASTER:	// DIFFICULTY - MASTER
      difficulty = MASTER;
      break;



    default:			/* here for safety and debugging pusposes only */
      if ( VERBOSE )
	printf
	  ( "Error with menu entries. Invalid callback value has been passed.\n" );
      break;
    }
}

/*                                                                            */
/*                                                                            */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/******************************************************************************/




/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* gamemode_callback - the game mode submenu callback function                */
/* inputs: the callback value                                                 */
/*                                                                            */
/*                                                                            */


void
gamemode_callback ( int menuentry )
{
  switch ( menuentry )
    {
    case GAMEMODE_CPU:		// PLAY AGAINST CPU
      playing_against_cpu = TRUE;	/* set global to new mode */
      if ( turn == BLACK )	/* if it is BLACK's turn  */
	cpuflag = TRUE;		/* indicate that a move needs to be computed  */
      /* as soon as possible within the main loop   */
      break;

    case GAMEMODE_PLAYER:	// PLAY AGAINST HUMAN
      playing_against_cpu = FALSE;	/* set global to new mode */
      cpuflag = FALSE;		/* avoid a computed move from being carried out */
      break;

    default:			/* here for safety and debugging pusposes only */
      if ( VERBOSE )
	printf
	  ( "Error with menu entries. Invalid callback value has been passed.\n" );
      break;
    }
}

/*                                                                            */
/*                                                                            */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/******************************************************************************/




/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* menu - the menu callback function                                          */
/* inputs: the callback value                                                 */
/*                                                                            */
/*                                                                            */

void
menu ( int menuentry )
{
  switch ( menuentry )
    {

    case MAIN_MENU_NEW_GAME:	// NEW GAME
      initboard (  );		/* new game chosen */
      break;

    case MAIN_MENU_HELP:	// HELP
      eyex = -5;		/* set view position                   */
      eyez = 40;
      eyey = 11.0;
      upx = 0.0;		/* Set up direction to be the +Y axis  */
      upy = 1.0;
      upz = 0.0;
      centerz = 0;		/* set centre of attention             */
      centery = 11;
      centerx = -5;
      view = HELP;		/* set the current view identifier     */
      break;

    case MAIN_MENU_SCORE:	// TOGGLE SCORE ON/OFF
      togglescore = ( !togglescore );	/* inverse the current state     */
      break;

    case MAIN_MENU_GRID:	// TOGGLE GRID ON/OFF
      display_grid = ( !display_grid );	/* inverse the current state   */
      break;

    case MAIN_MENU_METERS:	// TOGGLE METERS ON/OFF
      toggle_meters = ( !toggle_meters );	/* inverse the current state */
      break;

    case MAIN_MENU_UNDO:	// UNDO MOVE
      load_game_from_filename ( "temp.sav" );
      break;

    case MAIN_MENU_QUIT:	// EXIT
      exit ( 0 );		/* exit chosen */
      break;

    default:			/* here for safety and debugging pusposes only */
      if ( VERBOSE )
	printf
	  ( "Error with menu entries. Invalid callback value has been passed.\n" );
      break;
    }
}

/*                                                                            */
/*                                                                            */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/******************************************************************************/





/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* mouse - reacts to mouse events sensibly                                    */
/*                                                                            */
/*                                                                            */


void
mouse ( int button, int state, int x_val, int y_val )
{
  int x = 0,
    y = 0;			/* retains the block pointed at rather than pixels */

  if ( ( state == GLUT_DOWN ) && ( button == GLUT_LEFT_BUTTON )
       && ( view == BOARD ) && ( movecount < 64 ) && ( game_on == TRUE )
       && ( ( turn == RED ) || ( !playing_against_cpu ) ) )
    {				/* if the left mouse button has been pressed, the view is a top view over */
      /* the board, the game has not reached end and has also kicked off, the   */
      /* turn is either RED's or two humans are playing                         */

      int move_made = FALSE;	// says if a legal move is recorded in log file

      if ( x_val > 65 && x_val < 435 && y_val > 65 && y_val < 435 )
	/* if the mouse pointer position was within the legal range */
	{			/* analyse the values to extract the block pointed at       */
	  if ( x_val > 65 && x_val < 65 + 46.25 * 1 )
	    x = 1;
	  if ( x_val > 65 + 46.25 * 1 && x_val < 65 + 46.25 * 2 )
	    x = 2;
	  if ( x_val > 65 + 46.25 * 2 && x_val < 65 + 46.25 * 3 )
	    x = 3;
	  if ( x_val > 65 + 46.25 * 3 && x_val < 65 + 46.25 * 4 )
	    x = 4;
	  if ( x_val > 65 + 46.25 * 4 && x_val < 65 + 46.25 * 5 )
	    x = 5;
	  if ( x_val > 65 + 46.25 * 5 && x_val < 65 + 46.25 * 6 )
	    x = 6;
	  if ( x_val > 65 + 46.25 * 6 && x_val < 65 + 46.25 * 7 )
	    x = 7;
	  if ( x_val > 65 + 46.25 * 7 && x_val < 65 + 46.25 * 8 )
	    x = 8;

	  if ( y_val > 65 && y_val < 65 + 46.25 * 1 )
	    y = 1;
	  if ( y_val > 65 + 46.25 * 1 && y_val < 65 + 46.25 * 2 )
	    y = 2;
	  if ( y_val > 65 + 46.25 * 2 && y_val < 65 + 46.25 * 3 )
	    y = 3;
	  if ( y_val > 65 + 46.25 * 3 && y_val < 65 + 46.25 * 4 )
	    y = 4;
	  if ( y_val > 65 + 46.25 * 4 && y_val < 65 + 46.25 * 5 )
	    y = 5;
	  if ( y_val > 65 + 46.25 * 5 && y_val < 65 + 46.25 * 6 )
	    y = 6;
	  if ( y_val > 65 + 46.25 * 6 && y_val < 65 + 46.25 * 7 )
	    y = 7;
	  if ( y_val > 65 + 46.25 * 7 && y_val < 65 + 46.25 * 8 )
	    y = 8;

	  if ( enable_edit )	/* if editing the board */
	    board.slot[x][y] = edit_element;	/* place the block */
	  else
	    {			/* if a move is now possibly made */
	      if ( turn == RED )	/* if the above was carried out for RED */
		{
		  if ( ( board.slot[x][y] == NONE )	/* if the slot is empty */
		       && ( reducible ( x, y, RED, board ) )
		       /* and placement in that position is legal */
		       && ( turn == RED ) )
		    /* and it is RED's turn                    */
		    {
		      save_game_to_filename ( "temp.sav" );	/* save current state for undo */
		      board.slot[x][y] = RED;	/* put the red stone     */
		      board = reduce ( x, y, board );	/* perform the reductions    */
		      movecount++;	/* increment the move count  */
		      turn = BLACK;	/* pass turn to BLACK        */
		      cpuflag = TRUE;	/* signal a move computation */
		      /* is pending                */
		      if ( keep_log_file )	/* if a log file is kept     */
			{
			  fprintf ( log_file, "RED " );
			  move_made = TRUE;	/* a log entry was added     */
			}
		    }
		}
	      if ( turn == BLACK )	/* in this case player II */
		{
		  if ( ( board.slot[x][y] == NONE )	/* if the slot is empty       */
		       && ( reducible ( x, y, BLACK, board ) )	/* and move is legal */
		       && ( turn == BLACK ) )	/* and BLACK's turn  */
		    {
		      save_game_to_filename ( "temp.sav" );	/* save current state for undo */
		      board.slot[x][y] = BLACK;	/* put the black stone     */
		      board = reduce ( x, y, board );	/* perform the reductions  */
		      movecount++;	/* increment the move count */
		      turn = RED;	/* pass the turn to RED     */
		      cpuflag = FALSE;	/* hold move computation    */
		      if ( keep_log_file )	/* is a log file is kept    */
			{
			  fprintf ( log_file, "BLACK " );
			  move_made = TRUE;	/* indicate logging         */
			}
		    }
		}
	      if ( keep_log_file && move_made )	/* if log file is active and entry */
		/* was taking place already        */
		{
		  switch ( y )	/* print the Letter coordinate according to y       */
		    {
		    case 1:
		      fprintf ( log_file, "A " );
		      break;
		    case 2:
		      fprintf ( log_file, "B " );
		      break;
		    case 3:
		      fprintf ( log_file, "C " );
		      break;
		    case 4:
		      fprintf ( log_file, "D " );
		      break;
		    case 5:
		      fprintf ( log_file, "E " );
		      break;
		    case 6:
		      fprintf ( log_file, "F " );
		      break;
		    case 7:
		      fprintf ( log_file, "G " );
		      break;
		    case 8:
		      fprintf ( log_file, "H " );
		      break;
		    default:
		      if ( debugging )
			printf
			  ( "stones put in invalid position on board\n" );
		    }
		  switch ( x )	/* and similarly for x */
		    {
		    case 1:
		      fprintf ( log_file, "1\n" );
		      break;
		    case 2:
		      fprintf ( log_file, "2\n" );
		      break;
		    case 3:
		      fprintf ( log_file, "3\n" );
		      break;
		    case 4:
		      fprintf ( log_file, "4\n" );
		      break;
		    case 5:
		      fprintf ( log_file, "5\n" );
		      break;
		    case 6:
		      fprintf ( log_file, "6\n" );
		      break;
		    case 7:
		      fprintf ( log_file, "7\n" );
		      break;
		    case 8:
		      fprintf ( log_file, "8\n" );
		      break;
		    default:
		      if ( debugging )
			printf ( "stones put in invalid position on board" );
		    }
		}
	    }			// end else - move possibly made  
	  calculate_mobility (  );	/* calculate the new mobility                  */
	  check_deadlock (  );	/* given the new mobility check for deadlocks  */
	  calculatescore (  );	/* calculate the new score                     */
	  glutPostRedisplay (  );	/* update display                              */
	}
    }
}

/*                                                                            */
/*                                                                            */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/******************************************************************************/





/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* idlefun - carries out operations when OpenGL is idle                       */
/*                                                                            */
/*                                                                            */


void
idlefun (  )
{
  ang += 3;			/* change the angle of the ring */
  glutPostRedisplay (  );	/* update display               */
}

/*                                                                            */
/*                                                                            */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/******************************************************************************/




/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* automated_moves - gets the CPU to play a move when necessary               */
/*                                                                            */
/*                                                                            */

void
automated_moves ( void )
{
  if ( game_on == TRUE )	/* if the game has commenced                       */
    {
      if ( cpuflag == TRUE )	/* if the appropriate flag is set              */
	cpu_move ( BLACK );	/* play for BLACK                              */
      else if ( gather_statistics == TRUE )	/* if RED is CPU                */
	if ( ( turn == RED ) &&	/* if RED's turn                            */
	     ( cpuflag == FALSE ) )	/* and BLACK is not required to make a move */
	  cpu_move ( RED );	/* play for RED                             */
    }
}

/*                                                                            */
/*                                                                            */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/******************************************************************************/


/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* display - the main display loop. Called from main() to do all the drawing  */
/* to the frame buffer                                                        */
/*                                                                            */
/*                                                                            */


void
display ( void )
{
  glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  /* clear the frame   */
  glLoadIdentity (  );
  gluLookAt ( eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz );
  /* set camera state   */
  if ( movecount == 64 )	/* if end of game     */
    finishoff (  );		/* finish with result */
  draw_scene (  );		/* draw the scene     */
  draw_objects (  );		/* draw the stones    */
  annotate (  );		/* annotate the frame */
  automated_moves (  );		/* carry out CPU moves */
  glutSwapBuffers (  );		/* swap buffers        */
}

/*                                                                            */
/*                                                                            */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/******************************************************************************/





/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* reshape - the reshape callback function                                    */
/* inputs - w and h which are the new width and height allocated to the frame */
/* by the window manager                                                      */
/*                                                                            */
/*                                                                            */


void
reshape ( int w, int h )
{
  glViewport ( 0, 0, ( GLsizei ) width, ( GLsizei ) height );
  /* set up view port according to width and height */
  glMatrixMode ( GL_PROJECTION );
  glLoadIdentity (  );
  /* choose projection */
  gluPerspective ( 50, ( GLfloat ) width / ( GLfloat ) height, 0.1, 140.0 );
  /* set the perspective values, see GLUT documentation for details */
  glMatrixMode ( GL_MODELVIEW );
}

/*                                                                            */
/*                                                                            */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/******************************************************************************/







/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* mouse_motion - a callback function that is invoked upon an event of a      */
/* mouse move                                                                 */
/*                                                                            */
/*                                                                            */


void
mouse_motion ( int x, int y )
{
  if ( view != START && view != HELP && view != RED_WINS && view != BLACK_WINS
       && view != DRAW && view != BEGINNER_VIEW && view != NOVICE_VIEW
       && view != EXPERT_VIEW && view != PREMASTER_VIEW
       && view != MASTER_VIEW )
    {				/* if the current view is not game view */
      view = BOARD;		/* switch to board view */
      eyex = 0;			/* set position */
      eyez = 0;
      eyey = 3.4;
      centerx = 0;		/* set centre of attention */
      centerz = 0;
      centery = 0;
      upx = 0.0;		/* Set up direction to be the +Y axis  */
      upy = 0.0;
      upz = 1.0;
      glutPostRedisplay (  );	/* update display */
    }
}

/*                                                                            */
/*                                                                            */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/******************************************************************************/





/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* keyboard - the keyboard callback function. Invoked when a key is pressed   */
/*                                                                            */
/*                                                                            */


void
keyboard ( unsigned char key, int x, int y )
{
  switch ( key )		/* inspect key value */
    {
    case 27:			/* escape pressed */
      quit_game (  );		/* quit game and close all files or connections still open */
      break;

    case '1':
      if ( debugging )
	keyboard_number = 1;	/* record board position keypress */
      view = VIEW1;		/* set new view identifier */
      eyex = 8;			/* set new view position   */
      eyez = -9;
      eyey = 6;
      upx = 0.0;		/* Set up direction to be the +Y axis  */
      upy = 1.0;
      upz = 0.0;
      adjust_look_at_center (  );	/* set centre of interest  */
      glutPostRedisplay (  );	/* update the display */
      break;

    case '2':
      if ( debugging )
	keyboard_number = 2;	/* record board position keypress */
      view = VIEW2;		/* set new view identifier */
      eyex = -10;		/* set new view position   */
      eyez = 0;
      eyey = 4;
      upx = 0.0;		/* Set up direction to be the +Y axis  */
      upy = 1.0;
      upz = 0.0;
      adjust_look_at_center (  );	/* set centre of interest  */
      glutPostRedisplay (  );	/* update the display */
      break;

    case '3':
      if ( debugging )
	keyboard_number = 3;	/* record board position keypress */
      view = VIEW3;		/* set new view identifier */
      eyex = 0;			/* set new view position   */
      eyez = 20;
      eyey = 5;
      upx = 0.0;		/* Set up direction to be the +Y axis  */
      upy = 1.0;
      upz = 0.0;
      adjust_look_at_center (  );	/* set centre of interest  */
      glutPostRedisplay (  );	/* update the display */
      break;

    case '4':
      if ( debugging )
	keyboard_number = 4;	/* record board position keypress */
      view = VIEW4;		/* set new view identifier */
      eyex = 3;			/* set new view position   */
      eyez = 3;
      eyey = 3;
      upx = 0.0;		/* Set up direction to be the +Y axis  */
      upy = 1.0;
      upz = 0.0;
      adjust_look_at_center (  );	/* set centre of interest  */
      glutPostRedisplay (  );	/* update the display */
      break;

    case '5':
      if ( debugging )
	keyboard_number = 5;	/* record board position keypress */
      view = VIEW5;		/* set new view identifier */
      eyex = 1;			/* set new view position   */
      eyez = 1;
      eyey = 3;
      upx = 0.0;		/* Set up direction to be the +Y axis  */
      upy = 1.0;
      upz = 0.0;
      adjust_look_at_center (  );	/* set centre of interest  */
      glutPostRedisplay (  );	/* update the display */
      break;

    case '6':
      if ( debugging )
	keyboard_number = 6;	/* record board position keypress */
      view = VIEW6;		/* set new view identifier */
      eyex = 20;		/* set new view position   */
      eyez = 0;
      eyey = 2;
      upx = 0.0;		/* Set up direction to be the +Y axis  */
      upy = 1.0;
      upz = 0.0;
      adjust_look_at_center (  );	/* set centre of interest  */
      glutPostRedisplay (  );	/* update the display */
      break;

    case '7':
      if ( debugging )
	keyboard_number = 7;	/* record board position keypress */
      view = VIEW7;		/* set new view identifier */
      eyex = 9;			/* set new view position   */
      eyez = 1;
      eyey = 1.5;
      upx = 0.0;		/* Set up direction to be the +Y axis  */
      upy = 1.0;
      upz = 0.0;
      adjust_look_at_center (  );	/* set centre of interest  */
      glutPostRedisplay (  );	/* update the display */
      break;

    case '8':
      if ( debugging )
	keyboard_number = 8;	/* record board position keypress */
      view = VIEW8;		/* set new view identifier */
      eyex = 10;		/* set new view position   */
      eyez = 5;
      eyey = 10;
      upx = 0.0;		/* Set up direction to be the +Y axis  */
      upy = 1.0;
      upz = 0.0;
      adjust_look_at_center (  );	/* set centre of interest  */
      glutPostRedisplay (  );	/* update the display */
      break;

    case '9':
      view = VIEW9;		/* set new view identifier */
      eyex = 2;			/* set new view position   */
      eyez = 2;
      eyey = 2;
      upx = 0.0;		/* Set up direction to be the +Y axis  */
      upy = 1.0;
      upz = 0.0;
      adjust_look_at_center (  );	/* set centre of interest  */
      glutPostRedisplay (  );	/* update the display */
      break;

    case '0':
      view = VIEW0;		/* set new view identifier */
      eyex = 0;			/* set new view position   */
      eyez = 2.0;
      eyey = 2.4;
      upx = 0.0;		/* Set up direction to be the +Y axis  */
      upy = 1.0;
      upz = 0.0;
      centerz = 0;		/* set centre of interest  */
      centery = 1;
      centerx = 0;
      glutPostRedisplay (  );	/* update the display */
      break;

    case 'h':
      if ( debugging )
	keyboard_letter = 8;
      eyex = -5;		/* set new view position   */
      eyez = 40;
      eyey = 11.0;
      upx = 0.0;		/* Set up direction to be the +Y axis  */
      upy = 1.0;
      upz = 0.0;
      centerz = 0;		/* set centre of interest  */
      centery = 11;
      centerx = -5;
      view = HELP;		/* set to help view identifier  */
      glutPostRedisplay (  );	/* update the display */
      break;

    case ' ':
      if ( debugging )		// put object
	{
	  int move_made = FALSE;	// indicates if a legal move was carried out 

	  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
	  /* make a move for color when necessary                          */

	  void make_move ( int color )
	  {
	    if ( ( board.slot[keyboard_letter][keyboard_number] == NONE )	/* if slot is empty  */
		 && ( reducible	/* and move is legal */
		      ( keyboard_letter, keyboard_number, color, board ) ) && ( turn == color ) )	/* and color's turn    */
	      {
		save_game_to_filename ( "temp.sav" );	/* save current state for undo */
		board.slot[keyboard_letter][keyboard_number] = color;
		/* put the red stone */
		board = reduce ( keyboard_letter, keyboard_number, board );
		/* reduce the board appropriately */
		movecount++;	/* increment move count  */
		if ( color == RED )
		  {
		    turn = BLACK;	/* pass turn to BLACK   */
		    cpuflag = TRUE;	/* indicate that a move needs to be made */
		    if ( keep_log_file )	/* if log file is kept */
		      {
			fprintf ( log_file, "RED " );
			move_made = TRUE;	/* indicate that entry is added to log */
		      }
		  }
		if ( color == BLACK )
		  {
		    turn = RED;	/* pass turn to RED */
		    cpuflag = FALSE;	/* no automated move required */
		    if ( keep_log_file )	/* if log file is kept */
		      {
			fprintf ( log_file, "BLACK " );
			move_made = TRUE;	/* indicate that entry is added to log */
		      }
		  }
	      }
	  }

	  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */



	  if ( ( movecount < 64 ) &&	/* if game not over  */
	       ( game_on == TRUE ) &&	/* if game has begun */
	       ( ( turn == RED ) || ( !playing_against_cpu ) ) )
	    /* if a human is involved in game */
	    {
	      if ( turn == RED )	/* if RED's turn     */
		make_move ( RED );
	      if ( turn == BLACK )	/* in this case player II */
		make_move ( BLACK );
	      if ( ( keep_log_file )	/* is log file is kept */
		   && move_made )	/* and a move has begun to be recorded */
		{
		  switch ( keyboard_number )	/* inspect the numeric component */
		    /* input by the keyboard         */
		    {
		    case 1:
		      fprintf ( log_file, "A " );	/* record the corresponding letter */
		      break;
		    case 2:
		      fprintf ( log_file, "B " );	/* record the corresponding letter */
		      break;
		    case 3:
		      fprintf ( log_file, "C " );	/* record the corresponding letter */
		      break;
		    case 4:
		      fprintf ( log_file, "D " );	/* record the corresponding letter */
		      break;
		    case 5:
		      fprintf ( log_file, "E " );	/* record the corresponding letter */
		      break;
		    case 6:
		      fprintf ( log_file, "F " );	/* record the corresponding letter */
		      break;
		    case 7:
		      fprintf ( log_file, "G " );	/* record the corresponding letter */
		      break;
		    case 8:
		      fprintf ( log_file, "H " );	/* record the corresponding letter */
		      break;
		    default:
		      if ( debugging )
			printf
			  ( "stones put in invalid position on board\n" );
		    }
		  switch ( keyboard_letter )	/* and same for literal component   */
		    /* note that array allocation is done differently */
		    /* from a standard positioning on board.          */
		    {
		    case 1:
		      fprintf ( log_file, "1\n" );	/* record the corresponding number */
		      break;
		    case 2:
		      fprintf ( log_file, "2\n" );	/* record the corresponding number */
		      break;
		    case 3:
		      fprintf ( log_file, "3\n" );	/* record the corresponding number */
		      break;
		    case 4:
		      fprintf ( log_file, "4\n" );	/* record the corresponding number */
		      break;
		    case 5:
		      fprintf ( log_file, "5\n" );	/* record the corresponding number */
		      break;
		    case 6:
		      fprintf ( log_file, "6\n" );	/* record the corresponding number */
		      break;
		    case 7:
		      fprintf ( log_file, "7\n" );	/* record the corresponding number */
		      break;
		    case 8:
		      fprintf ( log_file, "8\n" );	/* record the corresponding number */
		      break;
		    default:
		      if ( debugging )
			printf ( "stones put in invalid position on board" );
		    }
		}
	      calculate_mobility (  );	/* calculate the new mobility                 */
	      check_deadlock (  );	/* and given the mobility check for deadlocks */
	      calculatescore (  );	/* calculate score                            */
	      glutPostRedisplay (  );	/* update display                             */
	    }
	}
      view = BOARD;		/* set the view to board overview */
      eyex = 0;			/* set position */
      eyez = 0;
      eyey = 3.4;
      centerx = 0;		/* set centre of attention */
      centerz = 0;
      centery = 0;
      upx = 0.0;		/* Set up direction to be the +Y axis  */
      upy = 0.0;
      upz = 1.0;
      glutPostRedisplay (  );	/* update display */
      break;
    case 'a':
      if ( debugging )
	keyboard_letter = 1;	/* save the input alphabetic component of slot */
      break;

    case 'b':
      if ( debugging )
	keyboard_letter = 2;	/* save the input alphabetic component of slot */
      break;
    case 'c':
      if ( debugging )
	keyboard_letter = 3;	/* save the input alphabetic component of slot */
      break;
    case 'd':
      if ( debugging )
	keyboard_letter = 4;	/* save the input alphabetic component of slot */
      break;
    case 'e':
      if ( debugging )
	keyboard_letter = 5;	/* save the input alphabetic component of slot */
      break;
    case 'f':
      if ( debugging )
	keyboard_letter = 6;	/* save the input alphabetic component of slot */
      break;
    case 'g':
      if ( debugging )
	keyboard_letter = 7;	/* save the input alphabetic component of slot */
      break;
    default:
      if ( debugging )
	printf ( "unused key pressed;\n" );
      break;







    }				// end switch key
}

/*                                                                            */
/*                                                                            */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/******************************************************************************/







/*                                                                      */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
/*                     end of callbacks.c                               */
/************************************************************************/

