/ #mechanics 

Turn Based: Unit Priority Order

Turn-based means that players take turns acting instead of all acting at once. Unit priority order means that a player takes a turn for each unit in the game based on the priority of that unit, so a player may have multiple turns over the course of the round. A player may even have multiple uninterrupted turns if they control several units that have higher priority than the opponent’s units.

This is more akin to the turn system found in roleplaying games like Dungeons & Dragons than to traditional turn systems.

In addition to being finer grained (players only act with one unit per turn), this system also tends to be more dynamic, with unit priority shifting a lot. For example, a fast creature might have the highest priority until a Slow spell is cast on it, at which point it drops to the bottom of the priority queue.

Here follows a detailed example from Heroes of Might & Magic (combat).

Player 1 is attacking with the following units:

  • Centaurs (medium)
  • Gryphons (medium)
  • Gargoyles (fast)
  • Minotaurs (medium)

Player 2 is defending with:

  • Archers (slow)
  • Peasants (slow)
  • Pikemen (medium)
  • Knights (fast)

This will result in the following turn order (attacker goes first in the event of ties):

  • P1: Gargoyles
  • P2: Knights
  • P1: Centaurs
  • P1: Gryphons
  • P1: Minotaurs
  • P2: Pikemen
  • P2: Archers
  • P2: Peasants

If the defending player casts Slow on the Gargoyles, they will be moved to the bottom of the queue, but they won’t act again as they already have. In the next round they will act last unless the player dispels Slow, in which case they will act next.

ECS Design

Components

Player

  • name: String
  • color: Color
  • order: Integer

Priority

  • priority: Integer (e.g. 0 fast, 1 medium, 2 slow, etc.)

Entities

Each unit in the game will have a Player component to identify who owns it and a Priority component.

Systems

Unit Priority Turn System

This turn system should be implemented aprroximately as follows (Python pseudo-code, very naive implementation):

units = world.get_entities_with_components(Player, Priority)
priority_queue = PriorityQueue(units, key=priority.priority)

# TODO: Static order was too simplistic - this probably is too... need to rethink this
while len(priority_queue) > 0:
  unit = priority_queue.pop()

  send_event("start_turn", unit)

  play_turn(unit)

  send_event("end_turn", unit)

Notes:

  • This assumes the priority queue will automatically adjust order if Priority.priority changes. Not sure if that would be the case…
  • The events indicate places where other systems may need to do stuff related to turns.
Author

Matt Van Der Westhuizen

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