Esempio n. 1
0
void	else_of_player_one(t_all *a)
{
  a->nb1 = 0;
  my_printf("\033[31mChoisissez une ligne valide\033[0m\n");
  print_allum(a);
  player_one(a);
}
int zz::map::solomax( int iterations, bool use_heuristic ) {
#ifdef DEBUG_MAP
    fprintf( stderr, "%*s(%d,%d) vs (%d,%d) solomax:\n", ( 10 - iterations ) * 2, "", player_one().x( ), player_one().y( ), player_two().x( ), player_two().y( ) );
#endif
    _max = INT_MIN;
    for( int i = 0; i < 4; ++i ) {
        zz::map::location player_one = _player_one.adjacent( i );
        if( is_wall( player_one ) ) {
            _mins[i] = INT_MIN;
        } else {
            if( iterations > 0 ) {
                // look ahead at the next solomax
                int result = 0;
                // save the current state
                int max = _max;
                int mins[4];
                for( int k = 0; k < 4; ++k ) {
                    mins[k] = _mins[k];
                }
                zz::map::location player_one_original( _player_one );
                // update the map
                set_player_one( player_one );
                // get the next solomax
                result = solomax( iterations - 1, use_heuristic ) * 0.999;
                // restore the current state
                set_player_one( player_one_original );
                set_is_wall( player_one, false );
                _max = max;
                for( int k = 0; k < 4; ++k ) {
                    _mins[k] = mins[k];
                }
                _mins[i] = result;
            } else {
                ++__minimax_leafs;
                if( use_heuristic ) {
                    _mins[i] = area_available_from( player_one ) * 128;
                } else {
                    _mins[i] = 0;
                }
            }
        }
        if( _mins[i] > _max ) {
            _max = _mins[i];
        }
    }
#ifdef DEBUG_MAP
    fprintf( stderr, "%*s(%d,%d) vs (%d,%d) solomax.mins(): [", ( 10 - iterations ) * 2, "", player_one().x( ), player_one().y( ), player_two().x( ), player_two().y( ) );
    for( int i = 0; i < 4; ++i ) {
        fprintf( stderr, "%d:%d", i, _mins[i] );
        if( i != 3 ) fprintf( stderr, ", " );
    }
    fprintf( stderr, "] (%d)\n", _max );
#endif
    return _max;
}
int zz::map::minimax( int iterations, bool use_heuristic ) {
#ifdef DEBUG_MAP
    fprintf( stderr, "%*s(%d,%d) vs (%d,%d) minimax:\n", ( 10 - iterations ) * 2, "", player_one().x( ), player_one().y( ), player_two().x( ), player_two().y( ) );
#endif
    // calculate the outcome of all possible moves of player_one and player_two
    _max = INT_MIN;
    for( int i = 0; i < 4; ++i ) {
        _mins[i] = INT_MAX;
        for( int j = 0; j < 4; ++j ) {
            if( _mins[i] < _max ) break;
            zz::map::location player_one = _player_one.adjacent( i );
            zz::map::location player_two = _player_two.adjacent( j );
            bool player_one_dies = is_wall( player_one );
            bool player_two_dies = is_wall( player_two );
            int result = 0;
            if( player_one == player_two || ( player_two_dies && player_one_dies ) ) {
                // draw
                result = -64;
            } else if( player_two_dies && !player_one_dies ) {
                // win
                result = INT_MAX;
            } else if( !player_two_dies && player_one_dies ) {
                // loss
                result = INT_MIN;
            } else if( !use_heuristic && iterations <= 0 ) {
                result = 0;
                ++__minimax_leafs;
            } else {
                // nothing interesting enough to end the game happened yet
                // save the current state
                int max = _max;
                int mins[4];
                for( int k = 0; k < 4; ++k ) {
                    mins[k] = _mins[k];
                }
                zz::map::location player_one_original( _player_one );
                zz::map::location player_two_original( _player_two );
                // update the map
                set_player_one( player_one );
                set_player_two( player_two );
                if( iterations > 0 ) {
                    // get the next minimax
                    result = minimax( iterations - 1, use_heuristic ) * 0.999;
                } else {
                    // get the voronoi_territory
                    result = territory() * 128;
                    ++__minimax_leafs;
                }
                // restore the current state
                set_player_one( player_one_original );
                set_player_two( player_two_original );
                set_is_wall(player_one, false);
                set_is_wall(player_two, false);
                _max = max;
                for( int k = 0; k < 4; ++k ) {
                    _mins[k] = mins[k];
                }
            }
            if( result < _mins[i] ) _mins[i] = result;
        }
        if( _mins[i] > _max ) {
            _max = _mins[i];
        }
    }

#ifdef DEBUG_MAP
    fprintf( stderr, "%*s(%d,%d) vs (%d,%d) minimax.mins(): [", ( 10 - iterations ) * 2, "", player_one().x( ), player_one().y( ), player_two().x( ), player_two().y( ) );
    for( int i = 0; i < 4; ++i ) {
        fprintf( stderr, "%d:%d", i, _mins[i] );
        if( i != 3 ) fprintf( stderr, ", " );
    }
    fprintf( stderr, "] (%d)\n", _max );
#endif
    return _max;
}
int zz::map::territory( ) const {
    int player_one_territory = 0;
    int player_two_territory = 0;
    int player_one_distances[width() * height()];
    int player_two_distances[width() * height()];
    for( int* i = player_one_distances; i < player_one_distances + width() * height(); ) {
        ( *i++ ) = -1;
    }
    for( int* i = player_two_distances; i < player_two_distances + width() * height(); ) {
        ( *i++ ) = -1;
    }
    int todo[width() * height()];
    int counted_locations[width() * height()];

    // initialize everything for player_one
    for( int* i = counted_locations; i < counted_locations + width() * height(); ) {
        ( *i++ ) = false;
    }
    int* current_todo = todo;
    int* todo_end = todo;
    (*todo_end++) = player_one().x() + width() * player_one().y();
    counted_locations[player_one().x( ) + width( ) * player_one().y( )] = true;
    player_one_distances[player_one().x( ) + width( ) * player_one().y( )] = 0;
    // find the distance to every location player_one can reach
    while( current_todo < todo_end ) {
        zz::map::location current( *current_todo % width( ), *current_todo / width( ) );
        ++player_one_territory; // everything will belong to player one, until we start counting player_two
        int current_index = current.x( ) + width() * current.y( );
        int distance = player_one_distances[current_index];
        for( int i = 0; i < 4; ++i ) {
            // add all accessible neighbors of this location to the todo list
            zz::map::location neighbor = current.adjacent( i );
            int neighbor_index = neighbor.x( ) + width( ) * neighbor.y( );
            if( !counted_locations[neighbor_index] && !is_wall(neighbor_index) ) {
                player_one_distances[neighbor_index] = distance + 1;
                counted_locations[neighbor_index] = true;
                ( *todo_end++ ) = neighbor_index;
            }
        }
        ++current_todo;
    }


    // re-init for player_two
    for( int* i = counted_locations; i < counted_locations + width() * height(); ) {
        ( *i++ ) = false;
    }
    current_todo = todo;
    todo_end = todo;
    (*todo_end++) = player_two().x() + width() * player_two().y();
    counted_locations[player_two().x( ) + width( ) * player_two().y( )] = true;
    player_two_distances[player_two().x( ) + width( ) * player_two().y( )] = 0;
    // find the distance to every location player_one can reach and adjust ownership of contested locations
    while( current_todo < todo_end ) {
        zz::map::location current( *current_todo % width( ), *current_todo / width( ) );
        int current_index = current.x( ) + width() * current.y( );
        int distance = player_two_distances[current_index];
        int player_one_distance = player_one_distances[current_index];
        if( player_one_distance == -1 || distance < player_one_distance ) {
            ++player_two_territory; // everything will belong to player one, until we start counting player_two
        }
        if ( distance < player_one_distance || distance == player_one_distance) {
            --player_one_territory; // everything will belong to player one, until we start counting player_two
        }
        for( int i = 0; i < 4; ++i ) {
            // add all accessible neighbors of this location to the todo list
            zz::map::location neighbor = current.adjacent( i );
            int neighbor_index = neighbor.x( ) + width( ) * neighbor.y( );
            if( !counted_locations[neighbor_index] && !is_wall(neighbor_index) ) {
                player_two_distances[neighbor_index] = distance + 1;
                counted_locations[neighbor_index] = true;
                ( *todo_end++ ) = neighbor_index;
            }
        }
        ++current_todo;
    }

    return player_one_territory - player_two_territory;
}