Money exchange program for BatMUD


0. Contents

   1. Purpose
   2. BatMUD coins and relative values
   3. Examples
      3.1. Being rich
         3.1.1. Being penny-wise
         3.1.2. Being generous
      3.2. Being poor
         3.2.1. Being too poor
         3.2.2. Having unsuitable coins
   4. Algorithm used
      4.1. Step 1: Pay with the smallest
      4.2. Step 2: Initiate exchange
      4.3. Step 3: Peel it
   5. Copying
   6. Requirements
   7. Downloading

1. Purpose

I do not have access to the BatMUD shopkeeper money exchange algorithm file, so I wrote my own.

Shortly:
If you want to pay a sum of cash and you have a various collection of coins, you can use this program to calculate what coins should you give. It creates a list of commands for giving the coins away. You can either give the smallest coins or the biggest coins you have.

It even handles the cases when you don't have enough money (no it does not walk to Bank), or you have no suitable coins.

2. BatMUD coins and relative values

mithril=500, batium=100, anipium=50, platinum=10, gold=1, silver=0.6, bronze=0.4, copper=0.2, tin=0.1, zinc=0.05, mowgles=0.01

3. Examples

Here are some examples of running this program.

3.1. Being rich

You are carrying 20.0 kg of equipment:
4049 coins (402 mithril, 91 batium, 69 anipium, 53 platinum, 1155 gold, 267
 silver, 106 bronze, 133 copper, 212 tin, 361 zinc and 1200 mowgles) [Cash:
 21555  Bank: 1  Total: 215516]

And you want to pay Bisqwit 3134.39 gold from what you're carrying.

3.1.1. Being penny-wise

Fine. You do this:
./batmoney bisqwit 3134.39
and the you copypaste your money possessions to the program. The program calculates what you should do:

*** Now paste your inventory here (the lines saying what coins do you have):
*** Thank you
*** Inv at start: 402 mithril, 91 batium, 69 anipium, 53 platinum, 1155 gold,
  267 silver, 106 bronze, 133 copper, 212 tin, 361 zinc, 1200 mowgles, that is 215515.45...
*** first: gave 1200 mowgles... so I've 3122.39 left to pay.
*** first: gave 361 zinc... so I've 3104.34 left to pay.
*** first: gave 212 tin... so I've 3083.14 left to pay.
*** first: gave 133 copper... so I've 3056.54 left to pay.
*** first: gave 106 bronze... so I've 3014.14 left to pay.
*** first: gave 267 silver... so I've 2853.94 left to pay.
*** first: gave 1155 gold... so I've 1698.94 left to pay.
*** first: gave 53 platinum... so I've 1168.94 left to pay.
*** first: gave 23 anipium... so I've 18.94 left to pay.
*** Inv now: 402 mithril, 91 batium, 46 anipium, that is 212400.00...
*** Have gave: 23 anipium, 53 platinum, 1155 gold, 267 silver, 106 bronze,
  133 copper, 212 tin, 361 zinc, 1200 mowgles, that is
3115.45...
*** exchange: gave 1 anipium (50.00), now I want 31.06 back...
*** exchange: took back 3 platinum (30.00)...
*** exchange: took back 1 gold (1.00)...
*** exchange: took back 1 zinc (0.05)...
*** exchange: took back 1 mowgles (0.01)...
-----------
*** Inv now: 402 mithril, 91 batium, 45 anipium, 3 platinum, 1 gold, 1 zinc,
  1 mowgles, that is 212381.06...
*** Have gave: 24 anipium, 50 platinum, 1154 gold, 267 silver, 106 bronze,
  133 copper, 212 tin, 360 zinc, 1199 mowgles, that is
3134.39...
-----------
give 24 anipium to bisqwit
give 50 platinum to bisqwit
give 1154 gold to bisqwit
give 267 silver to bisqwit
give 106 bronze to bisqwit
give 133 copper to bisqwit
give 212 tin to bisqwit
give 360 zinc to bisqwit
give 1199 mowgles to bisqwit
emote calculates: Paid 24 anipium, 50 platinum, 1154 gold, 267 silver, 106 bronze,
  133 copper, 212 tin, 360 zinc and 1199 mowgles, totalling worth of 3134.39.
