/* '='='=' '@' '='='='='='='='='=' '@' '='='='='='='='='=' '@' '='='='| */
/* ='='=' '@'@' '='='='='='='='=' '@'@' '='='='='='='='=' '@'@' '='='=| */
/* '='=' '@':'@' '='='='='='='=' '@':'@' '='='='='='='=' '@':'@' '='='| */
/* ='=' '@':':'@' '='='='='='=' '@':':'@' '='='='='='=' '@':':'@' '='=| */
/* '=' '@':':':'@' '='='='='=' '@':':':'@' '='='='='=' '@':':':'@' '='| */
/* =' '@':':':':'@' '='='='=' '@':':':':'@' '='='='=' '@':':':':'@' '=| */
/* ' '@':'                                                       '@' '| */
/*  '@'         3rd Year Project - ROY SCHESTOWITZ - 2002          @' | */
/* '@                                                               @'| */
/* @':':':':':':':':'@' ' '@':':':':':':':':'@' ' '@':':':':':':':':'@| */
/* ':':':':':':':':':'@' '@':':':':':':':':':'@' '@':':':':':':':':':'| */
/* :':':':':':':':':':'@'@':':':':':':':':':':'@'@':':':':':':':':':':| */
/* ':':':': : :':':':':'@':':':':': : :':':':':'@':':':':': : :':':':'| */
/*  -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
/*              Name:           omcore.c                                */
/*              Version:        0.7.8                                   */
/*              Date:           20/6/2003                               */
/*                                                                      */
/*              Main procedures and calls of the application            */
/*                                                                      */
/*  -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */

#include "omcore.h"
#include "loaders.c"
#include "drawing.c"
#include "callbacks.c"
#include "misc.c"



/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* adjust_look_at_center - sets the camera to point to the X,Y,Z origin       */
/*                                                                            */
/*                                                                            */


void
adjust_look_at_center ( void )
{
  centerx = 0;			/* zeroes the center of interest i.e. at table */
  centery = 0;
  centerz = 0;
}

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




/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* draw_objects - draws the stoned that are dynamically changing their layout */
/*                                                                            */
/*                                                                            */


void
draw_objects ( void )
{
  int i,
    j;
  GLfloat black[] = { 0.05, 0.05, 0.05, 0.0 };
  GLfloat red[] = { 1.0, 0.0, 0.0, 1.0 };


  for ( i = 1; i < 9; i++ )
    {
      for ( j = 1; j < 9; j++ )	/* for all board legal poisitions */
	{
	  if ( board.slot[i][j] != NONE )
	    {			/* requires drawing */
	      if ( board.slot[i][j] == RED )
		{
		  glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, red );
		  glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, red );
		  glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, red );
		  /* set colour to red          */
		}
	      else
		{
		  glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, black );
		  glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, black );
		  glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, black );
		  /* set colour to black         */
		}
	      glPushMatrix (  );	/* draw object */
	      glTranslatef ( 0.9 - i * 0.2, 1.05, 0.9 - j * 0.2 );
	      if ( board.slot[i][j] == turn )	/* if it is current player's stone */
		glScalef ( 0.09, 0.1, 0.09 );	/* draw large stone   */
	      else
		glScalef ( 0.08, 0.1, 0.08 );	/* draw smaller stone */
	      glutSolidSphere ( 1, 20, 20 );
	      glPopMatrix (  );
	    }
	}
    }
}

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




/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* initboard - initialises the board when a new game begins                   */
/*                                                                            */
/*                                                                            */


void
initboard ( void )
{
  int i,
    j;

  /* initialise global variables that retain state */
  cpuflag = FALSE;
  turn = RED;

  for ( i = 0; i < 10; i++ )	/* remove all stones              */
    for ( j = 0; j < 10; j++ )	/* including 0 and 10 for borders */
      board.slot[i][j] = NONE;	/* empty slot                     */
  board.slot[4][5] = RED;	/* put initial 4 stones at centre */
  board.slot[5][5] = BLACK;
  board.slot[4][4] = BLACK;
  board.slot[5][4] = RED;
  movecount = 4;		/* set the move count which includes */
  /* the first 4 stones put by deafult */
}

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




/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* initimenu - sets up the menu and takes care of the entries and their       */
/* callback value                                                             */
/*                                                                            */
/*                                                                            */


