How to Design the Data Structure for a Turn Based Game

how-design-data-structure-for-turn-based-game

One of the recurring questions you ask our support team is how to actually make a turn based game in Gamedonia.

Because you’re already great coding features for your games, all you may need is a little guidance on how to organize your design to make the things you want work.

When you see the following example, you’ll see how easy it is.

 

Stuff needed to build a turn-based game

To keep things simple, let’s say you want to build a classic tic-tac-toe game with Gamedonia. What features should you expect from a game like this?

  • Multiple simultaneous games. Players should be able to have multiple games with different opponents taking place at the same time.
  • Different game status. Every game should have a status that indicates what to expect. Waiting, created, running, finished or cancelled.
  • Play with listed friends. You could have the option to challenge your friends to a game or add new friends to the list.
  • Play with random users. You may want to play with people you don’t know.
  • Play same skill users. You might want to play against random players that have a similar skill than you do.

Making a game with Gamedonia that has all these features is easy.

All you need to know is how to lay out the features to make them work like you want.

Here are a few questions you should be able to answer.

 

#1 How are you going to store data?

In Gamedonia, game data is stored in collections, which is like a table in an SQL database.

There are some differences though. In a collection you store objects with a similar concept, but they don’t need to have the same number of “columns”. In fact, in a collection, objects have attributes instead of columns.

  • How many collections does the tic-tac-toe game need?
  • What information should we store in every object?
  • How does every process work inside the game?

To know these, first we have to determine the data structure of a game (match).

 

Designing the game structure

Our “games” will be objects stored inside a collection we can name GAMES.

Every “game” object has these features:

  • It is shared by two (or more) players
  • Allows players to make moves only on their turns
  • It has a winning condition
  • It has a winner
  • All players in it can update the “game” object

We’ll store all these features in GAMES collection, which must be readable and writeable by any player so they can work.

data-structure-for-turn-based-game

 

#2 How will the game structure look like?

Obviously it will depend on the kind of game you’d like to make, but in the tic-tac-toe example we’re doing you’ll need:

  • Users. Players involved in each game.
  • Status. Whether it is a waiting, created, running, finished or cancelled “game”.
  • Current turn. In tic-tac-toe, there will be a maximum of six turns between both players.
  • Current user. Which player has the active turn and can make a move.
  • Movements. List every move, which must be ordered by turn and has to contain the information about:
    • User who made the move
    • Position occupied on the board {x,y} when the move is made

game-structure-for-turn-based-game

Most games will have a more elaborate board than we’re dealing with in this example, so you’ll need a complex matrix of coordinates, and so on. But for this example, the board can be represented by a simple array of positions.

Let’s see our board of coordinates so we can represent movements in the “game”.

0,2 1,2 2,2
0,1 1,1 2,1
0,0 1,0 2,0

The format of the objects in Gamedonia is JSON, so every “game” will have this structure:

 

{

  'users':{

    // ‘user1’: gamedonia_id_of_user1

    '1': 55448343d3655,

    '2': 33129821c1233

  },

  'status': 'running',

  'currentturn': 3,

  'currentuser': '1',

  'movements': {

    '1': {‘user’: 55448343d3655, ‘position’:[0,0]},

    '2': {‘user’: 33129821c1233, ‘position’:[0,1]}

  },

}

 

#3 How will you manage the users?

Regardless of the method any user starts a session with (email, Facebook, silent) he or she will always have a profile in Gamedonia. Every user is automatically assigned a unique user id in the Gamedonia profile, where you can store any additional info you need.

Important notice. This profile is public for every other user that asks for it.

There is no need to create a collection for users, because the collection “Users” is automatically created for every game you add to Gamedonia.

 

User public information

In the user profile we are going to store the following information that can be seen by the rest of users:

  • Nickname. The name the user wants to be listed as.
  • Avatar. The name of the image she is using as avatar. The fastest method is referencing an image already in the game package. The alternatives are URL of the file, or ID of the downloadable file inside Gamedonia.
  • Friend list. The list of user id’s that are in the friend list.

 

Adding new users to the friend list

We’ll have to create a screen flow that allows the players to search for other players in the game and add them to their friend list.

The best way to add a new user to the friend list would be to store the user id of the entity, not the nickname, not the avatar, or any other concepts.

Important notice. Every object stored in Gamedonia is assigned a unique id, which is what you should use to look for the whole entity information when you need to challenge friends.

 

#4 How to play with random users of same skill?

With Gamedonia, your users will be able to play with random players around the world. Or, to be precise, players in your game database.

Now you know all these you’re ready to create any asynchronous game you want.

The most common solution would be to create a collection named “random”, or “randomqueue” and make it readable and writeable by all users: Own(er) users and Other users.

When a user wants to play with a random opponent we will need him to create an object on that collection indicating he is “waiting” for another user to join. Besides, we’ll need to store specific data that lets the user who wants to join the game decipher whether she is an opponent of same skill.

This is what you should store for this tic-tac-toe example:

  • User id. Object id of the waiting user because the opponent must be able to download the whole profile if needed.
  • Nickname. So it can be shown on screen easily.
  • Avatar. To have the picture shown on screen easily.
  • Skill. To find the right opponent and offer a balanced gameplay.

Should we create a new object every time a user wants to play random opponents?

Not really!

The algorithm to implement should be something like this:

  1. Make a search on the “random queue” collection looking for
    • a user that is not me, and
    • whose skill is close to my skill rating
  2. If the result is empty, create my own object on the queue for which I will be waiting
  3. If there are results:
    • pick one
    • create a game
    • send a notification to the opponent via server script

 

Calculate the user skill rating

In order to foster a balanced matchmaking system, it might be a good idea to have players of similar skill play each other. One way to calculate the skill level of a user is to design a system similar to an Elo rating system.

With a system like this, you can have a more balanced gameplay.

 

#5 How to notify users about their turn?

The are different ways to create a notification mechanism to alert users it is their turn to move or any other game event. Our preferred method are push notifications, though you may want to have an alternative mechanism just in case push are blocked by the user.

 

Push notifications

To let users know it’s their turn, we’ll create a server hook post-save script for the collection GAMES. This means every time a user creates or modifies a “game” object the script will run on the server side to send that notification.

The script we’ll add does a very simple thing:

  1. If the match status is waiting:
    • Pick the current user id
    • Send the user a push saying It’s your turn
  2. If the match status is created:
    • Pick the user who doesn’t Own (didn’t create) the match
    • Send the user a push saying Mary is challenging you

 

Alternatives to notify users

One option you have is to create a pulling system. This is how it’d work.

If your game detects push notifications are blocked, you can ask the server about your “games” status with an established frequency. You can do this by searching the GAMES collection or by creating a custom script that returns the information you need.

If changes to the “game” are found, you can update the scene, and if there aren’t the player can continue playing.

 

To sum up

You have to determine a few key things to build your turn-based game:

  • How to store data
  • How to structure a game
  • How to manage users

Now you know all these you’re ready to create any asynchronous game you want.

Don’t hesitate to post questions in the comments section! We’re here to help 😀