module TwentyFortyEight

Constants

MODES
SETTINGS
VERSION

Public Class Methods

endless(settings = {}, &block) click to toggle source
# File lib/TwentyFortyEight.rb, line 119
def self.endless(settings = {}, &block)
  loop { TwentyFortyEight.play settings, &block }
ensure
  Screen.restore! if settings.verbose?
end
load_highscore(path = '~/.2048') click to toggle source
# File lib/TwentyFortyEight.rb, line 107
def self.load_highscore(path = '~/.2048')
  path = File.expand_path path

  if File.exist? path
    contents = File.read path
    hsh      = JSON.parse contents.start_with?('{') && contents || '{}'
  else
    File.new path, File::CREAT
    {}
  end
end
load_or_set_highscore!(current_score, settings, path = '~/.2048') click to toggle source
# File lib/TwentyFortyEight.rb, line 90
def self.load_or_set_highscore!(current_score, settings, path = '~/.2048')
  skey = settings.size.to_s

  @@highscore       ||= load_highscore
  @@highscore[skey] ||= 0
  @@session_high      = current_score if current_score > @@session_high

  return unless current_score > @@highscore[skey]

  @@highscore[skey] = current_score
  write_highscore path
end
play(settings = {}, &block) click to toggle source
# File lib/TwentyFortyEight.rb, line 21
def self.play(settings = {}, &block)
  settings = Options.new SETTINGS.merge(settings)
  game     = Game.new @@games.count, settings
  dirs     = game.directions - (settings.except || [])
  dirs    -= (settings.only || [])
  dsl      = Dsl.new game, settings, &block if block_given?

  load_or_set_highscore!(game.score, settings) unless @@highscore

  Screen.init! settings if settings.verbose? && @@games.empty?

  trap 'SIGINT' do
    Screen.restore! if settings.verbose?
    exit
  end

  restart      = false
  non_blocking = dirs

  render_game game, settings if settings.verbose?

  loop do
    if game.end?
      break if settings.mode?(:endless) ||
               !settings.verbose? ||
               !settings.interactive?
      render_game game, settings, true

      action = :default
      until [:quit, :restart].include? action
        action = Screen.handle_keypress
        sleep 0.1
      end

      restart = true if action == :restart
      break
    else
      if settings.interactive?
        action = Screen.handle_keypress until Game::ACTIONS.include?(action)
      else
        non_blocking = game.changed? ? dirs : non_blocking - [action]
        action       = dsl && dsl.apply(game.dup) || non_blocking.sample

        if non_blocking.empty?
          non_blocking.concat settings.except if settings.except?
          non_blocking.concat game.directions if settings.only?
        end
      end

      game.action action
      load_or_set_highscore! game.score, settings
      render_game game, settings if settings.verbose? || settings.interactive?
      sleep(settings.delay.to_f / 1000) if settings.delay?
    end
  end

  @@games << game

  if settings.log?
    game.log.write! dir: 'logs',
                    name: "2048-#{Time.now.to_i}-#{game.id}-#{game.score}"
  end

  return play(settings, &block) if restart
  game
ensure
  Screen.restore! if settings.verbose? && settings.mode?(:play)
end
render_game(game, settings, final = false) click to toggle source
# File lib/TwentyFortyEight.rb, line 125
def self.render_game(game, settings, final = false)
  h = { interactive: settings.interactive?, info: [] }
  s = settings.key.to_s

  if settings.mode? :endless
    h[:info] << { highscore: "#{@@session_high}/#{@@highscore[settings.size.to_s]}" }
    h[:info] << { game: (1 + game.id), move: game.moves }
  else
    h[:info] << { highscore: @@highscore[settings.size.to_s] , move: game.moves}
  end
  h[:info] << { score: game.score, dir: game.current_dir}
  h[:history] = (@@games + [game]) if settings.history?

  return Screen.game_over game, h if final
  Screen.render game.board.to_a, h
end
write_highscore(path = '~/.2048') click to toggle source
# File lib/TwentyFortyEight.rb, line 103
def self.write_highscore(path = '~/.2048')
  File.write File.expand_path(path), @@highscore.to_json
end