ID:2379252
 
(See the best response by Lummox JR.)
Code:
mob/var
list/moneyex = list()
converting=0
confrom= 0
conto = 0



mob/verb
Ex_money()
set name = "curency exchange"
if(!usr.converting)
usr.converting = 1
if(usr.Orch)
moneyex.Add("Orch")
if(usr.Dram)
moneyex.Add("Dram")
if(usr.Elo)
moneyex.Add("Elo")
if(usr.Lygh)
moneyex.Add("Lygh")
if(usr.Jing)
moneyex.Add("Jing")
if(usr.Raan)
moneyex.Add("Ra'an")
if(!moneyex)
_message(usr,"You have no money!")
return
if(moneyex)
switch(input(src,"What are you echanging from?","Currency Type") in moneyex)
if("Orch")
switch(input(src,"What are you echanging to?","Currency Type") in list("Dram","Elo","Lygh","Jing","Ra'an"))
if("Dram")
usr.confrom = input("Enter an amount to exchange:","Orch to Dram",usr.confrom) as num
if(usr.confrom>usr.Orch||usr.confrom<1)
moneyex.Remove("Orch")
moneyex.Remove("Dram")
moneyex.Remove("Elo")
moneyex.Remove("Lygh")
moneyex.Remove("Jing")
moneyex.Remove("Ra'an")
alert(usr,"You dont have enough for this transaction")
usr.converting = 0
return
usr.Orch-=usr.confrom
usr.confrom = usr.confrom*10
usr.Dram += usr.confrom/4
usr.Dram = round(usr.Dram,1)
moneyex.Remove("Orch")
moneyex.Remove("Dram")
moneyex.Remove("Elo")
moneyex.Remove("Lygh")
moneyex.Remove("Jing")
moneyex.Remove("Ra'an")
usr.converting = 0
if("Elo")
usr.confrom = input("Enter an amount to exchange:","Orch to Elo",usr.confrom) as num
if(usr.confrom>usr.Orch||usr.confrom<1)
moneyex.Remove("Orch")
moneyex.Remove("Dram")
moneyex.Remove("Elo")
moneyex.Remove("Lygh")
moneyex.Remove("Jing")
moneyex.Remove("Ra'an")
alert(usr,"You dont have enough for this transaction")
usr.converting = 0
return
usr.Orch-=usr.confrom
usr.confrom = usr.confrom*10
usr.Elo += usr.confrom/4
usr.Elo = round(usr.Elo,1)
moneyex.Remove("Orch")
moneyex.Remove("Dram")
moneyex.Remove("Elo")
moneyex.Remove("Lygh")
moneyex.Remove("Jing")
moneyex.Remove("Ra'an")
usr.converting = 0
if("Lygh")
usr.confrom = input("Enter an amount to exchange:","Orch to Lygh",usr.confrom) as num
if(usr.confrom>usr.Orch||usr.confrom<1)
moneyex.Remove("Orch")
moneyex.Remove("Dram")
moneyex.Remove("Elo")
moneyex.Remove("Lygh")
moneyex.Remove("Jing")
moneyex.Remove("Ra'an")
alert(usr,"You dont have enough for this transaction")
usr.converting = 0
return
usr.Orch-=usr.confrom
usr.confrom = usr.confrom*10
usr.Lygh += usr.confrom/3
usr.Lygh = round(usr.Lygh,1)
moneyex.Remove("Orch")
moneyex.Remove("Dram")
moneyex.Remove("Elo")
moneyex.Remove("Lygh")
moneyex.Remove("Jing")
moneyex.Remove("Ra'an")
usr.converting = 0
return
if("Jing")
usr.confrom = input("Enter an amount to exchange:","Orch to Jing",usr.confrom) as num
if(usr.confrom>usr.Orch||usr.confrom<1)
moneyex.Remove("Orch")
moneyex.Remove("Dram")
moneyex.Remove("Elo")
moneyex.Remove("Lygh")
moneyex.Remove("Jing")
moneyex.Remove("Ra'an")
alert(usr,"You dont have enough for this transaction")
usr.converting = 0
return
usr.Orch-=usr.confrom
usr.confrom = usr.confrom*10
usr.Jing += usr.confrom/2
usr.Jing = round(usr.Jing,1)
moneyex.Remove("Orch")
moneyex.Remove("Dram")
moneyex.Remove("Elo")
moneyex.Remove("Lygh")
moneyex.Remove("Jing")
moneyex.Remove("Ra'an")
usr.converting = 0
return
if("Ra'an")
usr.confrom = input("Enter an amount to exchange:","Orch to Raan",usr.confrom) as num
if(usr.confrom>usr.Orch||usr.confrom<1)
moneyex.Remove("Orch")
moneyex.Remove("Dram")
moneyex.Remove("Elo")
moneyex.Remove("Lygh")
moneyex.Remove("Jing")
moneyex.Remove("Ra'an")
alert(usr,"You dont have enough for this transaction")
usr.converting = 0
return
usr.Orch-=usr.confrom
usr.confrom = usr.confrom*10
usr.Raan += usr.confrom/3
usr.Raan = round(usr.Raan,1)
moneyex.Remove("Orch")
moneyex.Remove("Dram")
moneyex.Remove("Elo")
moneyex.Remove("Lygh")
moneyex.Remove("Jing")
moneyex.Remove("Ra'an")
usr.converting = 0
return


