@create #18181 named RPG Money Manager:RPG Money Manager,MM
"#245.("usage") => E_PERM (Permission denied)
;;#245.("users") = {#22630, #24436, #29209, #46102, #49397, #50290, #50367, #55090, #56054, #58091, #58421, #58793, #58806, #59324, #59513, #74428, #76231, #76404, #78047, #81861, #72264, #67439, #59560, #63546, #37972, #87929, #87750, #63625, #87485, #78610, #53702, #90685, #90731, #85431, #94616, #38341, #94456, #80422, #63635, #94368, #89337, #58420, #91345, #89391, #97851, #98048, #98232, #59424, #58026, #94304, #86232, #96662, #92475, #89480, #53410, #56568, #81133, #97613, #99949, #98263, #101185, #100289, #80578, #91352, #101547, #100314, #88395, #94965, #102021, #99063, #103703, #91812, #104467, #101651, #101504, #89208, #47818, #104202, #90441, #105290, #99130, #96788, #86275, #105770, #103911, #85077, #90323, #108054, #107682, #100337, #81934, #103615, #108850, #9833, #107629, #103523, #97170, #71111, #108140, #107509, #64729, #97902, #108214, #106587, #97084, #96899, #108294, #106037, #110400, #112066, #110660, #110280, #112369, #107850, #110565, #112743, #90473, #112968, #108147, #112823, #108108, #100173, #87721, #59254, #48498, #87951, #106854, #109506, #114382, #103689, #112837, #110586, #114019, #114639, #114702, #114518, #100674, #113418, #112478, #105408, #98705, #87010, #115197, #114928, #115397, #105539, #114241, #87340, #107413, #113956, #110077, #115432, #37544, #116031, #64985, #114652, #113391, #116339, #116385, #87593, #113235, #116358, #107759, #116342, #116405, #58377, #107985, #116729, #116473, #113285, #106189, #91798, #115937, #116886, #116995, #115200, #117048, #38441, #69513, #114233, #108263, #115922, #116305, #117275, #117283, #109546, #112886, #116569, #116369, #98580, #116376, #114430, #12399, #118143, #109263, #92476, #90723, #97612, #88076, #30788, #112527, #101594, #117236, #103685, #116852, #118248, #35076, #118487, #118890, #107704, #118654, #118740, #86050, #119424, #109615, #119469, #110787, #115124, #119554, #119116, #111890, #119701, #86471, #107618, #114174, #119594, #120144, #120227, #120260, #120239, #120283, #114206, #117100, #120420, #118824, #120376, #120546, #120070, #120749, #57402, #121000, #121077, #121095, #121149, #121104, #120201, #121241, #119957, #121358, #121648, #121651, #117139, #121188, #121895, #121918, #121965, #121976, #121070, #115805, #114072, #110582, #122423, #118977, #119530, #122453, #122460, #122491, #122525, #122601, #122600}
;;#245.("users_last_updated") = 915757365
;;#245.("help_msg") = "RPG Money Manager helps you keep track of the RPG money you're carrying around and eases access to transfering it to someone else."
;;#245.("feature_verbs") = {"@worth", "@give"}
"#245.("key") => E_PERM (Permission denied)
;;#245.("aliases") = {"RPG Money Manager", "MM"}
;;#245.("description") = "RPG Money Manager helps you keep track of the RPG money you're carrying around and eases access to transfering it to someone else."
;;#245.("object_size") = {11775, 1141287172}

@verb #245:"coin_assets" this none this
@program #245:coin_assets
":coin_assets(who) => returns the new worth in coinage of this.";
if (caller != this)
  return E_PERM;
endif
who = args[1];
worth = 0;
coin_list = this:money_list(who);
for x in [1..length(coin_list)]
  worth = worth + (coin_list[x].quantity * coin_list[x].unit_worth);
endfor
return worth;
.

