tmi2_fluffos_v2/
tmi2_fluffos_v2/bin/
tmi2_fluffos_v2/etc/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/ChangeLog.old/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/Win32/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/compat/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/compat/simuls/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/include/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/clone/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/command/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/data/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/etc/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/include/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/inherit/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/inherit/master/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/log/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/compiler/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/efuns/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/operators/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/u/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/tmp/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/windows/
tmi2_fluffos_v2/lib/
tmi2_fluffos_v2/lib/adm/
tmi2_fluffos_v2/lib/adm/daemons/languages/
tmi2_fluffos_v2/lib/adm/daemons/network/I3/
tmi2_fluffos_v2/lib/adm/daemons/virtual/
tmi2_fluffos_v2/lib/adm/daemons/virtual/template/
tmi2_fluffos_v2/lib/adm/news/
tmi2_fluffos_v2/lib/adm/obj/
tmi2_fluffos_v2/lib/adm/obj/master/
tmi2_fluffos_v2/lib/adm/priv/
tmi2_fluffos_v2/lib/adm/shell/
tmi2_fluffos_v2/lib/adm/tmp/
tmi2_fluffos_v2/lib/cmds/
tmi2_fluffos_v2/lib/d/
tmi2_fluffos_v2/lib/d/Conf/
tmi2_fluffos_v2/lib/d/Conf/adm/
tmi2_fluffos_v2/lib/d/Conf/boards/
tmi2_fluffos_v2/lib/d/Conf/cmds/
tmi2_fluffos_v2/lib/d/Conf/data/
tmi2_fluffos_v2/lib/d/Conf/logs/
tmi2_fluffos_v2/lib/d/Conf/obj/
tmi2_fluffos_v2/lib/d/Conf/text/help/
tmi2_fluffos_v2/lib/d/Fooland/adm/
tmi2_fluffos_v2/lib/d/Fooland/data/
tmi2_fluffos_v2/lib/d/Fooland/data/attic/
tmi2_fluffos_v2/lib/d/Fooland/items/
tmi2_fluffos_v2/lib/d/TMI/
tmi2_fluffos_v2/lib/d/TMI/adm/
tmi2_fluffos_v2/lib/d/TMI/boards/
tmi2_fluffos_v2/lib/d/TMI/data/
tmi2_fluffos_v2/lib/d/TMI/rooms/
tmi2_fluffos_v2/lib/d/grid/
tmi2_fluffos_v2/lib/d/grid/adm/
tmi2_fluffos_v2/lib/d/grid/data/
tmi2_fluffos_v2/lib/d/std/
tmi2_fluffos_v2/lib/d/std/adm/
tmi2_fluffos_v2/lib/data/adm/
tmi2_fluffos_v2/lib/data/adm/daemons/
tmi2_fluffos_v2/lib/data/adm/daemons/doc_d/
tmi2_fluffos_v2/lib/data/adm/daemons/emoted/
tmi2_fluffos_v2/lib/data/adm/daemons/network/http/
tmi2_fluffos_v2/lib/data/adm/daemons/network/services/mail_q/
tmi2_fluffos_v2/lib/data/adm/daemons/network/smtp/
tmi2_fluffos_v2/lib/data/adm/daemons/news/archives/
tmi2_fluffos_v2/lib/data/attic/connection/
tmi2_fluffos_v2/lib/data/attic/user/
tmi2_fluffos_v2/lib/data/std/connection/b/
tmi2_fluffos_v2/lib/data/std/connection/l/
tmi2_fluffos_v2/lib/data/std/user/a/
tmi2_fluffos_v2/lib/data/std/user/b/
tmi2_fluffos_v2/lib/data/std/user/d/
tmi2_fluffos_v2/lib/data/std/user/f/
tmi2_fluffos_v2/lib/data/std/user/l/
tmi2_fluffos_v2/lib/data/std/user/x/
tmi2_fluffos_v2/lib/data/u/d/dm/working/doc_d/
tmi2_fluffos_v2/lib/data/u/l/leto/doc_d/
tmi2_fluffos_v2/lib/data/u/l/leto/smtp/
tmi2_fluffos_v2/lib/doc/
tmi2_fluffos_v2/lib/doc/driverdoc/applies/
tmi2_fluffos_v2/lib/doc/driverdoc/applies/interactive/
tmi2_fluffos_v2/lib/doc/driverdoc/concepts/
tmi2_fluffos_v2/lib/doc/driverdoc/driver/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/arrays/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/buffers/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/compile/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/ed/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/filesystem/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/floats/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/functions/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/general/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/mappings/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/numbers/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/parsing/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/constructs/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/preprocessor/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/types/
tmi2_fluffos_v2/lib/doc/driverdoc/platforms/
tmi2_fluffos_v2/lib/doc/mudlib/
tmi2_fluffos_v2/lib/ftp/
tmi2_fluffos_v2/lib/include/driver/
tmi2_fluffos_v2/lib/log/
tmi2_fluffos_v2/lib/log/driver/
tmi2_fluffos_v2/lib/obj/net/
tmi2_fluffos_v2/lib/obj/shells/
tmi2_fluffos_v2/lib/obj/tools/
tmi2_fluffos_v2/lib/std/adt/
tmi2_fluffos_v2/lib/std/board/
tmi2_fluffos_v2/lib/std/body/
tmi2_fluffos_v2/lib/std/fun/
tmi2_fluffos_v2/lib/std/living/
tmi2_fluffos_v2/lib/std/object/
tmi2_fluffos_v2/lib/std/shop/
tmi2_fluffos_v2/lib/std/socket/
tmi2_fluffos_v2/lib/std/user/
tmi2_fluffos_v2/lib/std/virtual/
tmi2_fluffos_v2/lib/student/
tmi2_fluffos_v2/lib/student/kalypso/
tmi2_fluffos_v2/lib/student/kalypso/armor/
tmi2_fluffos_v2/lib/student/kalypso/rooms/
tmi2_fluffos_v2/lib/student/kalypso/weapons/
tmi2_fluffos_v2/lib/u/l/leto/
tmi2_fluffos_v2/lib/u/l/leto/cmds/
tmi2_fluffos_v2/lib/www/errors/
tmi2_fluffos_v2/lib/www/gateways/
tmi2_fluffos_v2/lib/www/images/
tmi2_fluffos_v2/old/
tmi2_fluffos_v2/win32/
// shop.c
// A basic shop with a basic storeroom.
// Written by Mobydick@TMI-2, 8-25-92