void
initmenu ( void )
{
  int load_menu,
    save_menu,
    difficulty_menu,
    main_menu,
    determinism_menu,
    customised_menu,
    game_mode_menu,
    report_menu,
    log_file_menu,
    difficulty_desc_menu,
    opening_library_menu,
    edit_board_menu;

  /* set up the main menu */
  main_menu = glutCreateMenu ( menu );
  glutAddMenuEntry ( "NEW GAME", MAIN_MENU_NEW_GAME );
  glutAddMenuEntry ( "HELP", MAIN_MENU_HELP );
  glutAddMenuEntry ( "UNDO MOVE", MAIN_MENU_UNDO );
  glutAddMenuEntry ( "DISPLAY/HIDE SCORE", MAIN_MENU_SCORE );
  glutAddMenuEntry ( "DISPLAY/HIDE GRID", MAIN_MENU_GRID );
  glutAddMenuEntry ( "DISPLAY/HIDE METERS", MAIN_MENU_METERS );

  /* set up the edit board submenu */

  edit_board_menu = glutCreateMenu ( edit_board_callback );
  glutAddMenuEntry ( "START EDITING", EDIT_START );
  glutAddMenuEntry ( "BLACK PLACEMENT", EDIT_BLACK );
  glutAddMenuEntry ( "RED PLACEMENT", EDIT_RED );
  glutAddMenuEntry ( "EMPTY PLACEMENT", EDIT_NONE );
  glutAddMenuEntry ( "FINISH EDITING", EDIT_END );

  /* set up the log file submenu */
  log_file_menu = glutCreateMenu ( log_file_callback );
  glutAddMenuEntry ( "ACTIVATE LOGGING", LOGGING_ACTIVATE );
  glutAddMenuEntry ( "DEACTIVATE LOGGING", LOGGING_DEACTIVATE );

  /* set up the game mode submenu */
  game_mode_menu = glutCreateMenu ( gamemode_callback );
  glutAddMenuEntry ( "PLAYER AGAINST CPU", GAMEMODE_CPU );
  glutAddMenuEntry ( "HUMAN AGAINST HUMAN", GAMEMODE_PLAYER );

  /* set up the computation customisation submenu */
  customised_menu = glutCreateMenu ( customise_callback );
  glutAddMenuEntry ( "LINE FACTOR", CUSTOMISED_LINE );
  glutAddMenuEntry ( "SCORE FACTOR", CUSTOMISED_SCORE );
  glutAddMenuEntry ( "MOBILITY FACTOR", CUSTOMISED_MOBILITY );
  glutAddMenuEntry ( "POSITION FACTOR", CUSTOMISED_POSITION );

  /* set up the determinism submenu */
  determinism_menu = glutCreateMenu ( determinism_callback );
  glutAddMenuEntry ( "DETERMINISTIC", DETERMINISM_ON );
  glutAddMenuEntry ( "NON-DETERMINISTIC", DETERMINISM_OFF );

  /* set up the report submenu */
  report_menu = glutCreateMenu ( report_callback );
  glutAddMenuEntry ( "ADD GAME TO DEFAULT REPORT", REPORT_ON );
  glutAddMenuEntry ( "EXCLUDE THIS GAME FROM REPORT", REPORT_OFF );

  /* set up the report submenu */
  opening_library_menu = glutCreateMenu ( opening_library_callback );
  glutAddMenuEntry ( "ENABLE OPENING LIBRARY", LIBRARY_ON );
  glutAddMenuEntry ( "DISABLE OPENING LIBRARY", LIBRARY_OFF );

  /* set up the save game submenu */
  save_menu = glutCreateMenu ( save );
  glutAddMenuEntry ( "SLOT 0", SAVE_SLOT_0 );
  glutAddMenuEntry ( "SLOT 1", SAVE_SLOT_1 );
  glutAddMenuEntry ( "SLOT 2", SAVE_SLOT_2 );
  glutAddMenuEntry ( "SLOT 3", SAVE_SLOT_3 );
  glutAddMenuEntry ( "SLOT 4", SAVE_SLOT_4 );
  glutAddMenuEntry ( "SLOT 5", SAVE_SLOT_5 );
  glutAddMenuEntry ( "SLOT 6", SAVE_SLOT_6 );
  glutAddMenuEntry ( "SLOT 7", SAVE_SLOT_7 );
  glutAddMenuEntry ( "SLOT 8", SAVE_SLOT_8 );
  glutAddMenuEntry ( "SLOT 9", SAVE_SLOT_9 );

  /* set up the load game submenu */
  load_menu = glutCreateMenu ( load );
  glutAddMenuEntry ( "SLOT 0", LOAD_SLOT_0 );
  glutAddMenuEntry ( "SLOT 1", LOAD_SLOT_1 );
  glutAddMenuEntry ( "SLOT 2", LOAD_SLOT_2 );
  glutAddMenuEntry ( "SLOT 3", LOAD_SLOT_3 );
  glutAddMenuEntry ( "SLOT 4", LOAD_SLOT_4 );
  glutAddMenuEntry ( "SLOT 5", LOAD_SLOT_5 );
  glutAddMenuEntry ( "SLOT 6", LOAD_SLOT_6 );
  glutAddMenuEntry ( "SLOT 7", LOAD_SLOT_7 );
  glutAddMenuEntry ( "SLOT 8", LOAD_SLOT_8 );
  glutAddMenuEntry ( "SLOT 9", LOAD_SLOT_9 );

  /* set up the difficulty submenu */
  difficulty_menu = glutCreateMenu ( difficulty_callback );
  glutAddMenuEntry ( "BEGINNER", DIF_CALLBACK_BEGINNER );
  glutAddMenuEntry ( "NOVICE", DIF_CALLBACK_NOVICE );
  glutAddMenuEntry ( "EXPERT", DIF_CALLBACK_EXPERT );
  glutAddMenuEntry ( "PRE-MASTER", DIF_CALLBACK_PREMASTER );
  glutAddMenuEntry ( "MASTER", DIF_CALLBACK_MASTER );

  /* set up the difficulty description submenu */
  difficulty_desc_menu = glutCreateMenu ( difficulty_description_callback );
  glutAddMenuEntry ( "ABOUT BEGINNER", DIF_DESC_CALLBACK_BEGINNER );
  glutAddMenuEntry ( "ABOUT NOVICE", DIF_DESC_CALLBACK_NOVICE );
  glutAddMenuEntry ( "ABOUT EXPERT", DIF_DESC_CALLBACK_EXPERT );
  glutAddMenuEntry ( "ABOUT PRE-MASTER", DIF_DESC_CALLBACK_PREMASTER );
  glutAddMenuEntry ( "ABOUT MASTER", DIF_DESC_CALLBACK_MASTER );

  glutSetMenu ( main_menu );	/* set the main menu to that */

  glutAddSubMenu ( "GAME MODE", game_mode_menu );	/* add the submenues */
  glutAddSubMenu ( "DIFFICULTY", difficulty_menu );
  glutAddSubMenu ( "DIFFICULTY DESCRIPTION", difficulty_desc_menu );
  glutAddSubMenu ( "CPU DETERMINISM", determinism_menu );
  glutAddSubMenu ( "OPENING LIBRARIES", opening_library_menu );
  glutAddSubMenu ( "CUSTOMISED COMP.", customised_menu );
  glutAddSubMenu ( "SAVE GAME", save_menu );
  glutAddSubMenu ( "LOAD GAME", load_menu );
  glutAddSubMenu ( "LOG FILE", log_file_menu );
  glutAddSubMenu ( "REPORT GENERATION", report_menu );
  glutAddSubMenu ( "EDIT BOARD", edit_board_menu );
  glutAddMenuEntry ( "QUIT PROGRAM", MAIN_MENU_QUIT );
  glutAttachMenu ( GLUT_RIGHT_BUTTON );	/* attach the menu to button */
}

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





/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* init - initializes the program. This function is called once at bootstrap  */
/* inputs - illum is the illumination coefficient for extra brightness        */
/*                                                                            */


void
init ( int illumination_original )
{
  float illum=illumination_original/10; /* normalise the offset */
  GLfloat redamb[] = { 0.2 * illum, 0.15 * illum, 0.15 * illum, 0.0 };	/* arrays for light properties */
  GLfloat reddif[] = { 0.2 * illum, 0.15 * illum, 0.15 * illum, 0.0 };
  GLfloat redspec[] = { 1.0 * illum, 0.6 * illum, 0.6 * illum, 0.0 };
  GLfloat redpos[] = { 4.0, 4.0, 4.0, 0.0 };
  GLfloat reddir[] = { 0.0, 0.0, 0.0 };
  GLfloat redpos2[] = { 0.0, 10.0, 10.0, 0.0 };
  GLfloat reddir2[] = { 3.0, 3.0, 3.0 };
  GLfloat cutoff2[] = { 50.0 };
  GLfloat r1[] = { 0.0 };
  GLfloat r3[] = { 0.0 };
  GLfloat r4[] = { 0.0 };


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

  void define_first_light (  )
  {
    glLightfv ( GL_LIGHT0, GL_AMBIENT, redamb );	/* set up properties     */
    glLightfv ( GL_LIGHT0, GL_DIFFUSE, reddif );
    glLightfv ( GL_LIGHT0, GL_SPECULAR, redspec );
    glLightfv ( GL_LIGHT0, GL_POSITION, redpos );
    glLightfv ( GL_LIGHT0, GL_SPOT_DIRECTION, reddir );
    glLightfv ( GL_LIGHT0, GL_SPOT_CUTOFF, cutoff2 );
    glLightfv ( GL_LIGHT0, GL_CONSTANT_ATTENUATION, r1 );
    glLightfv ( GL_LIGHT0, GL_LINEAR_ATTENUATION, r3 );
    glLightfv ( GL_LIGHT0, GL_QUADRATIC_ATTENUATION, r4 );
    glEnable ( GL_LIGHT0 );	/* and enbale that light */
  }

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

  void define_second_light (  )
  {
    glLightfv ( GL_LIGHT1, GL_AMBIENT, redamb );	/* set up properties     */
    glLightfv ( GL_LIGHT1, GL_DIFFUSE, reddif );
    glLightfv ( GL_LIGHT1, GL_SPECULAR, redspec );
    glLightfv ( GL_LIGHT1, GL_POSITION, redpos2 );
    glLightfv ( GL_LIGHT1, GL_SPOT_DIRECTION, reddir2 );
    glLightfv ( GL_LIGHT1, GL_LINEAR_ATTENUATION, r3 );
    glLightfv ( GL_LIGHT1, GL_QUADRATIC_ATTENUATION, r4 );
    glEnable ( GL_LIGHT1 );	/* and enbale that light */
  }

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

  void open_textures (  )
  {
    imagegrass = glmReadPPM ( "data/00001003.dat", &hgrass, &wgrass );
    imagecloud = glmReadPPM ( "data/00001002.dat", &hcloud, &wcloud );
    imagebrick = glmReadPPM ( "data/00001001.dat", &hbrick, &wbrick );
    imagehair = glmReadPPM ( "data/00001004.dat", &hhair, &whair );
  }

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


  if ( load_flag == FALSE )	/* if the board is not already initialised        */
    initboard (  );
  initmenu (  );
  calculate_mobility (  );	/* initilise some essential globals by calling it */
  calculatescore (  );		/* initilise some essential globals by calling it */

  glClearColor ( 1, 1, 1, 0.0 );	/* clear screen */
  glEnable ( GL_DEPTH_TEST );	/* initialise some openGL modes */
  glEnable ( GL_FRONT_AND_BACK );
  glShadeModel ( GL_SMOOTH );
  glEnable ( GL_LIGHTING );

  glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
  glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
  glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
  glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
  glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

  define_first_light (  );	/* add the lights in the scene */
  define_second_light (  );
  open_textures (  );		/* opens the texture files */

  game_on = TRUE;		/* moves are now allowed */
  save_game_to_filename ( "temp.sav" );	/* save current state for undo */

  view = START;			/* Opening screen */

  if ( VERBOSE )
    {
      printf ( "Player 2's Initial level of difficulty is " );
      if ( difficulty == BEGINNER )
	printf ( "beginner.\n" );
      if ( difficulty == NOVICE )
	printf ( "novice.\n" );
      if ( difficulty == EXPERT )
	printf ( "expert.\n" );
      if ( difficulty == PRE_MASTER )
	printf ( "pre-master.\n" );
      if ( difficulty == MASTER )
	printf ( "master.\n" );

      if ( gather_statistics )
	{
	  printf ( "Player 1's Initial level of difficulty is " );
	  if ( stat_mode_difficulty == BEGINNER )
	    printf ( "beginner.\n" );
	  if ( stat_mode_difficulty == NOVICE )
	    printf ( "novice.\n" );
	  if ( stat_mode_difficulty == EXPERT )
	    printf ( "expert.\n" );
	  if ( stat_mode_difficulty == PRE_MASTER )
	    printf ( "pre-master.\n" );
	  if ( stat_mode_difficulty == MASTER )
	    printf ( "master.\n" );
	}
    }
}

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





/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* draw_ascii_board - draws an ASCII representation of the board              */
/* inputs: the input board                                                    */
/*                                                                            */
void
draw_ascii_board ( board_map board )
{
  int i,
    j;

  printf ( "####################\n" );
  for ( i = 0; i < 10; i++ )
    {
      for ( j = 0; j < 10; j++ )
	{
	  if ( i == 0 || i == 9 || j == 0 || j == 9 )
	    {
	      if ( board.slot[i][j] != NONE )
		{
		  printf ( "Borders were overwritten at %d, %d\n", i, j );
		  exit ( 1 );
		}
	      if ( i == 0 && j == 1 )
		printf ( "# " );
	      if ( i == 0 && j == 1 )
		printf ( "A " );
	      if ( i == 0 && j == 1 )
		printf ( "B " );
	      if ( i == 0 && j == 1 )
		printf ( "C " );
	      if ( i == 0 && j == 1 )
		printf ( "D " );
	      if ( i == 0 && j == 1 )
		printf ( "E " );
	      if ( i == 0 && j == 1 )
		printf ( "F " );
	      if ( i == 0 && j == 1 )
		printf ( "G " );
	      if ( i == 0 && j == 1 )
		printf ( "H " );

	      if ( j == 0 && i == 1 )
		printf ( "#1" );
	      if ( j == 0 && i == 2 )
		printf ( "#2" );
	      if ( j == 0 && i == 3 )
		printf ( "#3" );
	      if ( j == 0 && i == 4 )
		printf ( "#4" );
	      if ( j == 0 && i == 5 )
		printf ( "#5" );
	      if ( j == 0 && i == 6 )
		printf ( "#6" );
	      if ( j == 0 && i == 7 )
		printf ( "#7" );
	      if ( j == 0 && i == 8 )
		printf ( "#8" );
	      if ( i == 9 )
		printf ( "##" );
	      if ( ( j == 9 ) && ( i != 9 ) )
		printf ( "##" );
	    }

	  else
	    {
	      if ( board.slot[j][i] == NONE )
		printf ( "  " );
	      if ( board.slot[j][i] == RED )
		printf ( "0 " );
	      if ( board.slot[j][i] == BLACK )
		printf ( "x " );
	    }
	}
      printf ( "\n" );
    }
}

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