@verb #245:"@worth" any none none rxd
@program #245:@worth
"@worth [all|coin|me]";
"  Examples:";
"  @worth [me]   => returns the total value (in copper)";
"                   of all coins you carry.";
"                   (no argument defaults to 'me')";
"  @worth silver => returns the total value (in copper)";
"                   of silver coins you carry.";
"  @worth all    => returns a list of the values (in copper)";
"                   of all coins carried by you.";
this:update_usage(verb, player);
who = player;
if (!(caller in {who, this}))
  who:tell("Bugger off. You can't do that!");
  if (caller in connected_players())
    who:tell(caller:titlec(), " just tried to find your worth in coins.");
  endif
  return;
endif
types = $list_utils:map_prop(children(#57000), "denomination");
su = $string_utils;
if ((!dobjstr) || (dobjstr == "me"))
  worth = this:coin_assets(who);
  who:tell(">>Total net worth (in copper): ", worth);
  return;
elseif (dobjstr == "all")
  coin_list = this:money_list(who);
  if (coin_list)
    cum = 0;
    who:tell("You are carrying:");
    for x in [1..length(coin_list)]
      q = coin_list[x].quantity;
      den = coin_list[x].denomination;
      unit = coin_list[x].unit_worth;
      worth = q * unit;
      cum = cum + worth;
      who:tell(su:right(q, 8), " ", su:capitalize(den), " coins (value = ", unit, ") => ", worth, " (in copper).");
    endfor
    who:tell(">>Total net worth => ", cum, " (in copper).");
  else
    who:tell(">You are not carrying any coin.");
  endif
  return;
else
  type = "";
  (i = $string_utils:find_prefix(dobjstr, types)) ? type = types[i] | 0;
  if (!type)
    who:tell("I don't understand that.");
    return;
  elseif (!valid(coin = this:find_money(who, type)))
    who:tell("You don't seem to be carrying any ", dobjstr, " coins");
  else
    worth = coin.quantity * coin.unit_worth;
    who:tell(">Net worth of ", coin.quantity, " ", su:capitalize(type), " coins => ", worth, " (in copper).");
  endif
  return;
endif
who:tell("I don't understand that.");
.

@verb #245:"find_money" this none this
@program #245:find_money
":find_money(OBJ who, STR denomination) => OBJ money_object else if not found.. returns #-1";
if (caller != this)
  return E_PERM;
endif
who = args[1];
coin_list = children(#57000);
for i in [1..length(coin_list)]
  if (coin_list[i].denomination == args[2])
    object = coin_list[i];
  endif
endfor
if (!valid(object))
  return E_INVARG;
else
  for x in (who.contents)
    if ($object_utils:isa(x, object))
      it = x;
      return it;
    endif
  endfor
endif
return $nothing;
.

@verb #245:"money_list" this none this
@program #245:money_list
":money_list(who) => returns LIST of money objs in person's contents.";
"..list is in ascending worth order.";
if (caller != this)
  return E_PERM;
endif
who = args[1];
temp_list = ret_list = coin_list = {};
temp_list = children(#57000);
for x in [1..length(temp_list)]
  if (valid(monobj = this:find_money(who, temp_list[x].denomination)))
    coin_list = listappend(coin_list, {monobj.unit_worth, monobj});
  endif
endfor
coin_list = $list_utils:sort_alist(coin_list);
ret_list = $list_utils:slice(coin_list, 2);
return ret_list;
.

@verb #245:"give_coin" this none this
@program #245:give_coin
":give_coin(OBJ from, OBJ to, NUM amount) =>";
"0 if not done, 1 if done.. it checks if amount necessary";
"is there.. then gives the amount in smallest change units.";
if (caller != this)
  return E_PERM;
endif
{from, to, tender} = args;
len = length(children(#57000));
coin_list = pay_list = {};
coin_list = this:money_list(from);
extra = 0;
for x in [1..length(coin_list)]
  coin = coin_list[x];
  q = coin.quantity;
  unit = coin.unit_worth;
  worth = unit * q;
  div = unit * 10;
  give = 0;
  if ((!(tender > 0)) && (!pay_list))
    "...if there is nothing to give...";
    return;
  elseif ((need = tender % unit) > 0)
    "...if needing to go up to the next coin (ie, no copper and give = 33)...";
    if (!(ok = this:ask_cont(from, unit - need)))
      callers = callers();
      caller = callers[1][2];
      from:tell(">Aborted '", caller, "' Command.");
      return;
    else
      give = 1;
    endif
  endif
  if ((y = tender + (give * unit)) && (y <= worth))
    "...if the smallest coin will do.. give that...";
    give = y / unit;
    pay_list = listappend(pay_list, {coin, give});
    tender = tender - (give * unit);
  elseif ((tender > 0) && (q > 0))
    "...going into the regular routine...";
    "...was there a shortage in a prev coinage amount?..";
    "..Do while len is 1-3, there is money needed and an amount to give..";
    while (((len > 0) && (tender > 0)) && (q > 0))
      "..r is in copper.. this is the amount needed for this level coin..";
      r = tender % div;
      "..if there is enough there.. skips if not.. all the rest.. goes to";
      "..extra question above in next higher coin level..";
      if (worth >= r)
        give = give + (r / unit);
        tender = tender - r;
      endif
      len = len - 1;
      div = div * 10;
      unit = unit * 10;
    endwhile
    "...adds to pay_list..";
    if (give)
      pay_list = listappend(pay_list, {coin, give});
    endif
  endif
endfor
for index in [1..length(pay_list)]
  this:s_i_n();
  coin = pay_list[index][1];
  amount = pay_list[index][2];
  c = coin:messaged_dist(to, from, amount);
endfor
.

@verb #245:"ask_cont" this none this
@program #245:ask_cont
":ask_cont(OBJ who, NUM over) => asks the who if they wanna continue.";
"..cause the amount will given will be over by amount.";
if (caller != this)
  return E_PERM;
endif
{who, over} = args;
who:tell("You do not have the correct change for this transaction.");
who:tell("If you continue, the amount given will be over by ", over, " (value in copper).");
ans = $command_utils:yes_or_no("Continue?");
return ans;
.

@verb #245:"@give @pay" any to any rxd
@program #245:@give
"@give|@pay <NUM amount> to <OBJ|STR what>.";
"   (make sure the amount is in listed as 'worth of copper')";
"   Gives amount TO what in the MOST number of coins possible.";
"   (this is to aid you in keeping your encumbrance as low as possible.)";
"   Example:";
"     You have: 1 gold, 20 silver and 110 copper.";
"     You type: @pay 302 to XYZ";
"               102 copper, and 20 silver coins will be paid to XYZ";
"               leaving you with 1 gold coin and 8 copper coins.";
this:update_usage(verb, player);
usage = "USEAGE: @give|@pay <NUM amount> to <OBJ|STR what>.";
who = player;
if ((!(caller in {who, this})) && (!$local.rpg:trust()))
  who:tell("You attempt to sneak some ", this.denomination, ", but fail miserably.");
elseif ($command_utils:object_match_failed(to = who.location:match_object(iobjstr), iobjstr))
elseif (to.location != who.location)
  who:tell("I see no \"", iobjstr, "\" here.");
elseif (who == to)
  who:tell("You want to give it to yourself?");
elseif (!to:accept(this))
  who:tell(to:titlec(), " ", $gender_utils:get_conj("does/do", to), " not want that item.");
elseif (!dobjstr)
  who:tell(useage);
elseif (!(amt = toint(dobjstr)))
  who:tell(usage);
elseif (amt < 0)
  who:tell("You can't give a negative amount!");
elseif (amt == 0)
  who:tell("You want to give nothing?");
elseif (amt > (worth = this:coin_assets(who)))
  who:tell("You don't have enough money for that.");
else
  this:give_coin(who, to, amt);
endif
.

@verb #245:"s_i_n" this none this
@program #245:s_i_n
"suspends if ticks left is under 7000 or if secs left is under 3";
if (caller != this)
  raise(E_PERM);
endif
ticks = ticks_left();
secs = seconds_left();
if ((ticks < 7000) || (secs < 3))
  suspend(0);
endif
.

"***finished***