Novice programmer here. To challenge my self i want to create an achievement system that randomly generates achievements for me based on a set of trackable metrics within my game.

To keep it as abstract as possible my game is a turn based highscore chaser. Each game has 13 turns. Each turn consists of placing 4 tiles, each tile can have an individual score which together form the turn score. There are 5 different tile types that can be individually combined to raise each tile's score differently. Each turn one of the 5 tiles gets a bonus making it worth double points. Also in each turn you can form "hands" similar to poker where for example two tiles of the same type next to each other are a pair, which nets a hand bonus for individual turns.

Here's what my generated achievements should look like:

Get a turn score of 15 and create a pair using tile type x.
Create a tile type y that has 5 points.
Create 5 hands of type x and use tile type x or y.
Get a total score of 50 without creating more than 3 hands of type x.

Obviously this seems kind of complicated and i'm kind of asking myself how to create such "complex" achievements. Seems like i need to establish some kind of syntax that i can feed the system to produce these kinds of requirements. But i'm kind of stuck since i couldn't find any info on this issue yet.

Maybe you have done something similar?

  • \$\begingroup\$ How will people compare achievements? \$\endgroup\$
    – Lucien
    Dec 11, 2015 at 18:26
  • 1
    \$\begingroup\$ The ideas is that people get 3 random achievements each day, more like quests or tasks. If they complete them they get a reward. Pretty much like Hearthstones Dailys. But in hearthstone the Achievements are kind of lame since they repeat to much and are not different enough. \$\endgroup\$ Dec 11, 2015 at 18:29
  • 2
    \$\begingroup\$ Ah, I see. I'd call them "Daily quests" or "Miniquests" or something to make it more clear but nice idea! \$\endgroup\$
    – Lucien
    Dec 11, 2015 at 19:26

2 Answers 2


I'd solve this by breaking down an achievement into constitute parts and then randomly selecting values from pools for each part. Based on your examples, you have an achievement grammar that looks like

achievement = <verb> <instance count> <metric> <value count> [and <achievement>...]

that is, an achievement is a basically a verb associated with a metric which may be joined via 'and' with another achievement up to some arbitrary number of times you'll get to decide (probably no more than twice?)

You'd then define the valid values for each aspect of the grammar. For example, you've already got some metrics:

  • turn score
  • tile type value
  • hand type
  • use of tile type

And some verb types (plus a few extra I've made up that might work):

  • create
  • acquire ("get")
  • use (play, as in play a hand)
  • last (as in, "last for X turns")

The instance and value counts are just numbers, so you can pick ranges for them that seem appropriate ("5" hands seems reasonable, "0" hands does not, for example).

Whether or not you stick two conditions together with an "and" can just be a fixed percent chance that you deem appropriate. At this point generating a random achievement is simply a process of generating a random value for each component of the grammar.

You'll probably want to introduce some data dependence between the various components. For example, the valid range of values for instance counts might depend on the metric that was randomly selected, because a range of one to five might work for "hands" but may be too small to be a challenge for "score," for example. Similarly you may want to prevent certain verbs being generated with certain metrics because they may be nonsensical for the rest of your game.

  • \$\begingroup\$ Awesome thanks for your input. I will try to implement something tomorrow. \$\endgroup\$ Dec 11, 2015 at 21:10

Make a base for the types of achievments, like you started. Example in a Hack'n Slash game: Slay X enemies Survive X seconds Block X hits

And so on. Then you need to setup a few metrics. I can't use the same Block metric for the Survive, because Survive 10 seconds is far easier than Blocking 10 times. So, your best bet is to make a multiplier to the random number you got. Slay (rnd() * 50 + 10) enemies Survive (rnd() * 30 + 15) seconds Block(rnd() * 10 + 2) hits

The plus part represents the minimum, and the multiplier the max without the min. So the Slay means that the minimum is 10 up to 60(50+10) enemies.

  • \$\begingroup\$ Thanks but i want the system to spit out unique combinations not pre defined things. What i don't want is Collect 15, Collect 20, Collect 30. I want unique combinations of different metrics. \$\endgroup\$ Dec 11, 2015 at 18:31
  • \$\begingroup\$ Maybe create a relationship matrix? I mean, you can say that "Slay X enemies" can combine with "Enemy Type", "in X seconds" and so on. The X value you can still use the part that I said on the answer. \$\endgroup\$
    – DH.
    Dec 11, 2015 at 18:32
  • \$\begingroup\$ Mh ok that could be interesting. I would define which metric can be combined with which and also how. I think there needs to be some logic connectors too. Like "and" "or" "not" and so on. I would also need to define how many metrics are combined in one achievement. This way the difficulty could also be somewhat adjusted. \$\endgroup\$ Dec 11, 2015 at 18:40
  • \$\begingroup\$ Also, make sure that the combined parts have read the before parts to avoid impossible or easier achievments. Like, "Slay 20 enemies in 3 seconds" depending on the game is impossible, and "Slay 5 enemies in 10 seconds" seens too easy. You may want to make a metric like "IF(EnemyType){ value = (BeforeMetric/normalizer) }", where the normalizer is a parameter got from the Slay X enemies function. \$\endgroup\$
    – DH.
    Dec 11, 2015 at 18:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .