Name: Buster

Author: Brad Greenlee

Code:

worksheet = Array.new(8) {|x| {:score => 0, :free => []}}
me = turn
matrix = move_matrix
worksheet_pos = 0

# check columns
0.upto(2) do |x|
  0.upto(2) do |y|
    v = matrix[x][y]
    worksheet[worksheet_pos][:score] += (v == me ? -1 : v != "" ? 1 : (worksheet[worksheet_pos][:free] << [x,y]) && 0)
  end
  worksheet_pos += 1
end

# check rows
0.upto(2) do |y|
  0.upto(2) do |x|
    v = matrix[x][y]
    worksheet[worksheet_pos][:score] += (v == me ? -1 : v != "" ? 1 : (worksheet[worksheet_pos][:free] << [x,y]) && 0)
  end
  worksheet_pos += 1
end

# check diagonals
0.upto(2) do |n|
  v = matrix[n][n]
  worksheet[worksheet_pos][:score] += (v == me ? -1 : v != "" ? 1 : (worksheet[worksheet_pos][:free] << [n,n]) && 0)
end
worksheet_pos += 1

0.upto(2) do |n|
  v = matrix[n][2-n]
  worksheet[worksheet_pos][:score] += (v == me ? -1 : v != "" ? 1 : (worksheet[worksheet_pos][:free] << [n,2-n]) && 0)
end

# analyze
if (rows = worksheet.find_all {|row| row[:score] == -2}).any?
  # -2 means I have a winning move
  move = rows.first[:free].first
  log_info("found winning move: #{move.inspect}")
elsif (rows = worksheet.find_all {|row| row[:score] == 2}).any?
  # 2 means I can block an opponent's winning move
  move = rows.first[:free].first
  log_info("blocked winning move: #{move.inspect}")
elsif (rows = worksheet.find_all {|row| row[:score] == -1 && row[:free].any?}).any?
  # -1 means either there are no open moves, or I have two moves on a row I already have piece on
  move = rows[rand(rows.size)][:free].first
  log_info("playing move on my row: #{move.inspect}")
elsif (rows = worksheet.find_all {|row| row[:score] == 1 && row[:free].any?}).any?
  # 1 means either there is either no open moves, or my opponent has one piece
  move = rows[rand(rows.size)][:free].first
  log_info("playing move in opponent's row: #{move.inspect}")
elsif (rows = worksheet.find_all {|row| row[:score] == 0 && row[:free].size == 3}).any?
  # 0 means either there is one open move on a row where we both have pieces, or it's an empty row
  move = rows[rand(rows.size)][:free].first
  log_info("playing move on empty row: #{move.inspect}")
else
  # must be a 0, but on a row were we both have pieces; our least desireable move, but our only one
  rows = worksheet.find_all {|row| row[:score] == 0}
  move = rows.first[:free].first
  log_info("playing only move on crowded row: #{move.inspect}")
end  
make_move!(move[0],move[1])

Edit | Play against X | Play against O | Back