0
\$\begingroup\$

I am new at game development and am now facing the problem for a market price algorithm in a turn based game. What I try to achieve:

  • the market starts with fixed bidding and asking prices for one piece of goods. To keep it simple the minimum value is 1, the maximum 20
  • if the user buys/sells the same goods in too large quantities in a certain amount of turns, the prices should rise/drop; simple supply and demand logic. The maximum amount of a goods per transaction is 100
  • if the user doesn't trade that good for a few turns, it should adjust the price in the other direction
  • there are certain type of goods that can be "easily" produced by the player and are thus sold and some that are harder to get by and are usually bought.
  • the market can sell each good infinitely and would also buy everything, so it has no stock to take into account.

What I tried and didn't work:

  • if the accumulated quantity of bought/sold good reaches 500 (I use negative values for buying) the price rises or drops by 1 respectively
  • to factor the turns into it, I thought I just reduce the accumulated value by 10 each turn and then adjust the price if it reaches 0 again. This has one big flaw, as you can easily cheat by just selling a small amount, wait a few turns and the price will rise; repeat until the price reaches the maximum of 20.

Any simple ideas on how to fix this?

ps. I hope this is an appropriate question to ask here

\$\endgroup\$
9
  • \$\begingroup\$ This is entirely a conversational comment. I made a stock trading board game that worked really well. The markets did just what they should. Players had cards for insider trading info. People who played it said it worked! But... it wasn't really fun, and I agreed it wasn't fun. I sincerely hope you have more luck than I did; it's a great concept for a board game! :) \$\endgroup\$
    – Almo
    Oct 27, 2020 at 20:54
  • \$\begingroup\$ If this is the game, then you'd probably just need to spend a whole bunch of time trying different things and tweaking the results until you get something fun. If this is only a part of the game, then I'd probably suggest simplifying this detail out of the game (by e.g. having fixed prices or preventing you from reselling items) until you have an otherwise functional game and then resort back to trying a bunch of different things if you feel the game needs something like this. \$\endgroup\$ Oct 27, 2020 at 21:29
  • \$\begingroup\$ Are there multiple players in this game? If so, have you considered having the market just change based on their actions rather than also by itself? If it's just a single player game, there might be a risk that it's fairly easy to find the optimal strategy if the market only changes in a deterministic way based on the player's actions. (Random market movement might help with that, if it's indeed a problem) \$\endgroup\$ Oct 27, 2020 at 21:40
  • \$\begingroup\$ @BernhardBarker It is a single player game and the market is currently the only way to get money for the player. He can then spend this money to get additional units. There are other things I'm planning to add but I'd like to have some basic mechanic for the market beforehand. \$\endgroup\$
    – Thomas
    Oct 27, 2020 at 21:48
  • \$\begingroup\$ "you can easily cheat by just selling a small amount, wait a few turns and the price will rise" - is this actually a problem? Allowing players to spend or hold resources to give them more resources later is not that uncommon in games. This becomes a trade-off between spending the resources now to make yourself a bit stronger to face the immediate challenges or waiting and making yourself a lot stronger for later challenges. \$\endgroup\$ Oct 27, 2020 at 21:56

1 Answer 1

0
\$\begingroup\$

Although I am not entirely sure what you are looking for I think your basic solution is okay, but probably needs to be a bit more refined to avoid issues of suspected "cheating". I hate to post an answer without more information on exactly what you want, a naive solution like mine below might help. The system uses a linear remapping function so it's not the most exciting implementation, but should be able to handle basic pricing. You might need something a bit more robust if you want deal with players trying to flood the market while prices are high (for example if someone is selling 5 items when the price is $20, you may want to pay the entire $100, but if they are selling 500, you may want to settle for paying $5 per item or $2,500 total rather than $10,000).

namespace Thomas.Game
{
    public class Item
    {
        public float popularity = 1.0f; // use if item is currently trending
        private int supply;
        private int minDemand;
        private int maxDemand;
        private int minPrice;
        private int maxPrice;
        private int minSupply; // should be 0 but can be higher if this should be held on to.
        private int maxSupply;
        private float buyBackAdjustment;
        private bool isSupplyUnlimited;

        Item(int initialSupply, int minSupply, int maxSupply, bool isSupplyUnlimited, int minDemand, int maxDemand, int minPrice, int maxPrice, float buyBackAdjustment)
        {
            this.supply = initialSupply;
            this.minSupply = minSupply;
            this.maxSupply = maxSupply;
            this.isSupplyUnlimited = isSupplyUnlimited;
            this.minDemand = minDemand;
            this.maxDemand = maxDemand;
            this.minPrice = minPrice;
            this.maxPrice = maxPrice;
            this.buyBackAdjustment = buyBackAdjustment;
        }

        public void Consume()
        {
            supply -= popularity * Random.Range(minDemand, maxDemand);
        
            if (supply < 0)
            {
                supply = 0;
            }
        }

        public bool CanSell(int amount)
        {
            return isSupplyUnlimited || (supply - amount) >= minSupply;
        }

        public void Sell(int amount)
        {
            supply -= amount;
            
            if (supply < 0)
            {
                supply = 0;
            }
        }

        public void Buy(int amount)
        {
            supply += amount;

            if (supply < 0)
            {
                supply = 0;
            }
        }

        public int GetSalePrice()
        {
            return (int)supply.RemapClamped(minSupply, maxSupply, maxPrice, minPrice);
        }

        public int GetBuyPrice()
        {
            return (int)(buyBackAdjustment * GetSalePrice());
        }
    }
}

namespace Thomas.Utility
{
    public static class FloatExtensions
    {
        public static float Remap(this float value, float from1, float to1, float from2, float to2)
        {
            return (value - from1) / (to1 - from1) * (to2 - from2) + from2;
        }

        public static float RemapClamped(this float value, float from1, float to1, float from2, float to2)
        {
            return Mathf.Clamp(value.Remap(from1, to1, from2, to2), from2, to2);
        }
    }
}
    
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged .