Search This Blog

Thursday, July 21, 2011

Leveling up!

I'm working on the server side implementation of a level based game. The problem is that we are designing the game as we implement it (did I hear agile?). Given that we are still not sure what actions should trigger a level up, I decided to implement the most flexible, yet simple mechanism to define level completions. Fortunately we are working with Rails for the server side, so meta-programing is easy ...

My proposed solution:

class Criterion

  class << self
    attr_reader :criteria
    attr_reader :requiring_levels
  end

  @criteria = []
  @requiring_levels = {}

  def self.abstract_class?
    true
  end

  def self.criteria_for_level( level )
    criteria = []
    Criterion.criteria.each do |klass|
      criteria << klass.new( level ) if klass.should_apply?( level )
    end
    return criteria.empty? ? nil : criteria
  end

  def self.inherited(subclass)
    Criterion.criteria << subclass
    super
  end

end

# This subclass exemplifies how new criteria can be added.
# The completed? method can be as simple of complicated as you want
# and you can define more level specific attributes in the
# @requiring_levels hash_map
class XPCriterion < Criterion

  attr_reader :threshold

  @requiring_levels = {1 => 5, 2 => 10, 3 => 20}

  def self.should_apply?( level )
    self.requiring_levels.has_key? level
  end

  def initialize( level )
    @threshold = self.class.requiring_levels[ level ]
  end

  def completed?( args )
    return args > self.threshold
  end

end


class Level < ActiveRecord::Base

  # RoR related stuff omitted

  def completed?( args )
    criteria = Criterion.criteria_for_level( self.number )
    return nil unless criteria
    criteria.each do |c|
      print ( "Checking #{c.class.name} criteria\n" )
      return false unless c.completed?( args )
    end
    return true
  end
  
end

1 comment:

  1. I like to get up early to go out and breathe fresh air. I feel that it is good for health and a good habit
    19216811ll.com

    ReplyDelete