/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* annotate_board - annotates the overhead main view                          */
/*                                                                            */
/*                                                                            */

void
annotate_board ( void )
{

  GLfloat black[] = { 0.0, 0.0, 0.0, 0.0 };	/* to hold colour values */
  GLfloat white[] = { 1.0, 1.0, 1.0, 0.0 };
  char blackscorestr[8],
    redscorestr[8];		/* to hold the score of the two sides */
  char blackmobilitystr[8],
    redmobilitystr[8];		/* to hold mobility */
  char redscoreview[16];	/* the mobility and score strings to be displayed */
  char redmobilityview[19];
  char blackscoreview[16];
  char blackmobilityview[19];
  int i;

  redscoreview[0] = 'S';	/* accommodating some parts of the string */
  redscoreview[1] = 'C';
  redscoreview[2] = 'O';
  redscoreview[3] = 'R';
  redscoreview[4] = 'E';
  redscoreview[5] = ':';
  redscoreview[6] = ' ';
  redmobilityview[7] = '\0';

  for ( i = 0; i < 8; i++ )
    blackscoreview[i] = redscoreview[i];	/* copy this */

  redmobilityview[0] = 'M';	/* accommodating some parts of the string */
  redmobilityview[1] = 'O';
  redmobilityview[2] = 'B';
  redmobilityview[3] = 'I';
  redmobilityview[4] = 'L';
  redmobilityview[5] = 'I';
  redmobilityview[6] = 'T';
  redmobilityview[7] = 'Y';
  redmobilityview[8] = ':';
  redmobilityview[9] = ' ';
  redmobilityview[10] = '\0';

  for ( i = 0; i < 11; i++ )
    blackmobilityview[i] = redmobilityview[i];	/* making a copy */

  glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, white );	/* switch colour */
  glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, white );
  glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, white );

  drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.76, 0.047, player_name );
  /* display the player name */

  if ( toggle_meters )
    {
      drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.070, 0.130, "S" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.897, 0.130, "M" );
      /* put M for mobility and S for score on meters */
    }

  glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, black );	/* switch colour */
  glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, black );
  glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, black );

  if ( playing_against_cpu )	/* if the player at top is CPU */
    drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.05, 0.92, "CPU" );
  if ( !playing_against_cpu )	/* if the player at top is human */
    drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.05, 0.92, "PLAYER" );

  /* concatenate the strings with the colon and the numbers */
  sprintf ( redscorestr, "%u", ( unsigned int ) redscore );
  strcat ( redscoreview, redscorestr );
  sprintf ( blackscorestr, "%u", ( unsigned int ) blackscore );
  strcat ( blackscoreview, blackscorestr );
  sprintf ( redmobilitystr, "%u", ( unsigned int ) red_mobility );
  strcat ( redmobilityview, redmobilitystr );
  sprintf ( blackmobilitystr, "%u", ( unsigned int ) black_mobility );
  strcat ( blackmobilityview, blackmobilitystr );

  if ( debugging )		/* in debugging mode print some information out */
    {
      printf ( "%smove number: %d\n", CLEAR, movecount );
      printf ( "upper player's turn?: %d\n", turn );
      printf ( "against cpu?: %d\n", playing_against_cpu );
      printf ( "Red score: %s", redscorestr );
      printf ( "      Black score: %s\n", blackscorestr );
      printf ( "Red mobility: %s", redmobilitystr );
      printf ( "   Black mobility: %s\n", blackmobilitystr );
      printf ( "difficulty bottom player: %d    ", stat_mode_difficulty );
      printf ( "difficulty upper player: %d \n\n", difficulty );
      draw_ascii_board ( board );
    }

  if ( togglescore && ( !enable_edit ) )	/* if score is required to be displayed */
    {
      glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, white );	/* choose colour */
      glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, white );
      glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, white );
      /* and print appropriate string */
      drawString ( GLUT_BITMAP_HELVETICA_18, 0.05, 0.077, redscoreview );
      drawString ( GLUT_BITMAP_HELVETICA_18, 0.05, 0.047, redmobilityview );

      glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, black );	/* choose colour */
      glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, black );
      glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, black );
      /* and print appropriate string */
      drawString ( GLUT_BITMAP_HELVETICA_18, 0.68, 0.925, blackscoreview );
      drawString ( GLUT_BITMAP_HELVETICA_18, 0.68, 0.895, blackmobilityview );
    }
  if ( enable_edit )		/* if editing, notify user */
    {
      drawString ( GLUT_BITMAP_HELVETICA_18, 0.05, 0.077, "EDITING" );
      drawString ( GLUT_BITMAP_HELVETICA_18, 0.68, 0.925, "EDITING" );
      switch ( edit_element )	/* inform user which is current color to be placed */
	{
	case NONE:
	  drawString ( GLUT_BITMAP_HELVETICA_18, 0.05, 0.047, "NONE" );
	  drawString ( GLUT_BITMAP_HELVETICA_18, 0.68, 0.895, "NONE" );
	  break;

	case BLACK:
	  drawString ( GLUT_BITMAP_HELVETICA_18, 0.05, 0.047, "BLACK" );
	  drawString ( GLUT_BITMAP_HELVETICA_18, 0.68, 0.895, "BLACK" );
	  break;

	case RED:
	  drawString ( GLUT_BITMAP_HELVETICA_18, 0.05, 0.047, "RED" );
	  drawString ( GLUT_BITMAP_HELVETICA_18, 0.68, 0.895, "RED" );
	  break;
	}
    }
  if ( ( turn == BLACK ) && ( ( ang % 2 ) == 1 ) )
    /* if BLACK's turn and ang is an odd number - makes it blink */
    {
      if ( playing_against_cpu )	/* CPU computing a move */
	drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.37, 0.92, "WORKING" );
      else			/* human needs to make a move */
	drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.37, 0.92, "YOU'RE UP" );
    }
  if ( ( turn == RED ) && ( ( ang % 2 ) == 1 ) )
    /* if RED's turn and ang is an odd number - makes it blink */
    {
      glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, white );	/* change colour */
      glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, white );
      glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, white );

      if ( !gather_statistics )	/* human needs to make a move */
	drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.37, 0.047, "YOU'RE UP" );
      else			/* CPU computing a move       */
	drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.37, 0.047, "WORKING" );
    }
}

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




