Class: TictactoeJ8th::AI

Inherits:
Object
  • Object
show all
Defined in:
lib/tictactoe_j8th/ai.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(token) ⇒ AI

Returns a new instance of AI.



6
7
8
# File 'lib/tictactoe_j8th/ai.rb', line 6

def initialize(token)
  @token = token
end

Instance Attribute Details

#tokenObject (readonly)

Returns the value of attribute token.



4
5
6
# File 'lib/tictactoe_j8th/ai.rb', line 4

def token
  @token
end

Instance Method Details

#move(board) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/tictactoe_j8th/ai.rb', line 10

def move(board)
  return nil if board.full?

  # ####### Speed Hacks #######
  # Hacks to speed up minimax by bypassing most of the possible games.
  # The return statements here are important.  We make a move, then
  # bail out so that we don't end up analyzing all the possible games further down.
  # TODO:  See if there is a craftier, less hackish way to speed things up.

  # If the board is empty, always take the middle.
  if board.empty?
    board.place(token, 0)
    return 0
  end

  open_spots = get_open_spots(board)
  # If there is one spot taken, then always take the middle.
  # Unless the middle is taken already, then take the corner.
  if open_spots.count == Board::BOARD_SIZE-1
    spot = board[4].nil? ? 4 : 0
    board.place(token, spot)
    return spot
  end
  # ###### End Hacks ########


  enemy_token = discover_enemy_token(board)
  # Better here, but we do it above for our speed hacks.
  #open_spots = get_open_spots(board)
  games = Hash.new

  open_spots.each do |i|
    board_copy = board.create_copy
    board_copy.place(token, i)
    game = Game.new(board_copy, AI.new(enemy_token), AI.new(token))
    if game.winner == token
      board.place(token, i)
      return i
    end
    games[i] = game
  end

  scores = Hash.new

  games.each do |i, game|
    game.play
    scores[i] = 1 if game.winner == token
    scores[i] = -1 if game.winner == enemy_token
    scores[i] = 0 if game.winner.nil? and game.game_over?
  end

  max = scores.max_by { |k, v| v }
  spot = max[0]
  board.place(token, spot)
  spot
end