Problem description: In my game there are 6 currencies, there HAS to be a better way than this! This is just the code to convert 1 currency, is there a better way or do I just have to suffer?

Instead of having Orch, Dram, Elo etc vars, you should just have a single list of all money like list("Orch" = 0, "Dram" = 0, "Elo" = 0).
I purposefully did that so the currency wouldn't show in the list if the player didn't have any of it. But I meant the conversion process. Is there a simpler way to do it?
Best response
Generally speaking, the easiest way to do currency conversion will be to use a global list that gives each currency a value relative to some global constant (such as 1, or 100). You could even change this list over time to cause fluctuations in the currency.

// lower values mean currency is worth less; higher is worth more
var/list/exchange_rates = list(\
"Orch" = 92,
"Dram" = 34,
"Elo" = 161,
"Lygh" = 107,
"Jing" = 73,
"Ra'an" = 124)

Now you need a proc to calculate how much of X is worth how much of Y. To make things simpler let's assume that you always get a non-decimal amount of currency in the exchange, and it rounds down--which will avoid gaming the system. (You could also add a fee for the money exchange process, so the rate of exchange takes, say, a 2% hit in either direction.)

proc/ExchangeValue(n, cur_from, cur_to)
n *= exchange_rates[cur_from] / exchange_rates[cur_to]
return round(n) // round down

So looking at the math, if your "from" currency is worth more than the "to", n is being multiplied by more than 1 and will increase. If it's worth less, n will decrease.

Now let's put that in a simple verb. Mind you a nice UI would be better, but we can start here.

mob/verb/Exchange_Money()
var/amount_from, amount_to
var/cur_from, cur_to

var/list/choice = new
// Fill the list of "from" choices
for(var/v in exchange_rates)
var/vname = ckeyEx(v) // change Ra'an to Raan
if((vars[vname]||0) > 0) choice["[v]: [vars[vname]]"] = v

cur_from = input("Which currency would you like to exchange for another?", "Exchange") as null|anything in choice
if(!cur_from) return // cancel
cur_from = choice[cur_from] // convert from nice formatted text to just the name

amount_from = input("How much [cur_from] would you like to exchange?", "Exchange") as num
// sanity checek: round money down, and no more than we have
amount_from = min(vars[ckeyEx(cur_from)], round(amount_from))
if(amount_from <= 0) return // cancel

// Fill the list of "to" choices
choice.Cut()
for(var/v in exchange_rates)
if(v == cur_from) continue
var/money = ExchangeValue(amount_from, cur_from, v)
if(money > 0) choice["[money] [v]"] = v
if(!choice.len)
usr << "[amount_from] [cur_from] won't buy you anything."
return

cur_to = input("Which currency would you like to receive in exchange for [amount_from] [cur_from]?", "Exchange") as null|anything in choice
if(!cur_to) return // cancel
cur_to = choice[cur_to] // convert from nice formatted text to just the name

// complete the transaction
amount_to = ExchangeValue(amount_from, cur_from, cur_to)
vars[ckeyEx(cur_from)] -= amount_from
vars[ckeyEx(cur_to)] += amount_to

usr << "You exchanged [amount_from] [cur_from] for [amount_to] [cur_to]."

This can be refined with a better UI than just using input() boxes, but it should give you a general idea of how to go about the exchange.

Other possible refinements include:

- Different banks might have different exchange rates, but be too far apart in the world to make gaming the system practical.
- Only so much money may be in circulation, and a bank may not have very much of a high-value currency OR a currency from a far-flung country (unless said country is politically influential). Therefore the amount you're allowed to exchange may be limited by how much of the target currency the bank has on hand, which would need a separate calculation that looks like the inverse of ExchangeValue().
- Changing money usually incurs a small fee, which occurs in the form of a reduced exchange rate. This too would reduce gaming the system if different banks had different rates.
Thanks a lot!