class RubyTictactoe::AI

Constants

LOSE
NEG_INF
POS_INF
TIE
WIN

Attributes

current_player[R]

Public Class Methods

new(player) click to toggle source
# File lib/ai.rb, line 10
def initialize(player)
  @current_player = player
end

Public Instance Methods

computer_move(board, player) click to toggle source
# File lib/ai.rb, line 14
def computer_move(board, player)
  test_board = board.dup
  test_board.all_cells = board.all_cells.dup
  get_best_move(test_board, player)
end
get_best_move(board, player) click to toggle source
# File lib/ai.rb, line 20
def get_best_move(board, player)
  ranked_moves = rank_possible_moves(board, player)
  move = ranked_moves.max_by {|cell, score| score}
  move.first
end

Private Instance Methods

alphabeta(board, player, depth, alpha, beta) click to toggle source
# File lib/ai.rb, line 59
def alphabeta(board, player, depth, alpha, beta)
  board.open_cells.each_key do |cell|
    player.opponent.add_marker(board, cell)
    score = (apply_minimax(board, player.opponent, cell, depth += 1, alpha, beta) / depth.to_f)
    alpha = player.get_alpha(alpha, score)
    beta = player.get_beta(beta, score)
    board.remove_marker(cell)
    break if alpha >= beta
  end
  player.return_best_score(alpha, beta)
end
apply_minimax(board, player, cell, depth, alpha, beta) click to toggle source
# File lib/ai.rb, line 48
def apply_minimax(board, player, cell, depth, alpha, beta)
  return get_score(board, player) if board.game_over?
  if (player == current_player)
    maximizing_player = MaximizingPlayer.new(player)
    alphabeta(board, maximizing_player, depth, alpha, beta)
  else
    minimizing_player = MinimizingPlayer.new(player)
    alphabeta(board, minimizing_player, depth, alpha, beta)
  end
end
get_move_score(board, player, cell) click to toggle source
# File lib/ai.rb, line 35
def get_move_score(board, player, cell)
  player.add_marker(board, cell)
  best_score = apply_minimax(board, player, cell, depth=0, NEG_INF, POS_INF)
  board.remove_marker(cell)
  best_score
end
get_score(board, player) click to toggle source
# File lib/ai.rb, line 42
def get_score(board, player)
  return WIN if board.winner?(player.marker) && (player == current_player)
  return LOSE if board.winner?(player.marker)
  TIE
end
rank_possible_moves(board, player) click to toggle source
# File lib/ai.rb, line 28
def rank_possible_moves(board, player)
  possible_moves = board.open_cells
  possible_moves.each_key do |cell|
    possible_moves[cell] = get_move_score(board, player, cell)
  end
end