/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* annotate_help - annotates the help screen                                  */
/*                                                                            */
/*                                                                            */

void
annotate_help ( void )
{
  GLfloat lucid[] = { 0.0, 0.0, 0.0, 0.0 };
  GLfloat lucid2[] = { 0.5, 0.5, 0.8, 0.0 };

  drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.02, 0.92, "CONTROLS" );

  glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, lucid2 );
  glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, lucid2 );
  glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, lucid2 );

  drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.88, "0..9 - CHANGE VIEW" );
  drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.84, "SPACE - TABLE VIEW" );
  drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.80,
	       "H - CALLS THIS SCREEN" );
  drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.76,
	       "RIGHT MOUSE BUTTON - MENU" );
  drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.72, "ESC - QUIT PROGRAM" );

  glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, lucid );
  glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, lucid );
  glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, lucid );

  drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.02, 0.66, "RULES" );

  glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, lucid2 );
  glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, lucid2 );
  glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, lucid2 );

  drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.62,
	       "START: EACH GAME BEGINS WITH FOUR STONES (TWO OF EACH COLOUR) ALREADY PLACED ON" );
  drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.59, "THE BOARD." );

  drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.53,
	       "PLAYING: YOU REVERSE THE COLOUR OF STONES BY SURROUNDING THEM IN A LINE SO THE" );
  drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.50,
	       "STONES FLIP OVER TO YOUR COLOUR. ALL STRAIGHT LINES ARE VALID: HORIZONTAL, VERTICAL," );
  drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.47,
	       "OR DIAGONAL. IF NO REVERSAL IS POSSIBLE, THE TURN IS PASSED." );

  drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.41,
	       "WINNING: THE GAME IS OVER WHEN NEITHER" );
  drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.38,
	       "PLAYER HAS ANY LEGAL MOVES LEFT." );
  drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.35,
	       "USUALLY, THE BOARD IS COMPLETELY FULL." );
  drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.32,
	       "WHOEVER HAS THE MOST STONES AT THE" );
  drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.29,
	       "END OF THE GAME WINS." );
}

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




/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* annotate_difficulty - displays the description of the algorithm used       */
/*                                                                            */
/*                                                                            */

void
annotate_difficulty ( void )
{
  GLfloat diffdesc_color[] = { 0.5, 0.5, 0.8, 0.0 };

  glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, diffdesc_color );
  glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, diffdesc_color );
  glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, diffdesc_color );
  switch ( view )
    {
    case BEGINNER_VIEW:
      drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.02, 0.93, "BEGINNER" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.88,
		   "This difficulty is a very basic one and it uses a very simple algorithm." );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.84,
		   "When deterministic is it meant to place a stone in the first available" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.80,
		   "and legal block on the board." );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.76,
		   "It can search the board either from the left to the right or from the top" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.72,
		   "to the bottom when searching for such a block." );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.68,
		   "When non-deterministic it attempts to place a stone in a random block where" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.64,
		   "the placement is legal. " );
      break;

    case NOVICE_VIEW:
      drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.02, 0.93, "NOVICE" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.88,
		   "ses the simplest form of evaluation." );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.84,
		   "For each possible placement, it inspects the value assigned by the evaluation" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.80,
		   "function to the board." );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.76,
		   "It will make a temporary placement of a stone for each of the placements" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.72,
		   "available and find out which is believed to be the best one." );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.68,
		   "Again, it can search the board either from the left to the right or from" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.64,
		   "the top to the bottom when searching for the best placement and, by doing" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.60,
		   "so, it may make different moves when two placements produce a board to" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.56,
		   "which the same value has been assigned by the evaluation function." );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.52,
		   "When the computation is set to be non-deterministic, the behaviour is similar," );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.48,
		   "but is affected by an offset." );
      break;

    case EXPERT_VIEW:
      drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.02, 0.93, "EXPERT" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.88,
		   "It assumes that the opponent makes his/her best move in the single turn" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.84,
		   "that is speculated here." );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.80,
		   "For each of the available placement, a temporary board structure will hold" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.76,
		   "the board state after the placement has been made, as well as two more" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.72,
		   "placements that are believed to be ideal in the short term." );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.68,
		   "Non-determinism and the form of search for available placements on the" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.64,
		   "board is performed in the same way as described under Novice." );
      break;

    case PREMASTER_VIEW:
      drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.02, 0.93, "PRE-MASTER" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.88,
		   "Looks ahead 14 moves." );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.84,
		   "Works the same way as Expert and is meant to demonstrate the influence" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.80,
		   "of over-speculation." );
      break;

    case MASTER_VIEW:
      drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.02, 0.93, "MASTER" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.88,
		   "Performs a full width search for the opponent." );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.84,
		   "It takes into account all possible moves that the opponent can make and" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.80,
		   "accumulates them sensibly." );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.76,
		   "It is, in fact, an enhancement for Expert where only one move that the" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.72,
		   "opponent can make is taken into account." );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.64,
		   "The accumulation of the values assigned to each possible move that the opponent" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.60,
		   "makes is controlled by pre-processor definitions." );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.56,
		   "The moves for which the consequences seem preferable have larger coefficients" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.52,
		   "than those for which the evaluation returned a small value i.e." );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.02, 0.48,
		   "the consequences seem unwanted. " );
      break;

    default:			/* for debugging purposes */
      if ( VERBOSE )
	printf ( "Bug in descrpition of difficulty text detected.\n" );
      break;
    }
}

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



