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/
# Merchant class
# Author: Craig Smith

# This source code copyright (C) 2009 Craig Smith
# All rights reserved.
#
# Released under the terms of the TeensyMUD Public License
# See LICENSE file for additional information.
#

$:.unshift "lib" if !$:.include? "lib"

require 'gettext'
require 'core/gameobject'
require 'core/body'
require 'storage/properties'

class Merchant < Mobile
   include GetText
   bindtextdomain("core")
   logger 'DEBUG'

   MAX_MERCHANT_INV = 10

   property :forsale, :buytype, :buyattribute, :buydtype, :markup

   def initialize(name, owner, location=nil)
	super(name, owner, location)
	self.forsale = []	# Oids that merchant will have an unlimited supply of
	self.buytype = []	# Object types that merchant will only buy
	self.buyattribute = []	# Only buy objects with specified attributes
	self.buydtype = []	# Buy only weapons of these damage types
	self.markup = 0.20	# Markup percentage
   end

   # Event :list
   # List the items for sale
   # e.from = person requesting list
   def list(e)
	return if has_attribute? :zombie
	items = {}
	msg = _("----[ %{name}'s Items for Sale ]-------------------\n" % {:name => name})
	msg += sprintf("%-10s %-25s %s\n", _("Amount"),_("Item"), _("Cost"))
	msg << mxptag("StoreList")
	forsale.each do |oid|
		obj = get_object(oid)
		price = obj.cost + (obj.cost * markup).to_i
		imsg = sprintf("%-10s %-25s $%d\n", _("unlimited"),obj.shortname, price)
		msg += mxptag("Buy '#{obj.name}' '#{name}'") + imsg + mxptag("/Buy")
	end
        # Group items together
	contents.each do |oid|
		obj = get_object(oid)
		if obj.parentid
			haveid = obj.parentid
		else
			haveid = obj.id
		end
	   	if not forsale.include? haveid
			if items.has_key? haveid
				items[haveid] += 1
			else
				items[haveid] = 1
			end
	   	end
	end
	items.each do |oid, count|
		obj = get_object(oid)
		price = obj.cost + (obj.cost * markup).to_i
		imsg = sprintf("%-10s %-25s $%d\n", "[#{count}]",obj.shortname, price)
		msg += mxptag("Buy '#{obj.name}' '#{name}'") + imsg + mxptag("/Buy")
	end
	msg << mxptag("/StoreList")
	msg << "--------------------------------[End of List]----\n"
	add_event(id, e.from, :show, msg)
   end

   # Check if merchant would by that item
   # [+oid+] Oid to check to see if merchant will buy
   # [+return+] True if they will buy that item
   def willbuy(oid)
	return false if has_attribute? :no_buy
	obj = get_object(oid)
	# At least one of these must match
	if buytype.size > 0
		typematch = false
		buytype.each do |btype|
			typematch = true if obj.class.to_s == btype
		end
	else
		typematch = true
	end
	if buyattribute.size > 0
		attrmatch = false
		buyattribute.each do |battr|
			attrmatch = true if obj.has_attribute? battr
			attrmatch = true if obj.has_val? battr
		end
	else
		attrmatch = true
	end
	if buydtype.size > 0
		dtypematch = false
		buydtype.each do |dtype|
			# If the dtype is specified as bludgeon then allow any
			dtypematch = true if obj.has_attribute? dtype or dtype == "bludgeon"
		end
	else
		dtypematch = true
	end
	typematch and attrmatch and dtypematch
   end

   # [+objid+] Object to see how many we are carrying
   # [+return+] number of items fo that type
   def totalobjs(objid)
	o = get_object(objid)
	objid = o.parentid if o.parentid
	cnt = 0
	contents.each do |oid|
		cobj = get_object(oid)
		cnt += 1 if cobj.id == objid
		if cobj.parentid
			cnt += 1 if cobj.parentid == objid
		end
	end
	cnt
   end

   # Event :offer
   # Ask merchant to make an offer on an item
   # [+e+] e.from = requester, e.msg = oid to make offer on
   def offer(e)
	return if has_attribute? :zombie
	obj = get_object(e.msg)
	return if not obj
	if not willbuy(obj.id)
		msg = _("Sorry, but I won't buy that.")
		add_event(id, e.from, :show, msg)
		return
	end
	if totalobjs(obj.id) > MAX_MERCHANT_INV
		msg = _("Sorry but I have too many of those.")
		add_event(id, e.from, :show, msg)
		return
	end
	price = obj.cost - (obj.cost * markup).to_i
	if price > 0
		msg = _("I will give you $%{price} for that." % {:price => price})
		add_event(id, e.from, :show, msg)
	else
		msg = _("That's is not worth anything to me.")
		add_event(id, e.from, :show, msg)
	end
   end

   # Event :buy
   # Seems backwards but this is when a merchant SELLS something and a player buys
   # [+e+] e.from = buyer, e.msg = object name
   def buy(e)
	return if has_attribute? :zombie
	ch = get_object(e.from)
	oname = e.msg
	if oname.size < 1
		ch.sendto _("Buy what?")
		return
	end
	# First we check out contents
	tobuy = nil
	have = false
	contents.each do |oid|
		obj = get_object(oid)
		if obj.name =~/#{oname}/i
			tobuy = obj
			have = true
		end
	end
	# Didn't find anything in contents see if it is something we always sell
	if not have
		forsale.each do |oid|
			obj = get_object(oid)
			if obj.name =~/#{oname}/i
				tobuy = obj
			end
		end
	end
	if not tobuy
		msg = _("I do not have that item for sale.")
		add_event(id, ch.id, :show, msg)
	else
		price = tobuy.cost + (tobuy.cost * markup)
		if ch.get_stat(:cash) < price
			msg = _("You do not have enough money.")
			add_event(id, ch.id, :show, msg)
		else
			ch.adjust_stat(:cash, -price.to_i)
			msg = _("That will be $%{cost}." % {:cost => price.to_i})
			add_event(id, ch.id, :show, msg)
			if not have # We need to load a new object
				tobuy = world.load_object(tobuy.id)
				tobuy.location = id
				tobuy.reset if tobuy.respond_to? "reset"
				add_contents(tobuy.id)
			end
			add_event(id, ch.id, :give, tobuy.id)
		end
	end
   end

   # Event :sell
   # Seems backwards but this is when a merchant BUYS something and the player sells it
   # [+e+] e.from = seller, e.msg = oid of object to sell
   def sell(e)
	return if has_attribute? :zombie
	ch = get_object(e.from)
	obj = get_object(e.msg)
	if willbuy(obj.id)
		if totalobjs(obj.id) <= MAX_MERCHANT_INV
			price = obj.cost - (obj.cost * markup)
			ch.adjust_stat(:cash, price.to_i)
			msg = _("%{name} gives you $%{cost}." % {:name => name, :cost => price.to_i})
			add_event(id, ch.id, :show, msg)
			add_event(ch.id, id, :give, obj.id)
		else
			msg = _("I have too many of those.")
			add_event(id, ch.id, :show, msg)
		end
	else
		msg = _("I do not want that.")
		add_event(id, ch.id, :show, msg)
	end
   end
end