znmud-0.0.1/benchmark/
znmud-0.0.1/cmd/
znmud-0.0.1/cmd/emotes/
znmud-0.0.1/cmd/objects/
znmud-0.0.1/cmd/tiny/
znmud-0.0.1/doc/
znmud-0.0.1/farts/
znmud-0.0.1/lib/
znmud-0.0.1/lib/combat/
znmud-0.0.1/lib/core/bodytypes/
znmud-0.0.1/lib/engine/
znmud-0.0.1/lib/farts/
znmud-0.0.1/logs/
#
# file::    room.rb
# author::  Jon A. Lambert
# version:: 2.10.0
# date::    06/25/2006
#
# Additional Contributor: Craig Smith
#
# This source code copyright (C) 2005, 2006 by Jon A. Lambert
# All rights reserved.
#
# Released under the terms of the TeensyMUD Public License
# See LICENSE file for additional information.
#
$:.unshift "lib" if !$:.include? "lib"
$:.unshift "vendor" if !$:.include? "vendor"

require 'network/protocol/mxpcodes'
require 'core/gameobject'
require 'core/spawn'
require 'gettext'

# The Room class is the mother of all rooms.
#
class Room < GameObject
  property :exits, :spawns
  logger 'DEBUG'

  include GetText
  include MXPCodes
  bindtextdomain("core")

  # Create a new Room object
  # [+name+]   The displayed name of the room
  # [+owner+]    The owner id of this room
  # [+return+] A handle to the new Room.
  def initialize(name, owner)
    super(name, owner)
    self.exits=[]               # The list of exits for this room.
    self.spawns=[]		# Objects to spawn here
  end

  # Resets a room
  # Removes stale entries that can come from shutting down the server
  def reset
	# Remove any stale user accounts
	contents.each do |oid|
		o = get_object(oid)
		if o.is_a? Character and not o.account and not o.kind_of? Mobile
			log.info "Purging stale contents #{oid} from Room #{id}."
			contents.delete oid
		end
	end
  end

  # Lists the characters in the room
  # [+notid+] Optional id of who not to return
  # [+return+] Array of character objects
  def characters(notid=nil)
	ppl = []
	contents.each do |oid|
		o = get_object(oid)
		if o.kind_of? Character
			if notid
				ppl << o if not notid == oid
			else
				ppl << o
			end
		end
	end
	ppl
  end

  # Sends a message to all characters in a room
  # [+msg+]     Message to broadcast
  # [+notid+]   Optional person to leave out of the broadcast
  def say(msg, notid=nil)
    if not msg.is_a? Msg
	msg = Msg.new(msg)
	msg.broadcast = true
    end
    if notid
    	characters(notid).each do |x|
		add_event(id,x.id,:show, msg) if x.account and x.cansee?
    	end
    else
    	characters.each do |x|
      		add_event(id,x.id,:show, msg) if x.account and x.cansee?
	end    	
    end
  end

  # Sends a message to the "rest" of the players in the room except
  # for notid1 and notid2
  # [+msg+] Message to display
  # [+notid1+] First person to skip
  # [+notid2+] Second person to skip
  def sayrest(msg, notid1, notid2)
    	characters(notid1).each do |x|
		add_event(id,x.id,:show, msg) if x.account and x.cansee? and not x.id == notid2
    	end
  end

  # Get the MP cost to move through this room via the modifier
  # [+return+] cost in MP to move through this room
  def mpcost
  	cost = 1
	cost += get_modifier("mp").abs
	cost
  end

  # Searches current room for an object by name
  # [+obj+] object name to serach for.  Supports 2.obj, etc.
  # [+return+] an array of objects that match that obj name
  def find_objects(what)
	objs = []
	nth = 1
	found = 0
	if what=~/^(\d+)\.(.*)/
		nth = $1.to_i
		what = $2
	elsif what=~/^all\.(.*)/
		nth = nil
		what = $1
	end
	objects.each do |o|
		gotname = false
		if o.name =~/^#{what}$/i
			gotname = true
		elsif o.aliases.size > 0
			o.aliases.each do |a|
				gotname = true if a=~/^#{what}$/
			end
		end
		if gotname	
			found += 1
			if not nth
				objs << o
			elsif found == nth
				objs << o
			end
		end
	end
	objs
  end

  # Returns if the room is dark
  # [+return+] true if room is dark
  def is_dark?
	return false if has_attribute? :bright
	return true if has_attribute? :dark
	return true if world.climate.night and not has_attribute? :inside
	false
  end

  # Event :describe
  # [+e+]      The event
  # [+return+] Undefined
  def describe(e)
    msg = "[COLOR Green]"
    if world.can_build? e.from
    	msg << "(#{id.to_s})"
	msg << "[#{mpcost}]" if mpcost > 1
	msg << " "
	if spawns
		msg << "*" if spawns.size > 0
	end
    end
    msg << mxptag("RName") + name + mxptag("/RName")
    if attributes
    	msg << " #{attributes.inspect}" if world.can_build? e.from and attributes.size > 0
    end
    msg << "[/COLOR]\n"
    if get_object(e.from).cansee? :dark
    	msg << mxptag("RDesc") + desc + mxptag("/RDesc") + "\n"
    else
	msg << _("It is dark.\n")
    end
    add_event(id,e.from,:show,msg)
  end

  # Event :describe_exits
  # [+e+]      The event
  # [+return+] Undefined
  def describe_exits(e)
    msg = "[COLOR Red]" + _("Exits:") +"\n"
    s = exits.size
    if s == 0
      msg << _("None.")+"[/COLOR]"
    else
      i = 0
      exits.each do |exid|
        ex = get_object(exid)
        key = ex.name.split(/;/).first
        msg << mxptag("Ex") + key + mxptag("/Ex")
        i += 1
        case s - i
        when 1 then s > 2 ? msg << "," + _(" and ") : msg << _(" and ")
        when 0 then msg << "."
        else
          msg << ", "
        end
      end
      msg << "[/COLOR]"
    end
    add_event(id,e.from,:show,msg)
  end

  # Event :spawn
  # [+e+]	Event to spawn all pending objects
  # [+return+]  Undefined
  def spawn(e)
	spawns.each do |s|
		spawnobj = get_object(s)
		# Check to make sure you dont exceed the max_in_room value
		in_room = 0
		contents.each do |oid|
			obj = get_object(oid)
			in_room += 1 if obj.id == spawnobj.targetid
			if obj.parentid
				in_room += 1 if obj.parentid == spawnobj.targetid
			end
		end
		if in_room < spawnobj.max_in_room
			o = spawnobj.load
			if o
				o.location = id
				case o
				when Mobile
					add_event(id, id, :arrive,o.id)
				else
					add_contents(o.id)
				end
			end
		end
	end
  end

  # Event :arrive
  # [+e+]      The event
  # [+return+] Undefined
  def arrive(e)
    ch = get_object(e.msg)
    # add character
    add_contents(ch.id) if not contents.include? ch.id
    ch.location = id
    infectguard = nil
    # While we are parsing through players check for special players
    characters(e.msg).each do |x|
	msg = Msg.new _("^p1 has arrived.")
	msg.p1 = ch.name
        msg.is_invisible = true if ch.has_attribute? :invisible
	add_event(id,x.id,:show,msg)
	infectguard = x if x.has_attribute? :infect_guard
    end
    # Check if the person is infected and it is an infect_guard location
    if ch.has_attribute? :infected and infectguard
	ch.sendroom _("%{guard} scans %{name}'s eye then a siren sounds, \"INFECTED! INFECTED!\"" % {:guard => infectguard.name, :name => ch.name})
	ch.sendto _("%{guard}, at point blank range, blows off your head!!" % {:guard => infectguard.name})
	ch.sendrest( _("%{guard} unloads his weapon and blows off %{name}'s head!" % {:guard => infectguard.name, :name => ch.name}), ch.id)
	ch.make_corpse
	return
    end
    # If player is holding a light that requires power use it.
    light = ch.has_light?
    if light
	if light.has_val? :powered_from and light.respond_to? "use_power"
		left = light.use_power
		if left == 1
			ch.sendto _("Your %{light} flickers." % {:light => light.name})
		elsif left == 0
			# Check to make sure there are not alternate fuels stored too
			if not light.has_power?
				# Nope, that was it...die
				ch.sendto _("Your %{light} flickers and dies." % {:light => light.name})
				msg = Msg.new("^p1 %{light} flickers and dies." % {:light => light.name})
				msg.p1 = ch.name
				add_event(ch.id, ch.id, :roomsay, msg)
			end
		end
        end
    end
    ch.parse('look') if ch.account
  end

  # Event :dig
  # [+e+]      Event
  # [+return+] Undefined
  def dig(e)
  	ch = get_object(e.from)
	dig_cost = 3
	dig_cost = 0 if world.can_build? ch.id
	if ch.stats[:mp]-dig_cost > 0
		ch.stats[:mp] -= dig_cost
		objects.each do |o|
			if o.has_attribute? :buried
				o.del_attribute(:buried)
				chmsg = Msg.new _("You dig up ^o1!")
				chmsg.o1 = o.shortname
				add_event(id,e.from,:show,chmsg)
				rmsg = Msg.new _("^p1 digs up ^o1!")
				rmsg.p1 = ch.name
				rmsg.o1 = o.shortname
				add_event(e.from,e.from,:roomsay,rmsg)
			end
		end
	else
		add_event(id,e.from,:show, _("You are too exhausted to dig right now."))
	end
  end
end