/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* annotate - adds text on top of the scene depending on which view is enabled*/
/*                                                                            */
/*                                                                            */


void
annotate ( void )
{
  GLfloat white[] = { 1.0, 1.0, 1.0, 0.0 };
  GLfloat lucid[] = { 0.0, 0.0, 0.0, 0.0 };

  glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, lucid );
  glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, lucid );
  glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, lucid );
  switch ( view )
    {
    case DRAW:			// draw    
      {
	char blackscorestr[8];	/* retain the score of the players */
	char redscorestr[8];

	drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.300, 0.24,
		     "THIS GAME IS A DRAW" );
	sprintf ( blackscorestr, "%u", ( unsigned int ) blackscore );	/* convert int to string */
	sprintf ( redscorestr, "%u", ( unsigned int ) redscore );
	drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.500, 0.14, redscorestr );	/* print score */
	drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.600, 0.14, blackscorestr );
	if ( debugging )
	  draw_ascii_board ( board );	/* show completed game board repetitively */
      }
      break;


    case BLACK_WINS:		// black wins   
      {
	char blackscorestr[8];	/* see the above (draw) for explanations */
	char redscorestr[8];

	drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.300, 0.24,
		     "YOU LOST THE GAME" );
	sprintf ( blackscorestr, "%u", ( unsigned int ) blackscore );
	sprintf ( redscorestr, "%u", ( unsigned int ) redscore );
	drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.500, 0.14, redscorestr );
	drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.600, 0.14, blackscorestr );
	if ( debugging )
	  draw_ascii_board ( board );
      }
      break;

    case RED_WINS:		// red wins
      {
	char blackscorestr[8];	/* see the above (draw) for explanations */
	char redscorestr[8];

	drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.300, 0.24,
		     "YOU WON THE GAME" );
	sprintf ( blackscorestr, "%u", ( unsigned int ) blackscore );
	sprintf ( redscorestr, "%u", ( unsigned int ) redscore );
	drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.500, 0.14, redscorestr );
	drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.600, 0.14, blackscorestr );
	if ( debugging )
	  draw_ascii_board ( board );
      }
      break;

    case START:		// opening screen
      eyex = 25.0;		/* set camera position */
      eyez = 20.0;
      eyey = 5.0;
      upx = 0.0;		/* Set up direction to be the +Y axis  */
      upy = 1.0;
      upz = 0.0;
      centerz = -20;		/* set centre of interest */
      centerx = -8;
      centery = -10.0;
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.41, 0.89,
		   "PRESS SPACE OR 0..9 TO START" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.41, 0.86,
		   "PRESS H FOR HELP" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.41, 0.83,
		   "PRESS ESC TO QUIT PROGRAM" );
      drawString ( GLUT_BITMAP_TIMES_ROMAN_10, 0.75, 0.02,
		   "(C) ROY SCHESTOWITZ" );
      glutPostRedisplay (  );
      break;

    case HELP:			// help 
      annotate_help (  );
      break;

    case BOARD:
      annotate_board (  );
      break;

    case VIEW0:
      drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.81, 0.9, "VIEW #0" );
      break;

    case VIEW1:
      glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, white );
      glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, white );

      drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.70, 0.90, "VIEW #1" );
      break;

    case VIEW2:
      glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, white );
      glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, white );

      drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.77, 0.008, "VIEW #2" );
      break;

    case VIEW3:
      drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.77, 0.008, "VIEW #3" );
      break;

    case VIEW4:
      glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, white );
      glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, white );

      drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.35, 0.008, "VIEW #4" );
      break;

    case VIEW5:
      drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.77, 0.008, "VIEW #5" );
      /* apply rotation to the camera view by */
      /* increasing and decreasing x and z    */
      if ( eyex > -2 )
	eyex = eyex - 0.1;
      if ( eyez > -2 )
	eyez = eyez - 0.1;

      break;

    case VIEW6:
      drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.77, 0.008, "VIEW #6" );
      break;

    case VIEW7:
      glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, white );
      glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, white );

      drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.10, 0.008, "VIEW #7" );
      break;

    case VIEW8:
      drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.75, 0.90, "VIEW #8" );
      break;

    case VIEW9:
      glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, white );
      glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, white );
      if ( eyez < 3 )
	eyez = eyez + 0.1;	/* dynamic view */
      if ( eyey < 3 )
	eyey = eyey + 0.1;
      drawString ( GLUT_BITMAP_TIMES_ROMAN_24, 0.77, 0.008, "VIEW #9" );
      break;

    case BEGINNER_VIEW:
    case NOVICE_VIEW:
    case EXPERT_VIEW:
    case PREMASTER_VIEW:
    case MASTER_VIEW:
      annotate_difficulty (  );
      break;

    default:			/* for debugging purposes */
      if ( VERBOSE )
	printf
	  ( "View was unexpectedly bound to an invalid value. Annotation cannot proceed. \n " );
    }

}

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





/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* set_name_of_player - called when the name of the player is entered and     */
/* to record that name                                                        */
/* inputs: the pointer to the characters representing that name               */
/*                                                                            */
/*                                                                            */

void
set_name_of_player ( char *name )
{
  printf ( "Welcome %s\n", name );
  player_name = name;		/* update global string */
}

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





/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* Prints some brief debugging instructions                                   */
/*                                                                            */


void
display_debugging_instructions ( void )
{
  printf ( "\n %s Version %s (%s)\n", PACKAGE, VERSION, DATE );
  printf ( " Bug reports and feature requests: Schestowitz@cs.man.ac.uk\n" );
  printf ( "\n" );
  printf ( " Debugging Mode\n" );
  printf ( " ==============\n\n" );
  printf ( " 1) Press 0-9 or space to begin the game. \n" );
  printf ( " 2) Press 1-8 to select the vertical component of the slot. \n" );
  printf
    ( " 3) Press A-H to select the horizontal component of the slot. \n" );
  printf ( " 4) Press space to place a stone. \n" );
  printf
    ( " *) To open the game menu, press the right mouse button inside \n" );
  printf ( "    the small frame. \n\n " );
}

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





/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* display_help - displays the command line option to the user and quits      */
/*                                                                            */
/*                                                                            */