-----------

3.1.2. Being generous

Though... if you are really generous, you can instead pay with the most valuable coins you have:
./batmoney -b bisqwit 3134.39
causing this output:

*** Now paste your inventory here (the lines saying what coins do you have):
*** Thank you
*** Inv at start: 402 mithril, 91 batium, 69 anipium, 53 platinum, 1155 gold, 267
  silver, 106 bronze, 133 copper, 212 tin, 361 zinc, 1200 mowgles, that is 215515.45...
*** first: gave 6 mithril... so I've 134.39 left to pay.
*** first: gave 1 batium... so I've 34.39 left to pay.
*** first: gave 3 platinum... so I've 4.39 left to pay.
*** first: gave 4 gold... so I've 0.39 left to pay.
*** first: gave 1 copper... so I've 0.19 left to pay.
*** first: gave 1 tin... so I've 0.09 left to pay.
*** first: gave 1 zinc... so I've 0.04 left to pay.
*** first: gave 4 mowgles... so I've 0.00 left to pay.
-----------
*** Inv now: 396 mithril, 90 batium, 69 anipium, 50 platinum, 1151 gold,
  267 silver, 106 bronze, 132 copper, 211 tin, 360 zinc,
1196 mowgles, that is 212381.06...
*** Have gave: 6 mithril, 1 batium, 3 platinum, 4 gold, 1 copper, 1 tin,
  1 zinc, 4 mowgles, that is 3134.39...
-----------
give 6 mithril to bisqwit
give 1 batium to bisqwit
give 3 platinum to bisqwit
give 4 gold to bisqwit
give 1 copper to bisqwit
give 1 tin to bisqwit
give 1 zinc to bisqwit
give 4 mowgles to bisqwit
emote calculates: Paid 6 mithril, 1 batium, 3 platinum, 4 gold, 1 copper,
  1 tin, 1 zinc and 4 mowgles, totalling worth of 3134.39.
-----------

3.2. Being poor

You are carrying 73.1 kg of equipment:
1425 coins (1155 gold, 267 silver and 3 mowgles) [Cash: 1315  Bank: 0
 Total: 1315]

3.2.1. Being too poor

