#!/usr/bin/ruby class ElItemAppearance attr_reader :type, :appearance, :identity, :possible_identities, :price_of @@appearance_table = {} # type is something like "shield" or "potion" # appearance is something like "balsa wand" or "clear potion" # identity is something like "wand of wishing" def initialize(type, appearance) raise "ElItemAppearance should never be instanced! Use a subclass." if self.class == ElItemAppearance @type = type @appearance = appearance @identity = nil @possible_identities = nil # let subclasses handle this @price_of = nil # let subclasses handle this @@appearance_table[appearance] = self end def ElItemAppearance.find(appearance) return @@appearance_table[appearance] end def rule_out(*types) return if @identity # handle receiving an array types.flatten! types.each {|type| @possible_identities.delete(type) } check_if_identifiable end def rule_out_all_but(*types) return if @identity # handle receiving an array types.flatten! @possible_identities.delete_if {|key, value| not types.include?(key) } check_if_identifiable end def identify_as(identity) return if @identity @identity = identity # add :gain_level to the appearance table @@appearance_table[identity] = self # add something like "gain level" to the appearance table word_identity = identity.to_s.gsub(/_/, " ") @@appearance_table[word_identity] = self # remove all other possibilities from current appearance @possible_identities = { identity => 1 } # remove this identity from all other appearances @@appearance_table.each_value {|appearance| appearance.rule_out(identity) unless appearance == self } end def check_if_identifiable() return if @identity if @possible_identities.keys.size == 1 identity = @possible_identities.keys[0] identify_as(identity) end end def engrave_useful?() return false end def price_id_buy(amount, charisma, is_tourist) return if @identity if charisma > 18 amount *= 2 elsif charisma > 17 amount += (amount / 2).to_i elsif charisma > 15 amount += (amount / 3).to_i elsif charisma < 6 amount = (amount / 2).to_i elsif charisma < 8 amount -= (amount / 3).to_i elsif charisma < 11 amount -= (amount / 4).to_i end amount = 1 if amount < 1 amount -= (amount / 4).to_i if is_tourist amount = 0 if amount == 5 amount_sur = amount - (amount / 4).to_i amount_sur = 0 if amount_sur == 5 price_id_aux(amount, amount_sur) end def price_id_sell(amount, is_tourist) return if @identity if is_tourist amount *= 3 else amount *= 2 end amount_sur = amount + (amount / 3).to_i price_id_aux(amount, amount_sur) end def price_id_aux(amount, amount_sur) # search around (amount +/-4) for base price hits due to inaccuracy of # inverting integer arithmetic hits = [] for try in [amount, amount_sur, amount-1, amount+1, amount_sur-1, amount_sur+1, amount-2, amount+2, amount_sur-2, amount_sur+2, amount-3, amount+3, amount_sur-3, amount_sur+3, amount-4, amount+4, amount_sur-4, amount_sur+4] next unless @price_of.has_value?(try) @price_of.each do |key, value| hits.push(key) if try == value end end return if hits.size == 0 rule_out_all_but(hits) check_if_identifiable end def price_id_useful?() return false if @identity # See comment in wandappearance.rb engrave_useful? for info on what # this does; this time we build a hash keying on base price, producing # a list of identities. We can't use the builtin Hash.invert method, # because it doesn't handle multiple values as we need it. price_groups = {} @price_of.each do |key, value| price_groups[value] ||= [] # initialize unless initialized price_groups[value].push(key) end appearance_groups = 0 price_groups.each do |price, group| group.each do |identity| next unless @possible_identities.has_key?(identity) appearance_groups += 1 break # that is, next price group end end return appearance_groups > 1 end end