#include <move.h>
#include <mudlib.h>
#include <money.h>

inherit ROOM ;
inherit COINVALUE ;

object storeroom ;
object ob,ob2 ;

void create() {
	seteuid(getuid()) ;
	::create() ;

/* Force the warehouse to load, if it's not loaded  */

	CENTSTORE->frog() ;
}

void init() {
	add_action ("list", "list") ;
	add_action ("value", "value") ;
	add_action ("buy", "buy") ;
	add_action ("sell", "sell") ;
	add_action ("enter_storeroom", "storeroom") ;
}



int list() {

        int i,j,k ;
	string str, foo;
        string *shorts, *coins ;
        int *number, *price ;
        mixed *value ;
	object *frog ;

	write ("The following objects are for sale:\n") ;

#define NUM_STR ({ "Zero", "One", "Two", "Three", "Four", "Five", "Six", \
	"Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", \
	"Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", \
	"Eighteen", "Nineteen", "Twenty" })

	frog = all_inventory(storeroom) + 
		all_inventory(find_object_or_load(CENTSTORE)) ;

	shorts = ({ }) ;
	coins = ({ }) ;
	number = ({ }) ;
	price = ({ }) ;
        for (i=0;i<sizeof(frog);i++) {
            str = (string)frog[i]->query("short") ;
	    if (str[0..1]=="a ") str=str[2..<1] ;
	    if (str[0..2]=="an ") str=str[3..<1] ;
	    if (str[0..3]=="the ") str=str[4..<1] ;
	    value = (mixed *)frog[i]->query("value") ;
	    if (!value || sizeof(value)!=2) continue ;
            j = -1 ;
            for (k=0;k<sizeof(shorts);k++) {
                if (str==shorts[k] && value[0]==price[k] &&
                       value[1]==coins[k]) {
                    j = k ;
                    continue ;
                }
            }
            if (j==-1) {
                shorts += ({ str }) ;
                number += ({ 1 }) ;
		value = frog[i]->query("value") ;
                price += ({ value[0] }) ;
                coins += ({ value[1] }) ;
            } else {
                number[j] += 1 ;
            }
        }
        for (i=0;i<sizeof(shorts);i++) {
            if (number[i]>20) {
		foo = "Many" ;
            } else {
		foo = NUM_STR[number[i]] ;
            }
	    foo += " " ;
            if (number[i]==1) {
		foo += shorts[i] ;
            } else {
		foo += pluralize(shorts[i]) ;
            }
	    write (sprintf("   %-42s %d %s\n",foo,price[i],coins[i])) ;
        }
	return 1 ;
}

