/ #mechanics 

Economy: Buying

Most strategy games feature an economic system that produces different resources for the player to spend on improving their circumstances. Those resources would be pointless without interesting things to spend them on…

This post looks at the basic mechanic of buying something: exchanging resources for something else.

Since this post is being written in the context of explaining the mechanics of Heroes of Might and Magic I, it will serve as a good example.

The first thing you are likely to spend these resources on in Heroes of Might and Magic, is building additional buildings in your castle. Pictured below is the dialog for building a Shipyard, which costs gold and wood.

Gold and Wood gets you a shipyard, which can build ships.

The second thing you’ll be spending resources on is buying creatures for your armies:

Buying creatures typically costs gold - occasionally some rare resources for the most powerful creatures.

The scope of what I’ll try to illustrate in the ECS design below, is simply exchanging resources for something else - I won’t focus too much on what is bought, instead just spawning a token component that will be turned into whatever the player bought by some other system. I’ll do two examples:

  • Peasant Hut
    • Cost: 5 Wood
    • Cost: 1000 Gold
  • Peasant
    • Cost: 100 Gold
    • Cost: 1 Peasant resource in the building

ECS Design

Components

Offer

  • type: Class

The type here is type(PeasantToken) or type(PeasantHutToken) or whatever thing is being bought.

Cost

  • amount: Integer
  • type: Class

The amount is the cost paid with the resource of type.

Transaction

  • entity: Integer

This is the command from the player to buy something - resolving it changes the resources in the offer into the resources produced by the offer.

The entity is the entity ID of the player initiating the transaction, their resources will be used to pay costs.

PeasantHutToken

Token that will be transformed into a Peasant Hut by the building system.

PeasantToken

Token that will be transformed into a Peasant unit by the unit system.

Entities

Practically speaking there will need to be some form of hierarchical structure to the world, but I haven’t tried to model that in code yet. For now here’s an idea of how it might look:

  • Castle
    • PeasantHutOffer
      • GoldCost
      • WoodCost
    • Offers for other buildings not included in this example…

Then when the player buys the peasant hut the picture changes:

  • Castle
    • PeasantHut
      • PeasantResource
      • PeasantOffer
      • GoldCost
      • PeasantCost

When the player buys peasants they are added to the army in the castle as new units.

Buying something involves simply adding a Transaction to the entity containing the offer the player is buying.

Systems

TransactionSystem

This system is responsible for exchanging resources for goods tokens when a Transaction is created to indicate that the player bought an offer.

transactions = world.get_entities_with_components(
  Offer,
  Transaction
)

for offering_entity in transactions:
    payer = offering_entity.transaction.entity
    costs = find_costs(offering_entity)
    resources = []

    # Find all resources and check we have enough
    for cost in costs:
      # Try player resources...
      resource = find_resource(cost.type, payer)
      
      # ... else try local resources
      if resource is None:
        resource = find_resource(cost.type, offering_entity)
      
      # Abort: resource not found
      if resource is None:
        world.remove_component(entity, Transaction)
        continue
      
      # Abort: insufficient resources
      if resource.amount < cost.amount:
        world.remove_component(entity, Transaction)
        continue
      
      resources.append(resource)
    
    # Deduct costs
    for i in range(0, len(costs)):
      resources[i].amount -= costs[i].amount

    # Grant the offered item
    offer = entity.offer
    world.add_component(offering_entity, offer.type)

    # End the transaction
    world.remove_component(entity, Transaction)

Notes:

  • The token added above will be picked up by another system that knows how to instantiate the thing you bought.
  • find_costs(entity) finds all costs on the given entity.
  • find_resource(type, entity) finds the resource on the entity with the given type.
  • Some additional complexity is probably needed to handle the case where bought units spawn into a hero’s army.
Author

Matt Van Der Westhuizen

Back-end service developer at Ubisoft Blue Byte by day - wannabe game designer & developer by night.