int min_value(char piece1, char piece2, int a, int b, char **board, int currstate) {
  int utility=terminal_test(board), x, y, minimax=100000, temp;

  //if bottom of tree reached
  if (terminal_test(board)!=INCOMPLETE)	{
    //return utility value of the board
    return utility;
  }
	
  for (x=0; x<3; x++) {
    for (y=0; y<3; y++) {
      if (board[x][y]==BLANK) {							
        //for each successor of the current board
	board[x][y]=piece1;
	//get minimax value of its successor
	temp=max_value(piece2, piece1, a, b, board, 0); 
	//find minimum of all minimax values of its successors
	if (temp<minimax) {							
	  minimax=temp;	
	}
	//if minimax value of a successor <= alpha of its predecessor
	if (minimax<=a) {
          //skip this node since predecessor will never choose this node
	  board[x][y]=BLANK;						
	  return minimax;
	}	
	b=min(b, minimax);	
	board[x][y]=BLANK;	
      }	
    }
  }
  return minimax;	
}
/**
 * Perform a cutoff test
 *
 * @param state the state of the game
 * @param depth the current depth
 * @return 1 if depth has exceeded max depth, or if terminal state has been reached, else return 0
 */
int cutoff_test( const struct State * state, int depth )
{
    if( depth > MAX_DEPTH )
        return 1;

    return terminal_test( state );
}
int max_value(char piece1, char piece2, int a, int b, char **board, int currstate) {
  int utility=terminal_test(board), x, y, minimax=-100000, temp, cont=0;

  //if bottom of tree reached
  if (terminal_test(board)!=INCOMPLETE) {
    //return utility value of the board
    return utility;
  }
	
  for (x=0; x<3; x++) {
    for (y=0; y<3; y++) {
      //for each successor of the current board
      if (board[x][y]==BLANK) {								
        board[x][y]=piece1;
        //get minimax value of its successor
        temp=min_value(piece2, piece1, a, b, board, 0);     
        //find maximum of all minimax values of its successors
	if (temp>minimax) {									
	  minimax=temp;
	  cont = 1;
	}	
	//if minimax value of a successor >= beta of its predecessor,
	if (minimax>=b) {							
	  //skip this node since predecessor will never choose this node	
	  board[x][y]=BLANK;							
	  return minimax;
	}	
	a=max(a, minimax);
	//if current state's successor minimax is the maximum value so far
	if (currstate && cont) {							
	  //assign corresponding x- and y- coordinates	
	  comp_x=x; 									
	  comp_y=y;	
	}
	board[x][y]=BLANK;	
      }			
    }
  }
  return minimax;	
}
/**
 * Computer vs computer
 *
 * The computer plays itself
 * @param string for filename
 * @param agent_color
 * @return 1 if black wins, else return 0
 */
int computer_vs_computer( char *file, char agent_color )
{
    char board[ SIZE ][ SIZE ];

    /* set up board */
    setup_board(file,board);

    /* create a new state */
    struct State * state = new_state( board, 'B' );
    struct State * temp_state;

    /* start game */
    print_state( state );
    temp_state = computer_player_first( state );
    Free( state, sizeof( struct State ) );
    state = temp_state;

    /* second move */
    printf( "\n" );
    print_state( state );
    temp_state = computer_player_second( state );
    Free( state, sizeof( struct State ) );
    state = temp_state;

    /* regular game */
    for( ;; )
    {
        printf( "\n" );
        print_state( state );

        //printf( "\n>> Mem usage before: %lu\n", memory_usage() );
        temp_state = computer_player( state );
        Free( state, sizeof( struct State ) );
        state = temp_state;
        //printf( "\n>> Mem usage after: %lu\n", memory_usage() );

        if( terminal_test( state ) == 1 )
        {
            printf( "\n" );
            print_state( state );
            printf( "\nNo moves left!... \n" );
            printf( "\n%c wins!!!\n", opposite_player( state->player ) );
            Free( state, sizeof( struct State ) );
            break;
        }
    }

    return opposite_player( state->player ) == 'B';
}
/**
 * Human vs compter
 *
 * Plays vs the computer
 * @param string for filename
 * @param agent_color the agent color
 * @return 1 if human player won, else return 0
 */
int human_vs_computer( char *file, char agent_color )
{
    char board[ SIZE ][ SIZE ];
    char player = toupper( agent_color );

    /* set up board */
    setup_board(file,board);


    /* create a new state */
    struct State * state = new_state( board, 'B' );

    print_state( state );

    /* START GAME */

    /* start game ( B first ) */
    struct State * temp_state;
    if( player == state->player )
    {
        temp_state = computer_player_first( state );
        Free( state, sizeof( struct State ) );
        state = temp_state;
    }
    else
    {
        temp_state = human_player_first( state );
        Free( state, sizeof( struct State ) );
        state = temp_state;
    }

    /* second move */
    printf( "\n" );
    print_state( state );
    if( player == state->player )
    {
        temp_state = computer_player_second( state );
        Free( state, sizeof( struct State ) );
        state = temp_state;
    }
    else
    {
        temp_state = human_player_second( state );
        Free( state, sizeof( struct State ) );
        state = temp_state;
    }

    /* regular game */
    for( ;; )
    {
        printf( "\n" );
        print_state( state );

        if( state->player == player )
        {
            temp_state = computer_player( state );
            Free( state, sizeof( struct State ) );
            state = temp_state;
        }
        else
        {
            temp_state = human_player( state );
            Free( state, sizeof( struct State ) );
            state = temp_state;
        }

        if( terminal_test( state ) == 1 )
        {
            printf( "\n\n%c wins!!!\n", opposite_player( state->player ) );
            break;
        }
    }

    return player == opposite_player( state->player );
}
int human_vs_computer( char *file )
{
    char input[ INPUT_SIZE ];
    char board[ SIZE ][ SIZE ];
    char player;

    /* set up board */
    /*int _player = 0;
    for( int i = 0; i < 8 ; i++ )
    {
        for( int j = 0; j < 8; j++ )
        {
            if( _player == 0 )
            {
                board[i][j] = 'B';
                _player = 1;
            }
            else
            {
                board[i][j] = 'W';
                _player = 0;
            }
        }
        if( _player == 0 )
            _player = 1;
        else
            _player = 0;
        }*/
    setup_board(file,board);


    /* choose player */
    do
    {
        printf( "Please choose a player ('B' or 'W' ): " );
        fgets( input, INPUT_SIZE, stdin );
    }
    while( input[ 0 ] != 'W' && input[ 0 ] != 'B' );
    player = input[0];

    /* create a new state */
    struct State * state = new_state( board, 'B' );

    print_state( state );

    /* START GAME */

    /* start game ( B first ) */
    struct State * temp_state;
    if( player == 'B' )
    {
        temp_state = human_player_first( state );
        Free( state, sizeof( struct State ) );
        state = temp_state;
    }
    else
    {
        temp_state = computer_player_first( state );
        Free( state, sizeof( struct State ) );
        state = temp_state;
    }

    /* second move */
    printf( "\n" );
    print_state( state );
    if( player == 'W' )
    {
        temp_state = human_player_second( state );
        Free( state, sizeof( struct State ) );
        state = temp_state;
    }
    else
    {
        temp_state = computer_player_second( state );
        Free( state, sizeof( struct State ) );
        state = temp_state;
    }

    /* regular game */
    for( ;; )
    {
        printf( "\n" );
        print_state( state );

        if( state->player == player )
        {
            temp_state = human_player( state );
            Free( state, sizeof( struct State ) );
            state = temp_state;
        }
        else
        {
            temp_state = computer_player( state );
            Free( state, sizeof( struct State ) );
            state = temp_state;
        }

        if( terminal_test( state ) == 1 )
        {
            printf( "%c wins!!!\n", opposite_player( state->player ) );
            break;
        }
    }

    return 1;
}
int computer_vs_computer( char *file )
{
    char board[ SIZE ][ SIZE ];

    /* set up board */
    /*int _player = 0;
    for( int i = 0; i < 8 ; i++ )
    {
        for( int j = 0; j < 8; j++ )
        {
            if( _player == 0 )
            {
                board[i][j] = 'B';
                _player = 1;
            }
            else
            {
                board[i][j] = 'W';
                _player = 0;
            }
        }
        if( _player == 0 )
            _player = 1;
        else
            _player = 0;
        }*/
    setup_board(file,board);


    /* create a new state */
    struct State * state = new_state( board, 'B' );
    struct State * temp_state;

    /* start game */
    print_state( state );
    temp_state = computer_player_first( state );
    Free( state, sizeof( struct State ) );
    state = temp_state;

    /* second move */
    printf( "\n" );
    print_state( state );
    temp_state = computer_player_second( state );
    Free( state, sizeof( struct State ) );
    state = temp_state;

    /* regular game */
    for( ;; )
    {
        printf( "\n" );
        print_state( state );

        printf( "\n>> Mem usage before: %ld\n", memory_usage() );
        temp_state = computer_player( state );
        Free( state, sizeof( struct State ) );
        state = temp_state;
        printf( ">> Mem usage after: %ld\n", memory_usage() );

        if( terminal_test( state ) == 1 )
        {
            printf( "\n" );
            print_state( state );
            printf( "\nNo moves left!... \n" );
            printf( "\n%c wins!!!\n", opposite_player( state->player ) );
            Free( state, sizeof( struct State ) );
            break;
        }
    }
    return 1;
}
int human_vs_computer( void )
{
    char input[ INPUT_SIZE ];
    char board[ SIZE ][ SIZE ];
    char player;

    /* set up board */
    int _player = 0;
    for( int i = 0; i < 8 ; i++ )
    {
        for( int j = 0; j < 8; j++ )
        {
            if( _player == 0 )
            {
                board[i][j] = 'B';
                _player = 1;
            }
            else
            {
                board[i][j] = 'W';
                _player = 0;
            }
        }
        if( _player == 0 )
            _player = 1;
        else
            _player = 0;
    }

    /* choose player */
    do 
    {
        printf( "Please choose a player ('B' or 'W' ): " );
        fgets( input, INPUT_SIZE, stdin );
    }
    while( input[ 0 ] != 'W' && input[ 0 ] != 'B' );
    player = input[0];

    /* create a new state */
    struct State * state = new_state( board, 'B' );

    /* create a new game node */
    struct GameNode * root = new_game_node( state, NULL );

    print_state( root->state );

    /* START GAME */

    /* start game ( B first ) */
    struct GameNode * current_state;
    struct GameNode * temp_state;
    if( player == 'B' )
    {
        temp_state = human_player_first( root );
        current_state = new_game_node( temp_state->state, NULL );
        delete_game_node( temp_state ); 
    }
    else
    {
        temp_state = computer_player_first( root );
        current_state = new_game_node( temp_state->state, NULL );
        delete_game_node( temp_state ); 
    }

    /* second move */
    printf( "\n" );
    print_state( current_state->state );
    if( player == 'W' )
    {
        current_state = human_player_second( current_state );
        current_state = new_game_node( temp_state->state, NULL );
        delete_game_node( temp_state ); 
    }
    else
    {
        current_state = computer_player_second( current_state );
        current_state = new_game_node( temp_state->state, NULL );
        delete_game_node( temp_state ); 
    }

    /* regular game */
    for( ;; )
    {
        printf( "\n" );
        print_state( current_state->state );

        if( current_state->state->player == player )
        {
            temp_state = human_player( current_state );
            current_state = new_game_node( temp_state->state, NULL );
            delete_game_node( temp_state ); 
        }
        else
        {
            temp_state = computer_player( current_state );
            current_state = new_game_node( temp_state->state, NULL );
            delete_game_node( temp_state ); 
        }

        if( terminal_test( current_state->state ) == 1 )
        {
            printf( "%c wins!!!\n", opposite_player( current_state->state->player ) );
            break;
        }
    }

    return 1;
}
int computer_vs_computer( void )
{
    char board[ SIZE ][ SIZE ];

    /* set up board */
    int _player = 0;
    for( int i = 0; i < 8 ; i++ )
    {
        for( int j = 0; j < 8; j++ )
        {
            if( _player == 0 )
            {
                board[i][j] = 'B';
                _player = 1;
            }
            else
            {
                board[i][j] = 'W';
                _player = 0;
            }
        }
        if( _player == 0 )
            _player = 1;
        else
            _player = 0;
    }
    /* create a new state */
    struct State * state = new_state( board, 'B' );

    /* create a new game node */
    struct GameNode * root = new_game_node( state, NULL );

    print_state( root->state );

    /* START GAME */

    /* start game ( B first ) */
    struct GameNode * current_state;
    struct GameNode * temp_state;

    temp_state = computer_player_first( root );
    current_state = new_game_node( temp_state->state, NULL );
    delete_game_node( temp_state ); 

    /* second move */
    printf( "\n" );
    print_state( current_state->state );
    temp_state = computer_player_second( current_state );
    current_state = new_game_node( temp_state->state, NULL );
    delete_game_node( temp_state ); 

    /* regular game */
    for( ;; )
    {
        printf( "\n" );
        print_state( current_state->state );

        printf( ">> Mem usage before: %ld\n", memory_usage() );
        temp_state = computer_player( current_state );
        current_state = new_game_node( temp_state->state, NULL );
        delete_game_node( temp_state ); 
        printf( ">> Mem usage after: %ld\n", memory_usage() );

        if( terminal_test( current_state->state ) == 1 )
        {
            printf( "\n" );
            print_state( current_state->state );
            printf( "\nNo moves left!... \n" );
            printf( "\n%c wins!!!\n", opposite_player( current_state->state->player ) );
            delete_game_node( current_state );
            break;
        }
    }
    return 1;
}