# == Synopsis
#
# Use a GA to breed a good potential player
# 
# == Author
# Neil Smith
# 
# == Change history
# Version 1.1::  23 April 2008 


require 'libttc'
require 'libpplayer'
require 'libgenetics'
require 'play'

class Population
  # Use tournament selection to pick an individual for the next generation
  def tournament_select_one(winner_success_chance = 0.8, max_game_length= 1000, verbose = false)
    player_count = rand(5) + 2
    pool_size = @individuals.length
    players = []
    1.upto(player_count) { players << @individuals[rand(pool_size)].to_potential_player }
    game = GameHandler.new(players, max_game_length, false, false)
    winner, length = game.play
    puts "Winner = #{winner} in #{length} moves.  Game had #{player_count} players" if verbose
    # If the game was a draw, or the winner is unlucky, pick a parent at random
    if winner == :draw or rand > winner_success_chance
      successful_player = players[rand(player_count)]
    else
      successful_player = winner
    end
    successful_player
  end
  
  # Select a new population the same size as the current population
  def tournament_select_population(winner_success_chance = 0.8, max_game_length = 1000, verbose = false)
    new_population = []
    1.upto(@individuals.length) do
      new_population << tournament_select_one(winner_success_chance, max_game_length, verbose).to_genome
      puts "Created #{new_population.length} indivduals" if verbose
    end
    new_population
  end
  
end

class Potential_player
  # Convert a player to a bitstring
  def to_bitstring
    (@friend_pull * 4).to_i.to_bitstring(4).gray_encode +
      (@enemy_pull * 4).to_i.to_bitstring(4).gray_encode +
      (@base_pull * 4).to_i.to_bitstring(4).gray_encode +
      @safe_bonus.to_bitstring(4).gray_encode +
      @capture_bonus.to_bitstring(4).gray_encode
  end
  
  # Convert a player to a genome
  def to_genome
    Genome.new(self.to_bitstring)
  end
end


class Genome
  
  # Create a potential player from a genome
  def to_potential_player
    friend_pull   = @genome[0,  4].gray_decode.to_decimal.to_f / 4
    enemy_pull    = @genome[4,  4].gray_decode.to_decimal.to_f / 4
    base_pull     = @genome[8,  4].gray_decode.to_decimal.to_f / 4
    safe_bonus    = @genome[12, 4].gray_decode.to_decimal
    capture_bonus = @genome[16, 4].gray_decode.to_decimal
    Potential_player.new({:friend_pull => friend_pull, 
        :enemy_pull => enemy_pull, :base_pull => base_pull, 
        :safe_bonus => safe_bonus, :capture_bonus => capture_bonus})
  end
end