int buy(string str) {

	int number, i, j, k, l, has, res ;
	string type ;
	object ob ;
	string *types ;
	mixed *value ;
	int oldval, newval, newnum, leftnum ;

/* Look for the object, first in central storage then in local storage. */

	if (!str) {
		notify_fail ("What would you like to buy?\n") ;
		return 0 ;
	}
	ob = present(str,find_object(CENTSTORE)) ;
	if (!ob) ob = present (str,storeroom) ;
	if (!ob) {
		notify_fail ("We don't have one of those for sale.\n") ;
		return 0 ;
	}
	value = ob->query("value") ;
	if (!value) {
		notify_fail ("That object should not have been in the shop.\n");
		ob->remove() ;
		return 0 ;
	}
	type = value[1] ;
	number = value[0] ;
	if (number==0) {
                notify_fail ("That object should not have been in the shop.\n");
		ob->remove() ;
		return 0 ;
	}

// Check to see if the player has exact change.

	i = this_player()->query("wealth/"+type) ;
	if (i>=number) {
		this_player()->set("wealth/"+type,i-number) ;
		j = this_player()->query("capacity") ;
		this_player()->set("capacity", j+number) ;
// See if the player can carry the object.
		res = ob->move(this_player()) ;
		if (res==MOVE_OK) {
			write ("The shopkeeper hands you "+(string)ob->query("short")+".\n") ;
			say (this_player()->query("cap_name")+" buys a "+ob->query("short")+".\n") ;
			return 1 ;
		} else {
// Give him his money back.
			this_player()->set("wealth/"+type,i) ;
			this_player()->set("capacity",j) ;
			write ("You cannot carry that object.\n") ;
			return 0 ;
		}
	}

// The rest of the procedure tries to let the player use other combinations
// of coins to buy the object. Clever players can use this to convert coins
// for free, by buying a 50 silver coin object for 5 gold and then selling
// it back for 50 silver. If you don't want this to happen, either have the
// shops return less than exact value on sales, or rip out the following
// code.

// Check to see if this is a convertable type of coin. If it isn't then
// the player cannot buy the object.

	types = cointypes() ;
	j = member_array (type,types) ;
	if (j==-1) {
		notify_fail ("You don't have "+number+" "+type+" and the shop cannot convert that to other coins.\n") ;
		return 0 ;
	}

// Check to see if he has enough total wealth to buy the object. If he
// doesn't we can save a lot of CPU time by giving up now.

	res = this_player()->total_wealth() ;
	k = this_player()->query("wealth/"+type) ;
	oldval = coinvalue(type) ;
	if (res<k*oldval) {
		write ("You can't afford that!\n") ;
		return 0 ;
	}

// First check higher-valued coins, lowest to highest, to see if the player
// can buy the object exactly for some combination of the higher-valued
// coin and the stated coin.

	for (i=j-1;i>=0;i--) {
	newval = coinvalue(types[i]) ;
	newnum = (oldval*number)/newval ;
	leftnum = ((oldval*number)-(newnum*newval))/oldval ;

// If the player has enough of the new type, he buys the item.

	has = this_player()->query("wealth/"+types[i]) ;
	if (has>=newnum && k>=leftnum) {
		this_player()->set("wealth/"+types[i],has-newnum) ;
		this_player()->set("wealth/"+type,k-leftnum) ;
		l = this_player()->query("capacity") ;
		this_player()->set("capacity",l+newnum+leftnum) ;
		res = ob->move(this_player()) ;
		if (res==MOVE_OK) {
			write ("The shopkeeper hands you "+(string)ob->query("short")+".\n") ;
			say (this_player()->query("cap_name")+" buys a "+ob->query("short")+".\n") ;
			return 1 ;
		} else {
			this_player()->set("wealth/"+types[i],has) ;
			this_player()->set("wealth/"+type,k) ;
			this_player()->set("capacity",l) ;
			write ("You cannot carry that object.\n") ;
			return 1 ;
		}
	}

// If that didn't work, try using all the player has of the stated coin, plus
// as many of the new coin type as necessary.

	newnum = (oldval*(number-k))/newval ;
	if ((oldval*number)-(newval*newnum)>(k*oldval)) newnum = newnum + 1 ;
	leftnum = ((oldval*number)-(newnum*newval))/oldval ;

	has = this_player()->query("wealth/"+types[i]) ;
	if (has>=newnum && k>=leftnum) {
		this_player()->set ("wealth/"+types[i],has-newnum) ;
                this_player()->set("wealth/"+type,k-leftnum) ;
                l = this_player()->query("capacity") ;
                this_player()->set("capacity",l+newnum+leftnum) ;
                res = ob->move(this_player()) ;
		if (res==MOVE_OK) {
			write ("The shopkeeper hands you "+(string)ob->query("short")+".\n") ;
			say (this_player()->query("cap_name")+" buys a "+ob->query("short")+".\n") ;
                	return 1 ;
		} else {
			this_player()->set("wealth/"+types[i],has) ;
                        this_player()->set("wealth/"+type,k) ;
                        this_player()->set("capacity",l) ;
                        write ("You cannot carry that object.\n") ;
                        return 1 ;
                }
        }

// If neither of those two worked, give up and try the next coin type.

	}

// Higher types didn't work. Now we try all less valuable coin types and
// see if we can buy it for all he possesses of the stated type plus some
// of the lower-valued type.

	for (i=j+1;i<sizeof(types);i++) {
	newval = coinvalue(types[i]) ;
	newnum = ((number-k)*oldval)/newval ;
	has = this_player()->query("wealth/"+types[i]) ;
	if (has>=newnum) {
		this_player()->set("wealth/"+types[i],has-newnum) ;
		this_player()->set("wealth/"+type,0) ;
		l = this_player()->query("capacity") ;
		this_player()->set("capacity",l+k+newnum) ;
		res = ob->move(this_player()) ;
		if (res==MOVE_OK) {
			write ("The shopkeeper hands you "+(string)ob->query("short")+".\n") ;
			say (this_player()->query("cap_name")+" buys a "+ob->query("short")+".\n") ;
			return 1 ;
		} else {
			this_player()->set("wealth/"+types[i],has) ;
                        this_player()->set("wealth/"+type,k) ;
                        this_player()->set("capacity",l) ;
                        write ("You cannot carry that object.\n") ;
                        return 1 ;
                }
	}

// If that didn't work, try the next coin type.

	}

// OK, it looks like he can't buy it for exact change. Now, try all the
// higher types again, this time giving whatever change is necessary.

	for (i=j-1;i>=0;i--) {
	newval = coinvalue(types[i]) ;
	newnum = (oldval*number)/newval ;
	if ((oldval*number)-(newval*newnum)>0) newnum = newnum + 1 ;
	leftnum = ((newval*newnum)-(oldval*number))/oldval ;
	has = this_player()->query("wealth/"+types[i]) ;
	if (has>=newnum) {
		this_player()->set("wealth/"+types[i],has-newnum) ;
		this_player()->set("wealth/"+type,k+leftnum) ;
		l = this_player()->query("capacity") ;
		this_player()->set("capacity",l+newnum-leftnum) ;
		res = ob->move(this_player()) ;
		if (res==MOVE_OK) {
			write ("The shopkeeper hands you "+(string)ob->query("short")+".\n") ;
			say (this_player()->query("cap_name")+" buys a "+ob->query("short")+".\n") ;
			return 1 ;
		} else {
			this_player()->set("wealth/"+types[i],has) ;
                        this_player()->set("wealth/"+type,k) ;
                        this_player()->set("capacity",l) ;
                        write ("You cannot carry that object.\n") ;
                        return 1 ;
                }
	}

//  That didn't work, so try the next type.

	}

// That's enough of this. We give up: he can't buy it from us.

	notify_fail ("You don't have the right coins to buy that.\n") ;
	return 0 ;
}