void
display_help ( void )
{
  printf ( "\n %s Version %s (%s)\n", PACKAGE, VERSION, DATE );
  printf ( " Final year project - University of Manchester\n" );
  printf ( " Copyright %d Roy Schestowitz\n", YEAR );
  printf ( " Author: Roy Schestowitz\n" );
  printf ( " Bug reports and feature requests: sch@danielsorogon.com\n" );
  printf ( "\n" );
  printf ( " Usage: OM [options]\n" );
  printf ( "\n" );
  printf ( "   --help\n" );
  printf ( "   -h\n" );
  printf ( "   -?                display this help message\n" );
  printf ( "   -v                be verbose\n" );
  printf ( "   -q                be quiet\n" );
  printf ( "   -e                exit game when it is finished\n" );
  printf ( "   -g                do not display the board grid\n" );
  printf ( "   -m                do not display the game meters\n" );
  printf ( "   -d                debugging mode - ASCII interface\n" );
  printf ( "   -dh               debugging mode with instructions\n" );
  printf ( "\n" );
  printf ( "   -l   <filename>   load a game from a .sav file\n" );
  printf ( "   -log <filename>   keep a game log in <filename>\n" );
  printf
    ( "   -rep <filename>   add this game to the report in <filename>\n" );
  printf ( "\n" );
  printf ( "   -2p               2 player mode. Upper player is human.\n" );
  printf ( "   -dif <difficulty> change the initial game difficulty\n" );
  printf ( "   -s   <difficulty> gather statistics by letting CPU\n" );
  printf ( "                     play itself (debugging purposes)\n\n" );
  printf
    ( "         difficulty in {beg, beginner, nov, novice, exp, expert,\n" );
  printf
    ( "                        pre, premaster, pre-master, mas, master}\n" );
  printf ( "\n" );
  printf ( "   -cp               Disable position evaluation.\n" );
  printf ( "   -cm               Disable mobility evaluation.\n" );
  printf ( "   -cs               Disable score evaluation.\n" );
  printf ( "   -cl               Disable lines evaluation.\n" );
  printf ( "\n" );
  printf ( "   -r   <seed>       apply randomisation for non-determinism\n" );
  printf ( "   -i   <value>      illumination boost\n" );
  printf ( "  		         value between 1 and 50 (10 by default)\n" );
  printf ( "   -o                Use opening library\n" );
  printf ( "   -n   <name>       change the name of a player\n\n" );
  
  exit ( 0 );
}

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




/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* process_comman_line - a function to process the comman line arguments      */
/* inputs - the arguments and the number of arguments                         */
/*                                                                            */
/*                                                                            */


void
process_command_line ( int argc, char *argv[] )
{
  int count = 1;		/* arguments index */
  int comp;			/* comparison temporary value */
  char *log_file = "";		/* name of log file */
  char *load_file = "";		/* name of file to load */
  int log_flag = FALSE;		/* log file defaults to unused */
  char *commandstrings[] = {
    "--help", "-h", "-?", "-l", "-dh", "-v", "-q", "-n", "-dif", "-s", "-log",
    "-e", "-r", "-rep", "-g", "-m", "-d", "-2p", "-cp", "-cm", "-cs", "-cl",
    "-o", "-i", NULL
  };

  while ( argv[count] > 0 )	/* while more arguments to process */
    {
      if ( '-' != *argv[count] )	/* if valid prefix only */
	{
	  printf ( "\nUnknown option %s\n", argv[count] );
	  display_help (  );
	}

      comp = 0;			/* initilaise this temporary index */
      while ( comp != 24 && ( strcasecmp ( commandstrings[comp], argv[count] ) ) )	//NOTE: dynamic value
	/* while end of known argument list not reached */
	if ( !commandstrings[comp] )
	  {
	    printf ( "Unknown option  %s\n", argv[count] );
	    exit ( 1 );
	  }
	else
	  comp++;		/* check next known option */
      switch ( comp )		/* inpect the match (or the non-existent one) */
	{
	case 0:
	case 1:
	case 2:		//help
	  display_help (  );
	  break;		// for safety
	case 3:		// load a game
	  if ( argv[count + 1] )	/* see if another argument is there */
	    if ( '-' != *argv[count + 1] )	/* and it is not an option */
	      {
		load_flag = TRUE;
		load_file = argv[++count];	/* get file name */
	      }

	  break;
	case 4:		// Debugging
	  debugging = TRUE;
	  display_debugging_instructions (  );
	  break;
	case 5:		//Verbose -v
	  VERBOSE = TRUE;
	  break;
	case 6:		//Quiet -q
	  VERBOSE = FALSE;
	  break;
	case 7:		//Change Name -n
	  if ( '-' != *argv[count + 1] )	/* if the name is there */
	    set_name_of_player ( argv[++count] );
	  break;
	case 8:		// Set Difficulty

	  if ( '-' != *argv[count + 1] )	/* if a difficulty is there */
	    set_difficulty ( argv[++count] );
	  break;
	case 9:		// gather statistics

	  if ( '-' != *argv[count + 1] )	/* if difficulty is there */
	    set_up_stat_mode_difficulty ( argv[++count] );
	  gather_statistics = TRUE;
	  break;
	case 10:		// log file
	  {
	    if ( '-' != *argv[count + 1] )	/* if filename of log is there */
	      if ( !keep_log_file )	/* if log file has not been opened yet */
		{
		  log_file = argv[++count];	/* get the filename */
		  log_flag = TRUE;	/* set global flag */
		}
	  }
	  break;
	case 11:		// exit when finished game
	  exit_game_when_finished = TRUE;
	  break;
	case 12:		// non-determinism enabled
	  non_determinism = TRUE;
	  if ( '-' != *argv[count + 1] )	/* check if seed is there */
	    srandom ( ( unsigned int ) *( argv[++count] ) );
	  /* seed the random sequesnce according to the given seed */
	  else
	    {
	      printf ( "Error with input seed.\n" );
	      exit ( 1 );
	    }
	  break;
	case 13:		// add to report file
	  if ( '-' != *argv[count + 1] )	/* see if report filename is given */
	    open_report ( argv[++count] );	/* open the report file */
	  add_to_report_file = TRUE;	/* and update the global accordingly */
	  break;
	case 14:		/* do not display grid */
	  display_grid = FALSE;
	  break;
	case 15:		/* do not display meters */
	  toggle_meters = FALSE;
	  break;
	case 16:		// Debugging w/o instructions
	  debugging = TRUE;
	  break;
	case 17:		// Human vs. human mode
	  playing_against_cpu = FALSE;
	  break;
	case 18:		// Computation option
	  enable_position_eval = FALSE;
	  break;
	case 19:		// Computation option
	  enable_mobility_eval = FALSE;
	  break;
	case 20:		// Computation option
	  enable_score_eval = FALSE;
	  break;
	case 21:		// Computation option
	  enable_line_eval = FALSE;
	  break;
	case 22:		// Opening Library enabled
	  use_opening_library = TRUE;
	  init_opening_library (  );
	  break;
	case 23:		// illumination
	  {
	    if ( '-' != *argv[count + 1] )	/* if value is there */
	     {
              illum_val=atoi(argv[++count]);
	      if (illum_val>50 || illum_val<1)
	       printf ( "\nInvalid illumination coefficient value\n" );
	     }
	    else
	      printf ( "\nMissing illumination coefficient\n" ); 
	  }
	  break;
	default:
	  printf ( "\nCommand parameter Error\n" );
	  display_help (  );
	  break;		// for safety
	}			//end switch
      count++;
    }				// end while

  if ( load_flag == TRUE )	/* log file if necessary now at the end of the analysis */
    if ( !( load_game_from_filename ( load_file ) ) )	// if cannot open successfully
      {
	if ( VERBOSE )
	  printf ( "Error opening %s.\n", load_file );
	exit ( 1 );
      }

  if ( log_flag == TRUE )	/* open log file if necessary now at the end of the analysis */
    open_log_file ( log_file );
  if ( debugging == TRUE )	/* if in debugging mode */
    if ( ( VERBOSE ) && ( !gather_statistics ) )	/* if verbose and human is involved */
      display_debugging_instructions (  );	/* display instructions */
}

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






