class AiPlayer

Constants

ALPHA
BETA

Public Class Methods

new(symbol) click to toggle source
Calls superclass method Player::new
# File lib/ai_player.rb, line 7
def initialize(symbol)
  super(symbol)
end

Public Instance Methods

choose_move(board) click to toggle source
# File lib/ai_player.rb, line 11
def choose_move(board)
  minimax(board, true, board.vacant_indices.size, ALPHA, BETA).first[1]
end
minimax(board, is_max_player, depth, alpha, beta) click to toggle source
# File lib/ai_player.rb, line 19
def minimax(board, is_max_player, depth, alpha, beta)
  best_score_so_far = initial_score(is_max_player)

  if round_is_over(board, depth)
    return score(board, depth)
  end

  board.vacant_indices.each do |i|
    new_board = board.make_move(i, current_players_symbol(is_max_player))
    result = minimax(new_board, !is_max_player, depth - 1, alpha, beta)
    best_score_so_far = update_score(is_max_player, i, best_score_so_far, score_from(result))

    alpha = update_alpha(is_max_player, best_score_so_far, alpha)
    beta = update_beta(is_max_player, best_score_so_far, beta)

    if alpha > beta
      break
    end
  end

  best_score_so_far
end
ready?() click to toggle source
# File lib/ai_player.rb, line 15
def ready?
  true
end

Private Instance Methods

current_players_symbol(is_max_player) click to toggle source
# File lib/ai_player.rb, line 105
def current_players_symbol(is_max_player)
  is_max_player == true ? game_symbol : PlayerSymbols::opponent(game_symbol)
end
initial_score(is_max_player) click to toggle source
# File lib/ai_player.rb, line 97
def initial_score(is_max_player)
  if is_max_player
    best_score_so_far = {ALPHA => nil}
  else
    best_score_so_far = {BETA => nil}
  end
end
maximizing_player_won?(winners_symbol) click to toggle source
# File lib/ai_player.rb, line 85
def maximizing_player_won?(winners_symbol)
  symbols_are_equal?(winners_symbol, game_symbol)
end
minimizing_player_won?(winners_symbol) click to toggle source
# File lib/ai_player.rb, line 89
def minimizing_player_won?(winners_symbol)
  symbols_are_equal?(winners_symbol, PlayerSymbols::opponent(game_symbol))
end
round_is_over(board, depth) click to toggle source
# File lib/ai_player.rb, line 66
def round_is_over(board, depth)
  @winner = board.winning_symbol
  !@winner.nil? || depth == 0
end
score(board, depth) click to toggle source
# File lib/ai_player.rb, line 71
def score(board, depth)
  if @winner.nil?
    return {0 => nil}
  end

  if maximizing_player_won?(@winner)
    return {(1 + depth) => nil}
  end

  if minimizing_player_won?(@winner)
    return {(-1 - depth) => nil}
  end
end
score_from(score) click to toggle source
# File lib/ai_player.rb, line 55
def score_from(score)
  score.first.first
end
symbols_are_equal?(symbol1, symbol2) click to toggle source
# File lib/ai_player.rb, line 93
def symbols_are_equal?(symbol1, symbol2)
  symbol1 == symbol2
end
update_alpha(is_max_player, best_score_so_far, alpha) click to toggle source
# File lib/ai_player.rb, line 48
def update_alpha(is_max_player, best_score_so_far, alpha)
  if is_max_player && score_from(best_score_so_far) > alpha
    alpha = score_from(best_score_so_far)
  end
  alpha
end
update_beta(is_max_player, best_score_so_far, beta) click to toggle source
# File lib/ai_player.rb, line 59
def update_beta(is_max_player, best_score_so_far, beta)
  if !is_max_player && score_from(best_score_so_far) < beta
      beta = score_from(best_score_so_far)
  end
  beta
end
update_score(is_max_player, move, score, result_score) click to toggle source
# File lib/ai_player.rb, line 109
def update_score(is_max_player, move, score, result_score)
  if is_max_player && (result_score >= score_from(score))
    return {result_score => move}
  elsif !is_max_player && (result_score < score_from(score))
    return {result_score => move}
  end
  return score
end