int value(string str) {

	object *ob, obj ;
	string word ;
	string *types ;
	int i, number, changenum ;
	string type, changetype ;
	mixed *value ;
	int newval, oldval, newnum, j ;

	if (!str) {
		ob = all_inventory(this_player()) ;
		if (!ob) {
			notify_fail("You don't have any belongings.\n") ;
			return 0 ;
		}
		for (i=0;i<sizeof(ob);i++) {
			value = ob[i]->query("value") ;
			if (!value) {
				write (ob[i]->query("short")+" has no value.\n") ;
				continue ;
			}
			type = value[1] ;
			number=value[0] ;
		 	if (number==0) {
				write (ob[i]->query("short")+" has no value.\n") ;
				continue ;
			}

// If it's a coin we can make change for, we multiply by the sales fraction
// and calculate how much to give back of the stated coin and the lower-
// valued coin. If it's the lowest value coin, or if it's not list with
// coinvalue.c, we just take off the fraction and sell for that.

			types = cointypes() ;
			j = member_array(type,types) ;
			if (j==-1 || j==sizeof(types)-1) {
				newnum = number*SHOP_SALES_FRAC ;
				if (newnum==0) newnum=1 ;
				if (newnum==1) word="coin" ; else word="coins" ;
				write (ob[i]->query("short")+" is worth "+newnum+" "+type+" "+word+".\n") ;
			} else {
				changetype = types[j+1] ;
				oldval = coinvalue(type) ;
				newval = coinvalue(changetype) ;
				newnum = (number*oldval*SHOP_SALES_FRAC)/oldval;
				changenum = ((number*oldval*SHOP_SALES_FRAC)-(newnum*oldval))/newval ;
				if (newnum==1) word="coin" ; else word="coins" ;
				write (ob[i]->query("short")+" is worth "+newnum+" "+type+" "+word) ;
				if (changenum==0) {
					write (".\n") ;
				} else {
					if (changenum==1) word="coin" ; else word="coins" ;
				write (" and "+changenum+" "+changetype+" "+word+".\n") ;
				}
			}
		}
		return 1 ;
	}
	obj = present(str,this_player()) ;
	if (!obj) {
		notify_fail ("You don't have a "+str+".\n") ;
		return 0 ;
	}
	value = obj->query("value") ;
	if (!value) {
		notify_fail ("That object is not worth anything.\n") ;
		return 0 ;
	}
	type = value[1] ;
	number = value[0] ;
	if (number==0) {
		notify_fail ("That object is not worth anything.\n") ;
		return 0 ;
	}
	types = cointypes() ;
	j = member_array(type,types) ;
	if (j==-1 || j==sizeof(types)-1) {
		newnum = number*SHOP_SALES_FRAC ;
		if (newnum==0) newnum=1 ;
		if (newnum==1) word="coin" ; else word="coins" ;
		write (obj->query("short")+" is worth "+newnum+" "+type+" "+word+".\n") ;
	} else {
		changetype = types[j+1] ;
		oldval = coinvalue(type) ;
		newval = coinvalue(changetype) ;
		newnum = (number*oldval*SHOP_SALES_FRAC)/oldval;
		changenum = ((number*oldval*SHOP_SALES_FRAC)-(newnum*oldval))/newval ;
		if (newnum==1) word="coin" ; else word="coins" ;
		write (obj->query("short")+" is worth "+newnum+" "+type+" "+word) ;
		if (changenum==0) {
			write (".\n") ;
		} else {
			if (changenum==1) word="coin" ; else word="coins" ;
			write (" and "+changenum+" "+changetype+" "+word+".\n") ;
		}
	}
	return 1 ;
}

