For quite a long time (where on the Internet, “a long time” means, you know, ever since 2010 — I bet most of you have socks older than that, I know I do. But I digress, where was I again? Oh right), gamification has been a hot topic. If things said at tech conferences and board rooms across the world were tweets, I’m sure #gamification would be trending quite often.

Play where you used to work

The premise is simple: take our willingness to spend our own resources (like money, time and effort) and our drive for mastery, which we all willingly dispense while playing games and somehow harness it toward a goal more to your liking.

But, while people are ready to pay quite a lot of money to endlessly grind in their favorite game while weeks, months, YEARS pass them by,

Grinding is a term used in video gaming to describe the process of engaging in repetitive tasks

just try telling them to place proper numbers in this thing called Excel, play with the graphs and fonts for 8 hours a day, five days a week and suddenly you’ve got an “employee” who expects “a salary”, “health benefits” and “time off”. “Time off what,” you say, “having a sweet-ass computer all for yourself and making these awesome 3D-accelerated graphs?” Turns out, yes.

So, millions of people are willing to work on your farm for free (or even pay you for the experience), as long as the said farm is on Facebook? What’s the difference, besides lowered proximity to actual manure?

While proximity to manure indeed does have a certain significance, it’s not the whole story.

It’s in the game

As the above title (and, quite frankly, the whole text up to this point — should have had a “spoiler alert” somewhere in there) might have clued you in, the “game” part is important. People like playing games. No, scratch that: people LOVE playing games. People love playing (with) stuff that just sort of looks like a game, without even thinking about it.

square pavement, credit RGBStock

As a kid (before new-fangled stuff like cell phones or friends), have you ever tried making your trip to and from school less boring by only stepping on the pavement blocks, but not on the border separating them?

For some reason, it made the time and the road go by quicker, you got to your destination not bored out of your little mind. If so, you’ve basically gamified your trip home all by yourself, without Wikipedia articles, books, APIs or even any kind of framework.

Gamification is the application of game-design elements and game principles in non-game contexts

The key part is “in non-game context”; you don’t need to make people play “in game context”, they do that on their own if the game is appealing. You do, however, want to align their efforts with your desired outcome, be it profit, more users, higher quality users, more engagement / content, higher quality engagement / content, you name it. It obviously makes the process easier if your goals are more or less aligned with the user’s.

Our stab at gamification

Stand back, I gotta practice my stabbin’!, credit Fox (I guess?)

At my job in a digital agency, we were given the task of “doing gamification”, which I’ve mentioned before.

Our desired outcome was simple, although quite sinister: we wanted good stuff to happen (to our platform and our users) more often and sooner. I will not describe the whole process as it was well documented in a case study we published after seeing some results: it details selecting the elements we took into consideration for gamification, the procedures, copywriting, design process, etc.

What it does not (really) detail is our implementation. Right away, we decided not to implement it directly as the part of the app but instead chose the micro-service route, mostly to have an opportunity to use an off-the-shelf solution. We looked around and found some interesting projects. Unfortunately, I couldn’t get any of them to work (all written in Python, we’re a PHP shop) which deterred us from going down that path as we weren’t really comfortable pushing a technology we don’t thoroughly understand to production.

Not using an existing project does not mean we can’t use its documentation for inspiration.

So, we’re left with implementing it ourselves.

Game engine (GE) at a glance

To implement a “game engine”, first we need to know what “a game” means to us. In our context, it consists of two parts:

current game state:

“Currently the user has 6 potatoes.” changes between previous “current state” and current “current state” :

“User has harvested an additional potato and now has 7 potatoes, is that relevant to us?”

By functionality, we can separate the system into two parts: event processing and game evaluation.

Event processing: $potatoes++

Event processing is looking at what the users are doing, inspecting that data by various aspects (…) and assigning the outcome to one of GE’s predetermined variables, triggering the game evaluation.

In our example, the base system (which we’re gamifying) is inspecting every action which would lead to the change of the current number of potatoes and, when the number changes, notifies the GE on the change. GE stores the latest current state.

Game evaluation: $potatoes >= 10? \o/

Game evaluation begins on the GE after at least one variable has been altered: we check if the change affects the current state of the game and, if it has, we change the state (award the user with the achievement), notifying the main system about the change.

In our example, GE now knows the current state for $potatoes has changed and begins the evaluation stage:

is there an achievement which monitors the $potatoes variable? if so, is the fact that currently $potatoes == 10 relevant? if so, award the achievement.

That’s really everything there is to it. With this basic functionality (plus minor tweaks), we can implement all sorts of games.

Data model and key concepts

We’ll go through couple of key aspects of the implementation, starting with the DB schema.

Database schema

As every image is said to be worth a thousands words, here’s an image of our DB schema, followed by a few thousand words explaining it.

Simplified GE DB schema, highlighting four key segments, credit web.burza

Variables

