class Codebreaker::Game

Attributes

attempts[R]
configuration[R]
hints[R]
result[R]
secret_code[R]

Public Class Methods

new(*config) { |configuration| ... } click to toggle source
# File lib/codebreaker/game.rb, line 10
def initialize(*config)
  @locale = Localization.new(:game)
  @configuration ||= GameConfiguration.new(*config)
  yield @configuration if block_given?
  apply_configuration
  generate_secret_code
end

Public Instance Methods

guess_valid?(input) click to toggle source
# File lib/codebreaker/game.rb, line 18
def guess_valid?(input)
  raise message['errors']['invalid_input'] unless input.is_a?(String)
  raise message['alerts']['invalid_input'] unless input[/\A[1-6]{4}\z/]
  true
end
hint() click to toggle source
# File lib/codebreaker/game.rb, line 34
def hint
  raise message['alerts']['no_hints'] if hints.zero?
  @hints -= 1
  return secret_code.sample if result.empty?
  not_guessed = result.chars.map.with_index do |item, index|
    secret_code[index] unless item == RIGHT_ANSWER
  end
  not_guessed.compact.sample
end
score() click to toggle source
# File lib/codebreaker/game.rb, line 44
def score
  calculate_score
end
to_guess(input) click to toggle source
# File lib/codebreaker/game.rb, line 24
def to_guess(input)
  raise message['alerts']['no_attempts'] if attempts.zero?
  @attempts -= 1
  @result = fancy_algo(input, secret_code)
end
won?() click to toggle source
# File lib/codebreaker/game.rb, line 30
def won?
  result == RIGHT_ANSWER * 4
end

Private Instance Methods

apply_configuration() click to toggle source
# File lib/codebreaker/game.rb, line 70
def apply_configuration
  check_configuration
  configuration.freeze
  create_instance_vars
end
calculate_score() click to toggle source
# File lib/codebreaker/game.rb, line 100
def calculate_score
  level_rates =
    case configuration.level
    when SIMPLE_LEVEL then [TEN_POINTS, ZERO_POINTS]
    when MIDDLE_LEVEL then [TWENTY_POINTS, TWENTY_POINTS]
    else [FIFTY_POINTS, ONE_HUNDRED_POINTS]
    end

  attempt_rate, hint_rate = level_rates
  guessed = result.count(RIGHT_ANSWER)

  used_attempts = configuration.max_attempts - attempts
  used_hints = configuration.max_hints - hints
  bonus_points = won? && used_attempts == 1 ? BONUS_POINTS : ZERO_POINTS

  used_attempts * attempt_rate * guessed - used_hints * hint_rate + bonus_points
end
check_configuration() click to toggle source
# File lib/codebreaker/game.rb, line 52
def check_configuration
  levels = [SIMPLE_LEVEL, MIDDLE_LEVEL, HARD_LEVEL]
  raise message['errors']['fail_configuration'] if configuration.any?(&:nil?)
  raise message['errors']['unknown_level'] unless levels.include?(configuration.level)
  begin
    raise if configuration.max_attempts < 1 || configuration.max_hints.negative?
  rescue
    raise message['errors']['fail_configuration_values']
  end
end
create_instance_vars() click to toggle source
# File lib/codebreaker/game.rb, line 63
def create_instance_vars
  @attempts = configuration.max_attempts
  @hints = configuration.max_hints
  @locale.lang = configuration.lang
  @result = ''
end
fancy_algo(guess, secret_code) click to toggle source
# File lib/codebreaker/game.rb, line 80
def fancy_algo(guess, secret_code)
  guessed_indexes, guess = [], guess.chars.map(&:to_i)

  guess.each_with_index do |item, index|
    guessed_indexes << index if item == secret_code[index]
  end

  guess.map.with_index do |item, index|
    not_guessed_secret_nums =
      secret_code.reject.with_index do |_, guessed_index|
        guessed_indexes.include?(guessed_index)
      end
    case
    when item == secret_code[index] then RIGHT_ANSWER
    when not_guessed_secret_nums.include?(item) then RIGHT_ANSWER_DIFF_INDEX
    else WRONG_ANSWER
    end
  end.join
end
generate_secret_code() click to toggle source
# File lib/codebreaker/game.rb, line 76
def generate_secret_code
  @secret_code = (1..4).map { rand(1..6) }
end