Trading Game

This post contains just a summary of the fiddling I’ve done in creating a Merchant Trading Game Prototype.

As a matter of fact, the code for this prototype had been lying around for awhile now, I just haven’t had an inkling on how I wished to further develop the game.

Having decided to take a look at the work I’ve already done for it, I made some small modifications to the existing code, namely taking out the portions where the resource parameters were hardcoded and have them be dynamically generated from a JSON file instead.


The source code for the project can be found here.


The basic idea of the game was to have many markets, and we as players act the role of merchants, buying cheap at one market and selling dear at another. I had the idea of creating such a game a long time back after watching the Anime Spice & Wolf, and the idea has just been stuck on me since then, resurfacing time & again about how fun such a game might seem.

Of course, I never got around to creating a full-blown game, due to a lack of ideas, but I hope that this post may ultimately pique the interest of anyone who reads it.

The code I’ve written is fairly straightforward, although I’ve tried, unsuccessfully, to incorporate some elements of economics into the pricing of the resources.



The idea was that the baseline price of a resource can be established by knowing what is its baseline quantity. These are represented by P1 and Q1 on the chart above respectively. 

D stands for the demand curve, which is the price and quantity consumers are willing and able to pay for a resource at the specific point in time, and S is the supply curve, similar but representing the suppliers side of the story.

Trying to keep things simple, I utilized just the gradient of the demand curve to calculate how much a change in quantity would affect the price. That resulted in the following code.


Of course, I didn’t initially had the above class to begin with. It was made when I wanted to store resource information in a JSON file and convert them into an instance object.

I used Newtonsoft.Json for the JSON deserialization, faced some issues there as well, so I’ll add the resolution link here in case others have the same issue. It was simply to use an older dll version of Newtonsoft.Json.


The JSON file looked something like this:


The core of the pricing concept is based on an abstract Curve class.

using System;

/// <summary>
/// Contains basic parameters that can be used to calculate the price of a resource
/// Uses a default straight line curve to calculate prices, should be allowed to be overridden by child classes
/// </summary>
public abstract class Curve
{
	protected float y_displacement;
    public float x_displacement;

    public float gradientConstant;

    /// <value>Reference Y value used for calculating y displacement</value>
    public float equilibrium_y;
    /// <value>Reference X value used for calculating y displacement</value>
    public float equilibrium_x;

    public Curve(float gradientConstant, float x_displacement, float equilibrium_y, float equilibrium_x)
    {
        this.gradientConstant = gradientConstant;
        this.x_displacement = x_displacement;
        this.equilibrium_y = equilibrium_y;
        this.equilibrium_x = equilibrium_x;
    }

	public abstract float calculateY(int x);

    protected abstract void InitializeYDisplacement();
    public float GetYDisplacement()
    {
        return y_displacement;
    }

	public abstract float GetGradient ();
	public abstract float calculateAreaUnderCurve (int initialX, int finalX);

    public static Curve createCurveByName(string curveName, float gradientConstant, float x_displacement, float equilibrium_y, float equilibrium_x)
    {
        return (Curve)Activator.CreateInstance(Type.GetType(curveName), gradientConstant, x_displacement, equilibrium_y, equilibrium_x);
    }
}


By taking in the parameters stated in the JSON file, we are able to populate subclasses of the Curve class to calculate the price of a particular resource, like so:

using System;

/// <summary>
/// Gradient Constant should always be negative
/// </summary>

public class StraightCurve : Curve 
{
	public StraightCurve (float gradientConstant, float x_displacement, float equilibrium_y, float equilibrium_x) : base (gradientConstant, x_displacement, equilibrium_y, equilibrium_x) {
        InitializeYDisplacement();
    }
		
	public override float calculateY(int x){
		return (gradientConstant * x + y_displacement);
	}

	protected override void InitializeYDisplacement(){
		y_displacement = equilibrium_y - gradientConstant * equilibrium_x;
	}

	public override float GetGradient(){
		return gradientConstant;
	}

	public override float calculateAreaUnderCurve(int initialX, int finalX){	
		return (float)((gradientConstant * Math.Pow (initialX, 2) / 2 + y_displacement * initialX) - (gradientConstant * Math.Pow (finalX, 2) / 2 + y_displacement * finalX));
	}

}


Different resources can specify the extent to which a change in quantity would affect its price, either by using a different gradient/price_elasticity or a different Curve object. 

using System;

public abstract class Resources : Subject<int>
{
	public abstract Curve demand { get; protected set; }

    public float equilibrium_price { protected set; get; }
    public float equilibrium_qty { protected set; get; }

    public float price_elasticity { protected set; get; }
    public float demand_shift { protected set; get; }
    public float price_shift { protected set; get; }

    public Resources(float initialAmount, float equilibrium_price, float equilibrium_qty, float price_elasticity, float demand_shift, float price_shift)
	{
		state = (int)initialAmount;
        this.equilibrium_price = equilibrium_price;
        this.equilibrium_qty = equilibrium_qty;
        this.price_elasticity = price_elasticity;
        this.demand_shift = demand_shift;
        this.price_shift = price_shift;
	}

    public bool DecreaseQuantity(int amount)
    {
        if (state - amount >= 0)
        {
            setState(state - amount);
            return true;
        }
        return false;
    }

    public bool IncreaseQuantity(int amount)
    {
        setState(state + amount);
        return true;
    }

    public abstract float calculatePrice();
    public abstract float calculateTotalPrice(int quantity);


    /// <summary>
    /// private method that allows the Market class to create new resources
    /// </summary>
    /// <param name="resourceName">Class name of the resource instance/object to create</param>
    /// <param name="initialValues[0]">Initial amount of this resource to create for this market when the game begins</param>
    /// <param name="initialValues[1]">Equilibrium quantity of the resource, we may wish to shift this parameter to be handled by the subclass resource though</param>
    /// <param name="initialValues[3]">Price Elasticity of the Resource</param>
    /// <param name="initialValues[4]">Demand Shift to use, this is normally set to 0</param>
    /// <param name="initialValues[5]">Price Shift to use, this is normally set to 0</param>

    /// <returns>The subclass resource object</returns>
    public static Resources createNewResourceByName(string resourceName, params float[] initialValues)
    {
        if (initialValues.Length < 6)
            throw new Exception("Unable to create new Resource object, Argument passed to initialValues parameter is not correct");

        return (Resources)Activator.CreateInstance(Type.GetType(resourceName), initialValues);
    }

}


This is the jist of what I’ve done up so far. I’ve been thinking about other ideas, such as shifting the entire price and quantity calculation onto a separate server for co-op play, but that would be way beyond just pur Unity Game Development, and I’m not sure how much fun that would be to work on anyway.


  • From just looking at the code, you can see that if you wished to add a new resource, you would just need to extend the json object in the <marketName>_resource.json file with the appropriate parameters, and also add in a Resource Subclass corresponding to that new resource you wish to add.

  • Adding a new Market is as simple as creating a new Prefab which contains the Market script, and giving it a unique name that is not shared by the already existing markets.

  • I hope this post helps anyone who has the idea of creating a merchant trading game, even if it’s just to provide some inspiration.

    It might be interesting as well to implement concepts such as Cross Elasticity of Demand into such a game, and if I ever begin working on it, I’ll be sure to post it here.

    I’ve been wanting to write some new posts not just on games in general, but also about design patterns and Asset Store tools that may seem useful in developing a game, but we’ll see how that goes.

Author: simplygamedev

Leave a Reply

Your email address will not be published. Required fields are marked *