Variables are used to define which aspects of current state we’re interested in. We have the ability to optionally set the grouping mechanism.

(grouping will determine users_variables_values.group_key which is always an integer, even for dates)

For example:

$potatoes

Total number of potatoes a user has

(no grouping)

Total number of potatoes a user has (no grouping) $potatoes_by_day

Total number of potatoes a user has had on a specific day

(grouping by time period, a day)

Total number of potatoes a user has had on a specific day (grouping by time period, a day) $potatoes_by_type

Total number of specific types of potatoes the user has

(grouping by custom property)

Achievements

Achievements are used to specify the game rules, as follows:

Achievement: Potato lover

is the end target, by being awarded achievements the user “wins”. Each achievement has one or more achievement levels. User is not awarded an achievement but an achievement level (even if the achievement is a single-level achievement).

is the end target, by being awarded achievements the user “wins”. Each achievement has one or more achievement levels. User is not awarded an achievement but an achievement level (even if the achievement is a single-level achievement). Achievement level: Potato enthusiast, Potato lover, Potato master

gives us the ability to segment an achievement down to, well, levels (ie. level 1 = 10 potatoes, level 2 = 100 potatoes, level 3 = 10k potatoes) You can only win level 2 if you’ve already won level 1. Each level has one or more achievement goals and all goals must be satisfied for the level to be awarded.

gives us the ability to segment an achievement down to, well, levels (ie. level 1 = 10 potatoes, level 2 = 100 potatoes, level 3 = 10k potatoes) You can only win level 2 if you’ve already won level 1. Each level has one or more achievement goals and all goals must be satisfied for the level to be awarded. Achievement goal: $potatoes_by_day >= 2, INTERVAL 7 DAY

is a single test of the current game (variable) state. Each goal defines which variable it is monitoring, the evaluation type it will use, for which time interval, etc.

Achievement goal evaluation types

Our GE defines three distinct types of evaluation it can use on a variable. The type availability depends on the fact if the variable is grouped and by which property.

comparison

the simplest form, take the variable value and compare it against some preset value

(ie. $potatoes >= 10, total number of potatoes is greater than 10) interval

take the variable value sum for a certain time interval and then apply the simple comparison

(ie. $potatoes >= 10, INTERVAL 2 WEEK, total number of potatoes in the last two weeks is greater than or equal to 10) streak

take a certain time interval and apply the comparison for each interval period. The total is not considered.

(ie. $potatoes >= 2, INTERVAL 3 DAY, for the last three days, number of potatoes is greater than or equal to 2 each and every day. If the user skips a day, it cannot be “fixed” by doing twice as much the next day, this goal will still fail)

Users, their variable values & achievements levels

Lastly, we come to the main protagonist of our story, The User.

users

as our user system is managed remotely, the users catalogue is only a list of valid IDs, used for referential integrity.

as our user system is managed remotely, the users catalogue is only a list of valid IDs, used for referential integrity. variables values

this is where we keep the complete current state. Group key is determined by inspecting the variable’s grouping mechanism (if specified, equals to zero if not). If the grouping type is temporal in nature (which it most often is), we look up the proper value in the calendar table, inspired by the great Calendar table concept.

this is where we keep the complete current state. Group key is determined by inspecting the variable’s grouping mechanism (if specified, equals to zero if not). If the grouping type is temporal in nature (which it most often is), we look up the proper value in the calendar table, inspired by the great Calendar table concept. achievement level

as stated earlier, we do NOT assign the user an achievement but instead an achievement level, even for single-level achievements.

Assorted implementation details

GE sample usage via REST API

So… what’s next?

Our system has been in production for a couple of months (I’m not doing very well) and we’re seeing great results, there are more KPIs and FTWs than you can swing a stick at so I’ll just refer you back to the case study.

Managed games vs. unmanaged games

As we’ve implemented it, our GE does not know about the nature of events being processed, semantics of variables, etc. This means that the system playing the game has quite a bit of work to do in order for it to work. I have no idea if this concept has an official name so I’ve called this “an unmanaged game”.

unmanaged game

the system playing is doing all the calculations on current variable value and sending the calculation result to the GE

the system playing is doing all the calculations on current variable value and sending the calculation result to the GE managed game

the system playing is just forwarding the user-generated events (and the context) happening to the GE which, in turn, persists the events, calculates and updates all the related variable values, after which evaluation is run just like in an unmanaged game.

The managed version would mean it is much easier to implement the game inside your own system and we would get some sort of sanity checking for free, as you could recalculate all the variables from scratch and verify their current values. Also, introducing a new variable retroactively would be possible (currently, we’re using a sort of “primer script” which puts the system in the desired state before introducing a new variable).

What our system is missing

support for multiple games running simultaneously

support for managed games

being an open-source project, as it would help at least one of you two who managed to read up until this point. We’re looking into this.

I hope this has at least given you a few ideas for implementing this yourself if not source code to copy/paste.

Happy gaming.