/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/*  set_difficulty - sets up the difficulty of player 2                       */
/*                                                                            */
/*                                                                            */

void
set_difficulty ( char *diff )
{
  if ( ( strcasecmp ( diff, "beginner" ) == 0 )
       || ( strcasecmp ( diff, "beg" ) == 0 ) )
    difficulty = BEGINNER;
  else
    if ( ( strcasecmp ( diff, "novice" ) == 0 )
	 || ( strcasecmp ( diff, "nov" ) == 0 ) )
    difficulty = NOVICE;
  else
    if ( ( strcasecmp ( diff, "expert" ) == 0 )
	 || ( strcasecmp ( diff, "exp" ) == 0 ) )
    difficulty = EXPERT;
  else
    if ( ( strcasecmp ( diff, "pre-master" ) == 0 )
	 || ( strcasecmp ( diff, "pre_master" ) == 0 )
	 || ( strcasecmp ( diff, "premaster" ) == 0 )
	 || ( strcasecmp ( diff, "pre" ) == 0 ) )
    difficulty = PRE_MASTER;
  else
    if ( ( strcasecmp ( diff, "master" ) == 0 )
	 || ( strcasecmp ( diff, "mas" ) == 0 ) )
    difficulty = MASTER;
  else
    difficulty = BEGINNER;	/* default */
}

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






/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/*  set_up_stat_mode_difficulty - sets up the difficulty of player 1 when     */
/*  gathering statistics                                                      */
/*                                                                            */
/*                                                                            */

void
set_up_stat_mode_difficulty ( char *diff )
{
  if ( ( strcasecmp ( diff, "beginner" ) == 0 )
       || ( strcasecmp ( diff, "beg" ) == 0 ) )
    stat_mode_difficulty = BEGINNER;
  else
    if ( ( strcasecmp ( diff, "novice" ) == 0 )
	 || ( strcasecmp ( diff, "nov" ) == 0 ) )
    stat_mode_difficulty = NOVICE;
  else
    if ( ( strcasecmp ( diff, "expert" ) == 0 )
	 || ( strcasecmp ( diff, "exp" ) == 0 ) )
    stat_mode_difficulty = EXPERT;
  else
    if ( ( strcasecmp ( diff, "pre-master" ) == 0 )
	 || ( strcasecmp ( diff, "pre_master" ) == 0 )
	 || ( strcasecmp ( diff, "premaster" ) == 0 )
	 || ( strcasecmp ( diff, "pre" ) == 0 ) )
    stat_mode_difficulty = PRE_MASTER;
  else
    if ( ( strcasecmp ( diff, "master" ) == 0 )
	 || ( strcasecmp ( diff, "mas" ) == 0 ) )
    stat_mode_difficulty = MASTER;
  else
    stat_mode_difficulty = BEGINNER;	/* default */
}

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




/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* main - the main function. called when the program is started.              */
/* inputs - the arguments and the number of arguments from the command line   */
/*                                                                            */
/*                                                                            */


int
main ( int argc, char **argv )
{
  glutInit ( &argc, argv );
  glutInitDisplayMode ( GLUT_DOUBLE | GLUT_DEPTH );
  glEnable ( GL_DEPTH_TEST );
  process_command_line ( argc, argv );	/* process the given command-line arguments */
  if ( !debugging )
    glutInitWindowSize ( width, height );	/* set the window size       */
  else
    glutInitWindowSize ( 50, 50 );	/* small window when debugging */
  glutInitWindowPosition ( 100, 100 );	/* set window position         */
  glutCreateWindow ( "Othello Master - (C) Roy Schestowitz 2003" );
  init ( illum_val );			/* initialise the program      */
  glutDisplayFunc ( display );	/* register callback functions */
  glutReshapeFunc ( reshape );
  glutKeyboardFunc ( keyboard );
  glutIdleFunc ( idlefun );
  glutPassiveMotionFunc ( mouse_motion );
  glutMouseFunc ( mouse );
  if ( VERBOSE )
    printf ( "Starting Othello Master\n" );
  glutMainLoop (  );		/* invoke main GLUT loop       */
  return 0;
}

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


/******************************************************************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* quit_game - the main exit procedure. Close any connection and files here   */
/*                                                                            */
/*                                                                            */

void
quit_game ( void )
{
  if ( keep_log_file )
    fclose ( log_file );	// close the log file if any active
  exit ( 0 );
}

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



/*                                                                      */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
/*                     end of omcore.c                                  */
/************************************************************************/