You want to pay Bisqwit 3134.39 gold from what you're carrying.
Well, you obviously don't have that much:
*** Now paste your inventory here (the lines saying what coins do you have):
1425 coins (1155 gold, 267 silver and 3 mowgles) [Cash: 1315  Bank: 0
*** Thank you
*** Inv at start: 1155 gold, 267 silver, 3 mowgles, that is 1315.23...
*** first: gave 3 mowgles... so I've 3134.36 left to pay.
*** first: gave 267 silver... so I've 2974.16 left to pay.
*** first: gave 1155 gold... so I've 1819.16 left to pay.
*** Inv now: that is 0.00...
*** Have gave: 1155 gold, 267 silver, 3 mowgles, that is 1315.23...
say [batmoney] I don't have enough money to pay with.

3.2.2. Having unsuitable coins

You want to drop 134.39 gold.
./batmoney  134.39
Result:

*** Now paste your inventory here (the lines saying what coins do you have):
1425 coins (1155 gold, 267 silver and 3 mowgles) [Cash: 1315  Bank: 0
*** Thank you
*** Inv at start: 1155 gold, 267 silver, 3 mowgles, that is 1315.23...
*** first: gave 3 mowgles... so I've 134.36 left to pay.
*** first: gave 223 silver... so I've 0.56 left to pay.
*** Inv now: 1155 gold, 44 silver, that is 1181.40...
*** Have gave: 223 silver, 3 mowgles, that is 133.83...
*** exchange: gave 5 silver (3.00), now I want 2.44 back...
*** exchange: gave 10 gold more (10.00), now I want 12.44 back...
*** exchange: didn't help... getting cash back.
*** last: took 10 gold... I still need to reget 2.44.
*** last: took 4 silver... I still need to reget 0.04.
*** last: took 3 mowgles... I still need to reget 0.01.
-----------
*** Inv now: 1155 gold, 43 silver, 3 mowgles, that is 1180.83...
*** Have gave: 224 silver, that is 134.40...
-----------
drop 224 silver
emote calculates: Dropped 224 silver, totalling worth of 134.40.
say [batmoney] I ran out of small coins, I want 0.01 back.
-----------

4. Algorithm used

The algorithm behind this program (the smallest coins method) was surprisingly difficult to develope. I'll try to describe it here.

Imagine you have "coins (1 silver, 1 tin, 12 zinc)" and you have to pay 0.8 gold.

4.1. Step 1: Pay with the smallest

Start with the smallest coins in the inventory.

For Coinset = smallest to biggest:
  Giveamount = Debt.value / Coinset.value
  Give max(Coinset.possesscount, Giveamount) coins of Coinset type.

So, we do:

  • pay 12 zinc, as it lessens the debt with 0.05 * 12 = 0.60, remaining = 0.20
  • pay 1 tin, as it lessens the debt with 0.10 * 1 = 0.10, remaining = 0.10

4.2. Step 2: Initiate exchange

If you're out of coins now, there are three possibilities:
  • If the pay is even, you were robbed penniless.
  • If you've paid too much, you don't have suitable coins and you must negotiate exchange.
  • If you've paid too little, you don't have enough money.
If Step 1 didn't this time make the pay even, we must give bigger coins.

For Coinset = smallest to biggest:
  If Coinset.value > Debt.value Then
    Give 1 coins of Coinset type
    Exit for-loop.

In this example case, we pay 1 silver, as it is the smallest coin we can use to lessen the debt. This pays 0.60, making our debt now be -0.50.

4.3. Step 3: Peel it

After step 2, we have paid too much. You must get coins back. This is what is the hardest part of the algorithm. If you swap the customer and the seller now and try with Step 1, you'll end up in an infinite loop. So my solution was to use brute force. Test through all the possibilities of getting coins back from the customer, starting from the biggest coins, seeing which one of the combinations results to even pay. If none of them works, you must jump to Step 2 and pay more coins.
In this example case, the brute force reveals that getting back 1 tin (0.10) and 8 zinc (0.40) makes the pay even, and we're done.

If you have any idea how to do this without brute force, I encourage you to contact me and tell me.

5. Copying

batmoney has been written by Joel Yliluoma, a.k.a. Bisqwit,
and is distributed under the following terms:
* No warranty. You are free to modify this source and to
* distribute the modified sources, as long as you keep the
* existing copyright messages intact and as long as you
* remember to add your own copyright markings.
* You are not allowed to distribute the program or modified versions
* of the program without including the source code (or a reference to
* the publicly available source) and this notice with it.

6. Requirements

GNU make is probably required.

7. Downloading

Downloading help

  • Do not download everything - you only need one file (newest version for your platform)!
  • Do not use download accelerators or you will be banned from this server before your download is complete!

Date (Y-md-Hi) acc        Size Name                
2003-0530-0300 r--       14700 batmoney-2.01.3.tar.bz2
2003-0530-0300 r--        2728 patch-batmoney-2.01.2-2.01.3.bz2
2002-1216-1959 r--       14630 batmoney-2.01.2.tar.bz2
2002-1216-1959 r--       12248 patch-batmoney-2.01.1-2.01.2.bz2
2002-1216-1957 r--          14 patch-batmoney-2.1.1-2.1.2.bz2
2002-0501-2249 r--       10750 batmoney-2.01.1.tar.bz2
2002-0501-2249 r--        3449 patch-batmoney-2.01-2.01.1.bz2
2002-0209-2333 r--       10224 batmoney-2.01.rar
2002-0209-2334 r--       10507 batmoney-2.01.tar.bz2
2002-0209-2333 r--        7350 patch-batmoney-2.00-2.01.bz2
2001-0202-2222 r--        5108 batmoney-2.00.rar
2001-0202-2222 r--        5101 batmoney-2.00.tar.bz2
2001-0202-2222 r--        5632 batmoney-2.00.zip
2001-0202-2222 r--        5632 patch-batmoney-1.99-2.00.bz2
2001-0202-2147 r--        4625 batmoney-1.99.rar
2001-0202-2147 r--        4618 batmoney-1.99.tar.bz2
2001-0202-2147 r--        4947 batmoney-1.99.zip
Back to the source directory index at Bisqwit's homepage