class Basher::Level

Handles the initialization of a single level in the game. The defining characteristic of a level is it’s difficulty, which controls the number of the words in the level, and their size.

TODO: Extract constants to global configuration values.

Constants

MAX_WORD_SIZE

Biggest word size

WORDS_PER_LEVEL

How many words per level

WORD_SIZES

Word sizes

Attributes

cursor[R]
difficulty[R]

Use this attribute to determine the number of the words, and the length of the words.

timer[R]
words[R]

Public Class Methods

new(difficulty = 1) click to toggle source

Returns a Level instance with the default difficulty of 1.

# File lib/basher/level.rb, line 46
def initialize(difficulty = 1)
  @difficulty = difficulty || 1
  pick_words!
  @cursor = Cursor.new(words)
  @timer  = Timer.new
end
start(difficulty, &on_end) click to toggle source
# File lib/basher/level.rb, line 34
def start(difficulty, &on_end)
  level = self.new(difficulty)

  level.start do
    on_end.call
  end

  level
end

Public Instance Methods

average_word_size() click to toggle source
# File lib/basher/level.rb, line 102
def average_word_size
  words.reduce(0) { |sum, w| sum += w.string.size } / words.size
end
chances() click to toggle source
# File lib/basher/level.rb, line 61
def chances
  weights.map { |weight| (weight / total_weight * 100.0).round(2) }
end
finish() click to toggle source
# File lib/basher/level.rb, line 97
def finish
  timer.stop
  @thread.terminate if !@thread.nil? && @thread.alive?
end
pause() click to toggle source
# File lib/basher/level.rb, line 93
def pause
  timer.stop
end
pick(words = 15) click to toggle source
# File lib/basher/level.rb, line 73
def pick(words = 15)
  1.upto(words).collect { roll }
end
pick_words!(words_per_level = WORDS_PER_LEVEL) click to toggle source

Get an array of words that are calculated based on the difficulty. The bigger the difficulty, the bigger the words.

# File lib/basher/level.rb, line 67
def pick_words!(words_per_level = WORDS_PER_LEVEL)
  @words = pick(words_per_level).map do |size|
    Basher::Word.new(Basher::Dictionary.random_word(size))
  end
end
sizes() click to toggle source
# File lib/basher/level.rb, line 53
def sizes
  WORD_SIZES
end
start() { || ... } click to toggle source
# File lib/basher/level.rb, line 81
def start
  timer.start

  @thread = Thread.new do
    begin
      sleep 0.005 while timer.total_elapsed <= time_limit
      timer.stop
      yield
    end
  end
end
time_limit() click to toggle source
# File lib/basher/level.rb, line 77
def time_limit
  [((difficulty + 2) * 100.to_f / (average_word_size.to_f ** 2)).ceil, 20].min * 1000
end
weights() click to toggle source
# File lib/basher/level.rb, line 57
def weights
  sizes.map { |size| calculate(size) }
end

Private Instance Methods

calculate(size) click to toggle source
# File lib/basher/level.rb, line 126
def calculate(size)
  weight = (difficulty / (size / 2) ) ** size
  weight.round(2)
end
roll() click to toggle source
# File lib/basher/level.rb, line 112
def roll
  sizes_and_weights = sizes.zip(weights)

  loop do
    sizes_and_weights.shuffle.each do |tuple|
      size, weight = *tuple

      chance = (weight / weights.reduce(:+) * 100.0).round(2)
      rolled = (rand * 100).round(2)
      return size if rolled <= chance
    end
  end
end
total_weight() click to toggle source
# File lib/basher/level.rb, line 108
def total_weight
  weights.reduce(:+)
end