Achievements

Hi All,

In the last years we’ve found many gaming platforms like Steam, Battle.net or Origin include the concept of achievements in games, this is a concept that may as well be applied to IF games and probably has been applied already in some cases, but we lack of a centralized achievement site as for instance Steam is.

Achievements are good for game engagement and for authors feedback, apart of a common feature in modern games.

I opened a thread in spanish IF forums at CAAD. not only related to achievements but also to other kind of online tracking that may be done (like collecting all orders provided by players whose response was a laconic “You can’t do that.” or “I don’t understand you, please rephrase.”, but let’s talk about achievements first).

I was about to build an achievements library for ngPAWS authoring system, when I thought it would be nice to have a common service that may work for all authoring systems, with a common server side and the several client implementations for each IF engine. After checking with spanish authoring engine authors, they found it interesting, and so apart of my own ngPAWS engine (baltasarq.github.io/fi-js/) may be using it, or at least provide support for it. Also, it seems that is something that can be done with Inform games using Vorple (and probably can be done as well with some Quixe extension).

So, what’s is built so far? Nothing.

We have just discussed how it may work, please see a sumary with some bulletpoints below, but nothing has been yet decided, and before doing anyhting I wanted to ask other authoring system mantainers what they think about it and if in any case they are for it.

So these are the promised bulletpoints:

  • There should be a centralized site where each game may connect to save an achievement. That site would better be common for all IF engines, and have a login (so the achievements are saved with your name/nick). Maybe use an OpenID server?

  • People should be able to register (and so get an userID)

  • Authors should be able to create new games (and obtain new gameID) and achievements (and obtain new achievementID)

  • There should be a REST API so any game can try to save an achievement using three values: userID, gameID, a chievementID. The API may return a JSON object with success status and error code if it was not successful (error codes may be 0 for “uknown userID”, 1 for “unknown gameID”, 2 for “unknown achievementID”, 3 for “achievement already saved for this user”). Is up to the client implementation what to do with responses.

  • There should be an information API that allows some third party site/software get the achievement information for a given game,user or game/user combination. This API may be have some parameters to filter (like by date or by achievement count,that is get achievements 1 to 10, 11 to 20, etc.

  • Client implementation should handle the login procedure and call the server, and decide what to do if the server is unavaliable or just user decides not to participate (what should be an option).

  • Of course, game authors are able to decide wether they want to use achievements for their games or not.

Any opinions/comments?

About the player orders that fail to provide a proper answer, the same server can be used, and author may have a report that shows which sentences are most commonly not understood. But that is another story, what do you think about achievements feature?

Note: In case you can read spanish this is the link to thet original thread, though there’s not much more there than what I listed above: foro.caad.es/viewtopic.php?f=18&t=5853

I love the idea of a central IF achievement server from a design perspective, but from a development perspective, I’m not prepared to help. (Too far outside my technical abilities.)

This is a neat idea. My thoughts:

You could use the game’s IFID as a game ID – then you wouldn’t have to set up a system to assign them.

The client code is slightly simpler if “achievement already saved for this user” is not an error. It’s easier to just accept this silently.

I expect it will be impossible to make this system cheat-proof. (That is, a player will always be able to fake achievements in any game.) This is unavoidable in open-source code. I would just accept that and ignore the problem.

(You can authenticate players by making them use a password. So people can’t fake achievements for other people. But you can’t authenticate games. The best you could do is embed a secret key or password in the game file, and that’s not very secret.)

Your support is much appreciated :slight_smile:

Yes, I’ve already thought we could use that one, still you need to enter it in the achivements site, but it’s a good idea not to create yeat another ID :slight_smile:

Yes, it doesn’t have to raise an error client side, just nothing happens. Maybe the response should not include that as an error code, but just {“success”:“false”} (without “errorcode”:“nn”), is matter of defining that in the implementation and let the clients decide what to do.

I think the accept and ignore problem is the better approach, this is about having fun, see your friends achievements, etc. if you want to fake them, ok, is up to you as player.

Do you think is there a good way to implement client side for Inform games? (either I6 or I7 or both)

Two basic approaches:

  • Add the achievement API to Glk. Glulx game code could then call a function to set an achievement. Interpreters would want to offer a way for players to log in (and stay logged in through all their games).
  • Add a complete networking API to Glk (or perhaps just AJAX/JSON). Glulx game code could then include a library to do the REST requests.

The first plan is less ambitious and simpler for everybody.

I agree, and let interpreter authors decide how they implement it or even if implement it at all (as any other glk function). Also, interpreters may show a list of achievements for current game if they want, or if players stay logged in, then a list of player’s achivements can be shown.

I’ll wait a bit for more IF authoring systems to comment on this topic and then I’ll probably start writing formal specifications.

Kerkerkruip has a whole list of achievements and is free software hosted on github. If you’d like to tackle adding this central achievement system to it at some point, I certainly wouldn’t object!

If a game is hosted on a server with an OAuth 2 STS, authentication tokens can be used to ensure there is no cheating. So the REST API would send the previously mentioned values, but there would be an Authorization header with the standard “Bearer {token}”.

I could probably build and host something like this in fairly short period of time.

And too, any native interpreters could build in the same token requests to authenticate with the Achievements server. This scenario would require caching results while disconnected and then uploading when a connection is found, but that’s pretty standard stuff I would think.

I’m in the process of putting an OAuth environment together for my startup Wizely. I can use the same implementation for an IF server if we need it.

David C.
plover.net/~dave/blog

If the game can be downloaded at all, all its secrets can be extracted with a bit of wrench-work. I don’t think achievements are a good motivation to make a game online-only.

Right, so the game itself (or interpreter) could theoretically add OAuth login capabilities.

  • User opens game in interpreter
  • Games tells terp it offers achievements
  • Terp pops up login to STS
  • Once authenticated, the STS returns a “Bootstrap” token
  • Then the Terp uses the Bootstrap token to call the STS again for a “service token” or JWT
  • Then during the session, the JWT is added in the Authentication header with “Bearer {jwt}” for any calls to the achievement server, which will only return data if the JWT is valid.

No one can wrench this because the player has to enter credentials (after registering with the service). Credentials can be stored locally and/or the bootstrap token can be cached and have a really long timeout (like 90 days or maybe never). It’s all local data though so no one will care if it ever times out.

NOTE: This is pretty much what I’ve been doing at work for the past year.

NOTE: STS stands for “secure token service”

FWIW, I doubt that Choice of Games would ever want to integrate with an IF-specific achievement server.

Our iOS apps use iOS Game Center achievements; our Steam apps use Steam achievements, etc. The only cross-platform achievement system I’d consider using would be Facebook’s, just because they have so very many users. Being IF-specific doesn’t add value; it reduces value by being less visible to non-IF folks.

You’re competing with this:
developer.apple.com/game-center/
developers.google.com/games/ser … hievements
developers.facebook.com/docs/games/achievements
developer.amazon.com/appsandser … gamecircle

Now, what would be useful is a piece of drop-in code for Web-based Inform games that integrates with the major web-achievements systems (FB, Google, Amazon) and perhaps also provides a similar implementation in native interpreters/frameworks (e.g. iOSGlk… does it have one already?)

But this isn’t something that you can just do in client-side code. For the big four achievement systems, the author has to log in and define the achievements on the server side before clients can register successful achievements.

No, cheating is inevitable. Achievement success/failure is determined on the client side, and the client is under control of the attacker.

I mean, obviously, users could just follow a walkthrough and get the achievement; that’s the first layer of cheating. Obviously you can’t stop that (and probably wouldn’t want to).

Then they could write/run a script that follows the walkthrough without typing the commands. That’s the next layer of cheating. You can’t stop this, either. How can you tell the difference on the server side between a fast typer and a “real” user?

Given that you can’t prevent either of those, the next layer of cheating is to write an evil client. It would legitimately login, acquire a JWT, and be authenticated; then it would immediately report success for all of the achievements. “I just achieved X! and Y! and Z! … I just achieved all of the achievements!” There’s no way to distinguish an evil client from a legit client where the user typed really fast.

Then I could run my evil client on every game and achieve every achievement in every game. (Or I could follow a walkthrough for every game. Or I could automate the walkthrough for every game.)

This can’t be prevented. It’s not worth the trouble.

IMO, achievements are a cancer that should be removed from any game. They don’t make any sense and are the result of lazy game design where the designers are unable to integrate the feeling of achieving something in the game itself.

No one in the history of ever needed a pop-up saying: “Achievement unlocked: you’ve played through the first 20 seconds of the game.”

And even if the achievement actually represents something deserving of that name, then there should be something happening inside the game itself as a result, not a bunch of meta-info informing you about it.

You’re not the target; you’re already invested in the big game distribution platforms. The average IFArchive/IFComp entry is not, and might be interested in a standalone community solution.

Or not. If people think a simple Google-or-Amazon tie-in is more attractive, then that’s doable too.

Okay, but don’t freak out when it turns out that other people enjoy them.

I’m not sure if I got all this, I’ll have to have a closer look at it but… will all that work with a javascript client were all code can be seen and even easily modified?

To be honest I don’t see how, if in the end the javascript code have a function named "saveAchievement(userid, gameid, achievementid) what would prevent the user for launching that function from browser console once Bootstrap token or JWT token has been adquired, that is, if the game can save an achievement, the browser console can do it too.

Same goes for native terps, but calling the achievement function would not be that easy (it would require a debugger at least).

Anyway, even if all that security can be achieved, I think it would be better to concentrate first in the basic requirements :slight_smile:

I heartily dislike them as well, for the most part. However, if done well, they can be quite interesting. Thing is, they’re hardly ever done well.

The rest goes into a spoiler tag which will double as a rant tag. I spoil Heavy Rain, and also, I don’t want to start derailing the thread. But I think some discussion about “what the point of an achievement in IF is” might be relevant (and if you disagree, hey, just leave me talking to myself and I’ll get the hint!)

[spoiler]In Heavy Rain there are some achievements that are not about forcing you to lawnmower the entire game, which is what I detest about some achievements (others, the gratuitous ones, are just silly). One in particular was quite intriguing.

As you play through the game, when you play the detective, you won’t know you’re the killer. So you’ll play the knight in shining armor. Or not. Whatever rocks your boat. But then, when you discover the detective is actually the serial killer, all his interactions in-game with the various witnesses take on a new meaning.

And the achievement I’m talking about is one where you’re rewarded by doing things completely different on a second playthrough. So you know you’re the killer, heh? Then you’ll want to destroy all evidence of the crimes you’ve committed, leave behind no witnesses. It will radically alter the way you play the detective.

That’s the sort of achievement that I really think is worth having. Marco’s second Andromeda game also had achievements that you unlocked by exploring alternative solutions to puzzles. I thought that was great too.[/spoiler]

I think, RealNC, that the sort of achievement being talked about here is the one I talk about in my spoiler tags: achievements that encourage you to replay in different ways, like the Indy Quotient in Lucasart’s Indy3 or the three possible paths in Indy4.

And it’s not that you receive this achievement and it unlocks something for you; it’s that the achievement recognises that you did things a different way. Funny, IF always did have something like that: the “AMUSING” section. This would complement that section nicely. Or replace it.

The type of achievement that I think you mean is something I hate as well. But hey, as a satire it would be pretty cool. “ACHIEVEMENT UNLOCKED: WHO? WHAT? HUH? Congratulations, you’ve just had your first disambiguation prompt!”.

Huh. Come to think of it, properly done, that’d be a very funny game to play. Where’s Admiral Jota when you need him?

By the way, I 'm so concentrated lately in my new engine ngPAWS, that I forget sometimes about the old one Superglús, but this solution would make possible for Superglús to support achievements too.

I had thoughts about that a while ago, but lack time, resources and technical competences to do it ^^’

One solution for the achievements that I was thinking about was as follows: have the interpreter download the list of achievements for the game file (just hash the game and compare the hash with a precomputed database), which is a table “{ achievement, hashValue }”, where the hashValue is the hash of the string that the interpreter is displaying when the achievement is unlocked. So when you enter a command and the interpreter is displaying a string back, the hash of the string should be computed and compared to the downloaded table : if the hashValue is right, you get the achievement.

I.e. : take the string, say, “CONGRATULATIONS! YOU HAVE JUST VANQUISHED A DRAGON WITH YOUR BARE HANDS! (UNBELIEVABLE, ISN’T IT?)”, compute the hash value of this string (call it v), and add to your table “{ achievementDragonKilled, v }”. If the player kills the dragon, the interpreter is supposed to reply “CONGRATULATIONS! YOU HAVE JUST…”, it computes the hash value of that, which is v, it looks in the table, sees that v is there, unlocks the achievement “achievementDragonKilled”.

(Crash course on hash functions for those who are wondering: think deterministic paper-shredding functions : feed it a string, it will always give you the same short garbled mess ; and you can’t figure out the string from the garbled mess, or any string that would result in the same garbled mess. This is used for authentication, fast access to information, fast comparison of data, file integrity, etc.)

The pros:

  • works for any format with an interpreter, at the expense of modifying the interpreter slightly;
  • doesn’t modify any spec, so everything remains compatible;
  • prevents cheating, in the sense that finding a collision of the hash value is difficult.

Cons:

  • may be a slight tax in performances, although computing MD5, SHA-1 or even SHA-3 hashes is really, really fast
  • all the ones I don’t see because you don’t see the flaws in your own ideas :slight_smile:

To make it a flexible system, authors could have a file containing the names of the achievements, their description, their values, and the corresponding hashes, publicly released with the game, and each website/interpreter will work with that. (True, that makes hidden achievements harder.)

You might like: armorgames.com/play/2893/achievement-unlocked

Yes, you can do this from a JS client. Remember, the user has to login. If it’s web hosted, you’re actually directed to the host STS site for the login page and a cookie is set with the Bootstrap token. Once authenticated, you’re redirected back to the game site.

There is a lot of work to cheat. You’d have to unpack the story file to get the achievement codes, use a rest client to post new achievements. I highly doubt anyone would care. Maybe if there were money involved or something. Just for kicks? Maybe that’s an achievement too. Like you put a dummy achievement code in the game that never gets used. The hacker fires that at the server and we delete their account. Or we just give them a Hacker Achievement.