int sell(string str) {

	int i, j, l, res ;
	int newnum, changenum ;
	int oldval, newval ;
	string changetype ;
	object ob ;
	string *types ;
	object *obs ;
	string type, word ;
	mixed *value ;
	int number ;

	if (!str) {
		notify_fail("What do you want to sell?\n") ;
		return 0 ;
	}
	if (str=="all") {
		obs = all_inventory(this_player()) ;
		for (i=0;i<sizeof(obs);i++) {
			value = obs[i]->query("value") ;
			if (!value) continue ;
			number = value[0] ;
			if (number<1) continue ;
			if (obs[i]->query("prevent_drop")) continue ;
			res=(int)obs[i]->move(storeroom) ;
			if (res!=MOVE_OK) continue ;
			type = value[1] ;
			res=(int)this_player()->query("wealth/"+type) ;
			types = cointypes() ;
			j = member_array(type,types) ;
			if (j==-1 || j==sizeof(types)-1) {
				newnum = number*SHOP_SALES_FRAC ;
				if (newnum==0) newnum=1 ;
				l = this_player()->query("capacity") ;
				if (l<newnum) {
					write ("You can't carry the coins from selling "+obs[i]->query("short")+".\n") ;
					obs[i]->move(this_player()) ;
					continue ;
				}
				if (newnum==1) word="coin" ; else word="coins" ;
				write ("You sell "+obs[i]->query("short")+" for "+newnum+" "+type+" "+word+".\n") ;
				say (this_player()->query("cap_name")+" sells a "+obs[i]->query("short")+".\n") ;
				this_player()->set("wealth/"+type,newnum+res) ;
				this_player()->set("capacity",l-newnum) ;
			} else {
				changetype = types[j+1] ;
				oldval = coinvalue(type) ;
				newval = coinvalue(changetype) ;
				newnum = (number*oldval*SHOP_SALES_FRAC)/oldval;
				changenum = ((number*oldval*SHOP_SALES_FRAC)-(newnum*oldval))/newval ;
				l = this_player()->query("capacity") ;
				if (l<newnum+changenum) {
					write ("You can't carry the coins from selling "+obs[i]->query("short")+".\n") ;
					obs[i]->move(this_player()) ;
					continue ;
				}
				if (newnum==1) word="coin" ; else word="coins" ;
				write ("You sell "+obs[i]->query("short")+" for "+newnum+" "+type+" "+word) ;
				say (this_player()->query("cap_name")+" sells a "+obs[i]->query("short")+".\n") ;
				this_player()->set("wealth/"+type,newnum+res) ;
				if (changenum==0) {
					write (".\n") ;
				} else {
					if (changenum==1) word="coin" ; else word="coins" ;
					write (" and "+changenum+" "+changetype+" "+word+".\n") ;
					res = this_player()->query("wealth/"+changetype) ;
					this_player()->set("wealth/"+changetype,res+changenum) ;
				}
				this_player()->set("capacity",l-newnum-changenum) ;
			}
		}
		return 1 ;
	}
	ob = present(str,this_player()) ;
	if (!ob) {
		notify_fail("You don't have one to sell!\n") ;
		return 0 ;
	}
	value = ob->query("value") ;
	if (value==0) {
		notify_fail ("That has no value.\n") ;
		return 0 ;
	}
	number=value[0] ;
	if (number<1) {
		notify_fail ("That has no value.\n") ;
		return 0 ;
	}
	if (ob->query("prevent_drop")) {
		notify_fail ("You cannot bear to part with it.\n") ;
		return 0 ;
	}
	type = value[1] ;
        res = ob->move(storeroom) ;
        if (res != MOVE_OK) {
                notify_fail ("You can't sell that!\n") ;
                return 0 ;
        }
	res = (int)this_player()->query("wealth/"+type) ;
	if (number==0) {
		notify_fail ("That object is not worth anything.\n") ;
		return 0 ;
	}
	types = cointypes() ;
	j = member_array(type,types) ;
	if (j==-1 || j==sizeof(types)-1) {
		newnum = number*SHOP_SALES_FRAC ;
		if (newnum==0) newnum=1 ;
		l = this_player()->query("capacity") ;
		if (l<newnum) {
			write ("You can't carry the coins you'd get for selling "+ob->query("short")+".\n") ;
			ob->move(this_player()) ;
			return 1 ;
		}
		if (newnum==1) word="coin" ; else word="coins" ;
		write ("You sell "+ob->query("short")+" for "+newnum+" "+type+" "+word+".\n") ;
		say (this_player()->query("cap_name")+" sells a "+ob->query("short")+".\n") ;
		this_player()->set("wealth/"+type,newnum+res) ;
		this_player()->set("capacity",l-newnum) ;
	} else {
		changetype = types[j+1] ;
		oldval = coinvalue(type) ;
		newval = coinvalue(changetype) ;
		newnum = (number*oldval*SHOP_SALES_FRAC)/oldval;
		changenum = ((number*oldval*SHOP_SALES_FRAC)-(newnum*oldval))/newval ;
		l = this_player()->query("capacity") ;
		if (l<newnum+changenum) {
                        write ("You can't carry the coins you'd get for selling "+ob->query("short")+".\n") ;
			ob->move(this_player()) ;
			return 1 ;
		}
		if (newnum==1) word="coin" ; else word="coins" ;
		write ("You sell "+ob->query("short")+" for "+newnum+" "+type+" "+word) ;
		say (this_player()->query("cap_name")+" sells a "+ob->query("short")+".\n") ;
		this_player()->set("wealth/"+type,newnum+res) ;
		if (changenum==0) {
			write (".\n") ;
		} else {
			if (changenum==1) word="coin" ; else word="coins" ;
			write (" and "+changenum+" "+changetype+" "+word+".\n");
			res = this_player()->query("wealth/"+changetype) ;
			this_player()->set("wealth/"+changetype,changenum+res) ;
		}
		this_player()->set("capacity",l-newnum-changenum) ;
	}
	return 1 ;
}

int enter_storeroom() {
	if (!wizardp(this_player())) return 0 ;
	this_player()->move(storeroom) ;
	return 1 ;
}