CoralMUD-0.15/
CoralMUD-0.15/core/
CoralMUD-0.15/data/
CoralMUD-0.15/data/areas/
CoralMUD-0.15/data/help/
CoralMUD-0.15/data/players/
CoralMUD-0.15/lib/automap/
CoralMUD-0.15/lib/items/

class Object
  attr_accessor :owner
end

# Storable items can be placed in inventory.
module Storable
end

$editable_classes = {}


module CoralMUD

  module LivingEntity
    include HealthPool
    
    attr_accessor :in_room
    attr_accessor :wearing

    def is_npc?
      return is_a?(NPC)
    end

    def is_blind?
      false
    end

    def is_mute?
      false
    end

    def is_numb?
      false
    end

    def is_deaf?
      false
    end

    def can_hear? something
      case something
        when String
          return !is_deaf? 
        when NpcFacade, Player, ItemFacade
          return !is_deaf?  # it's possible we will have ways to communicate without having to hear it.
      end
    end

    def can_see? thing
      if is_blind?
        false
      end
      true
    end


    def short_desc
      return @name
    end

    # just return the items being worn right now.
    def worn_items
      if !@wearing
        return []
      end

      return @wearing.values
    end

    # wear an obj in one of the locations checking them in order for empty spots.
    def wear obj, locations=obj.worn_locs
      locations = [locations].flatten

      @wearing = {} if !@wearing

      # find the first location with nothing in it.
      locations.each do |a_loc|
        if !@wearing[a_loc] 
          @wearing[a_loc] = obj
          obj.worn_on = a_loc
          return true # bingo
        end
      end
      return false
    end

    # get an object from the room
    def get obj
      if obj.is_a? Array
        obj.each do |o|
          get(o) 
        end
      else
        obj.owner.remove obj
        accept obj
      end
    end

    # drop some this thing has
    def drop obj
      if obj.is_a? Array
        obj.each do |o|
          drop(o)
        end
      else
        obj.owner.remove obj
        in_room.accept obj
      end
    end

    def to_room  room  ### anything including this should may be placed into a room.
      if room.is_a? Integer
        r = Vnum.get_room_index(room)
        r = goto_make_room room if !r
        room = r
      end
      room.accept_player(self)
    end

    def from_room
      if in_room != nil
        in_room.remove_player(self)
      end
      in_room = nil
    end
    def is_imm?
      if @level
        return @level >= LEVEL_IMM
      end
      false
    end

    def is_admin?
      return @level == LEVEL_ADMIN if @level
      false
    end

  def listen thing, author
    if can_hear?(author)
      "#{thing}"
    else
      "something"
    end
  end

  def peek thing, a=true, full=true, just_path=false
    orig_thing = thing
    name = ""
    if thing.is_a? Array
      # it's an array of things to peek at, at once.
      found = []
      thing.flatten!
      paths = []
      thing.each do |element|
        found << peek(element, false, false)
        paths << peek(element, false, true, true)
      end
      paths.uniq!
      name += found.en.conjunction
      if paths.count == 1
        name += paths[0]
      else
        name += " in #{"source".en.quantify(paths.count)}"
      end
    else
      count = 0
      # do while loop.
      loop do
        count += 1
        a = true if count == 2
        begin
          a = false if thing.is_a? Player
          s = a ? thing.short_desc.en.a : thing.short_desc
        rescue
          s = "#{thing}"
        end
        break if !thing.owner && thing != orig_thing
        name += case count
          when 1 then ""
          when 2 then " from "
          else
            " in "
        end
        name += s if !just_path || count > 1
        thing = thing.owner
        break if !full
        break unless thing
      end

    end

    return name
  end


    def view obj
      if @socket
        case obj
        when String then @socket.text_to_socket obj
        when ItemFacade, Player, NpcFacade
          # description would eventually be here.
          @socket.text_to_socket "#{peek(obj).capitalize} has no distinguishing features." + ENDL
        end
      end
    end

    def text_to_player txt
      if @socket
        @socket.text_to_socket txt
      end
    end

    def go_anywhere
      found = nil

      log :info, "Moving someone."

      in_room.exit_list.each do |ex|
        next if ex == nil
        ex.enter(self)
        return
      end

      in_room.remove_player(self)
      r = Vnum.get_room_index(1)
      if r == nil
        r = goto_make_room 1
      end
      r.accept_player(self)
    end
  end

  module HasStuff    
    # put anything in this room in the generic list for stuff.
    def accept thing
      if self.respond_to? :can_accept?
        if !self.can_accept? thing
          return false
        end
      end
      @stuff = [] if !@stuff
      @stuff << thing
      thing.owner = self
      return true
    end

    def stuff
      @stuff || []
    end

    # remove anything from this room.
    def remove thing
      if self.respond_to? :can_remove?
        if !self.can_remove? thing
          return false
        end
      end

      thing.owner = nil

      @stuff.delete thing if @stuff
      @stuff = nil if @stuff && @stuff.empty?
      return true
    end

    def each_stuff_not_worn
      
      (@stuff || [] - self.worn_items).each do |item|
        yield item
      end
    end

    def each_stuff_worn
      self.worn_items.each do |item| 
        yield item, item.worn_on
      end
    end

    def each_stuff 
      @stuff.each { |thing| yield thing }
    end

    def count_stuff
      c = 0
      @stuff.each { c += 1 }
      return c
    end
  end

  module VirtualTags
    attr_accessor :vtag, :namespace
    def assign_tag tag_str, namespace=nil
      # do minimal checking to make sure the tag doesn't already exist.
      if @vtag 
        Tag.clear_tag(self)
      end
      @vtag = Tag.new(tag_str, self, namespace) # generate a tag.
      @namespace = namespace
    end
    def reassociate_tag namespace=nil
      @vtag.reassociate(self, namespace)

      @namespace = namespace
    end


    # Note: Most of the code involving the VirtualTag system is in tags.rb.
  end

  # If class can be written to file.
  module FileIO
    # Save any class to a file. Path should be given to the directory to save in.
    # example:  "player/Retnur.yml"
    def save_to_file file
      begin
        config = gen_configure
        File.open( file, 'w' ) do |out|
          YAML::dump config, out
        end
      rescue Exception=>e
        log :error, "Unable to write: #{file}"
        log_exception e
      end
    end
 
    # Load and configure a class from a file.   Path should be given to the directory to load from.
    # example:  "player/Retnur.yml"
    def load_from_file dir
      begin 
        a = YAML::load_file dir
        @when = Time.now.to_i # For finding out later if it needs to be reloaded.
                              # Class may or may not even make use of this.   Adding it at the time for help file support.
      rescue Exception=>e
        log_exception e
        log :error, "unable to load YAML."
        return nil
      end
      begin
        configure(a)
        return self
      rescue Exception=>e
        log_exception e
        log :error, "Unable to configure: #{dir}"
        return nil
      end
    end

    # convert map to instance.
    def configure data
      version = data[:version]

      # Note: These hooks do *not* need to be defined. 
      # They're only defined if you're using version controlling
      # or if you want more control on how data is transformed beyond generics.
      # hook for calling version_control
      if self.respond_to?:version_control
        data = self.version_control(version, data)
      end

      # Hook for calling data_transform
      if self.respond_to?:data_transform_on_load
        data = self.data_transform_on_load(version, data)
      end

      # load hash into object directly.   
      data.each do |key, value|
        if value.is_a?(String) && value == DEFAULT_STRING
          self.instance_variable_set(key, DEFAULT_STRING) # save a little memory.
        else
          self.instance_variable_set(key, value) # sets all instance variables by name of key.
        end
      
      end
    end

    # generate the hash we save.
    def gen_configure
      if respond_to?(:to_configure_properties) 
        #If this method is defined it will return an array of variables we must add to this hash.
        config_list = to_configure_properties

        data = {}
        # for each item we must configure...
        config_list.each do |item|
          val = instance_variable_get(item) # grab the value for this key
          data[item] = val # sets the value in our hash
        end

        # hook for transforming the data if need be.
        if respond_to?(:data_transform_on_save)
          data = data_transform_on_save(data)
        end
        return data
      end
    end
  end
end