class Rubykon::CLI

Constants

CHAR_LABELS
EXIT
GTP_COORDINATE
MOVE_CONSIDERATIONS_COUNT
X_LABEL_PADDING
Y_LABEL_WIDTH

Public Class Methods

new(output = $stdout, input = $stdin) click to toggle source
# File lib/rubykon/cli.rb, line 11
def initialize(output = $stdout, input = $stdin)
  @output         = output
  @input          = input
  @state          = :init
  @move_validator = MoveValidator.new
  @root           = nil
end

Public Instance Methods

start() click to toggle source
# File lib/rubykon/cli.rb, line 19
    def start
      @output.puts 'Please enter a board size (common sizes are 9, 13, and 19)'
      size = get_digit_input
      @output.puts <<-PLAYOUTS
Please enter the number of playouts you'd like rubykon to make!
More playouts means rubykon is stronger, but also takes longer.
For 9x9 10000 is an acceptable value, for 19x19 1000 already take a long time (but still plays bad).
      PLAYOUTS
      playouts = get_digit_input
      init_game(size, playouts)
      game_loop
    end

Private Instance Methods

ask_for_input() click to toggle source
# File lib/rubykon/cli.rb, line 120
def ask_for_input
  @output.puts "Make a move in the form XY, e.g. A19, D7 as the labels indicate!"
  @output.puts 'Or ask rubykon what it is thinking with "wdyt"'
  get_input
end
bot_move() click to toggle source
# File lib/rubykon/cli.rb, line 101
def bot_move
  @output.puts 'Rubykon is thinking...'
  @root = @mcts.start @game_state, @playouts
  move = @root.best_move
  make_move(move)
end
bot_turn?() click to toggle source
# File lib/rubykon/cli.rb, line 80
def bot_turn?
  @game.next_turn_color == Board::BLACK
end
exit_if_desired(input) click to toggle source
# File lib/rubykon/cli.rb, line 49
def exit_if_desired(input)
  quit if input.match EXIT
end
game_loop() click to toggle source
# File lib/rubykon/cli.rb, line 69
def game_loop
  print_board
  while true
    if bot_turn?
      bot_move
    else
      human_input
    end
  end
end
get_digit_input() click to toggle source
# File lib/rubykon/cli.rb, line 33
def get_digit_input
  input = get_input
  until input.match /^\d\d*$/
    @output.puts "Input has to be a number. Please try again!"
    input = get_input
  end
  input
end
get_input() click to toggle source
# File lib/rubykon/cli.rb, line 42
def get_input
  @output.print '> '
  input = @input.gets.chomp
  exit_if_desired(input)
  input
end
human_input() click to toggle source
# File lib/rubykon/cli.rb, line 108
def human_input
  input = ask_for_input.upcase
  case input
  when GTP_COORDINATE
    human_move(input)
  when 'WDYT'.freeze
    print_move_considerations
  else
    invalid_input
  end
end
human_move(input) click to toggle source
# File lib/rubykon/cli.rb, line 126
def human_move(input)
  move = move_from_input(input)
  if @move_validator.valid?(*move, @game_state.game)
    make_move(move)
  else
    retry_input
  end
end
init_game(size, playouts) click to toggle source
# File lib/rubykon/cli.rb, line 58
def init_game(size, playouts)
  board_size = size.to_i
  @output.puts "Great starting a #{board_size}x#{board_size} game with #{playouts} playouts"
  @game          = Game.new board_size
  @game_state    = GameState.new @game
  @mcts          = MCTS::MCTS.new
  @board         = @game.board
  @gtp_converter = GTPCoordinateConverter.new(@board)
  @playouts      = playouts.to_i
end
invalid_input() click to toggle source
# File lib/rubykon/cli.rb, line 161
def invalid_input
  puts "Sorry, didn't catch that!"
end
labeled_board() click to toggle source
# File lib/rubykon/cli.rb, line 88
def labeled_board
  rows = []
  x_labels = X_LABEL_PADDING + CHAR_LABELS.take(@board.size).join(' ')
  rows << x_labels
  board_rows = @board.to_s.split("\n").each_with_index.map do |row, i|
    y_label = "#{@board.size - i}".rjust(Y_LABEL_WIDTH)
    y_label + row + y_label
  end
  rows += board_rows
  rows << x_labels
  rows.join "\n"
end
make_move(move) click to toggle source
# File lib/rubykon/cli.rb, line 154
def make_move(move)
  @game_state.set_move move
  print_board
  @output.puts "#{move.last} played at #{@gtp_converter.to(move.first)}"
  @output.puts "#{@game.next_turn_color}'s turn to move!'"
end
move_from_input(input) click to toggle source
# File lib/rubykon/cli.rb, line 149
def move_from_input(input)
  identifier = @gtp_converter.from(input)
  [identifier, :white]
end
print_board() click to toggle source
print_move_considerations() click to toggle source
quit() click to toggle source
# File lib/rubykon/cli.rb, line 53
def quit
  @output.puts "too bad, bye bye!"
  exit
end
retry_input() click to toggle source
# File lib/rubykon/cli.rb, line 135
def retry_input
  @output.puts 'That was an invalid move, please try again!'
  human_input
end