If you're like me, you might enjoy these as well:
1. Microcorruption - https://microcorruption.com/ (a game that teaches about embedded systems and security basics)
2. Over the Wire - http://overthewire.org (several games based on Web security)
3. WeChall - http://www.wechall.net/ (a big list of games with progress tracking)
A friend of mine just started (yesterday) looking at Ruby stuff and this looks awesome, but I wouldnt recommend any service that has an impassable FB login after level 1.
This kind of problem comes up very often in the context of the Linux kernel. And the ability to deal with it is as even rarer among programmers experienced with concurrency than experience with concurrency is among programmers in general. A tutorial of this form for memory ordering issues would be invaluable.
I'd be happy to help with problems and game-element design for a memory-ordering version of this tutorial.
 You get the idea
Years of programming I guess have made me an explicit cross referencing kind of guy. I find it far worse when your not explicit at times. Misunderstood communication can lead to bad things...
One suggestion: it would be nice if you somehow integrated the fix for each bug into the game somehow. At the very least, in the congratulations screen, you could show a version of the code updated to fix the concurrency bug.
In other words, this helps you learn what not to do, but not so much on what you should do.
Btw, I bet Edward Lee¹ would like this game.
This manually "trickery" you are introducing is you intentionally replicating potential control flows that can (and will) happen in real life. You should come out of this game with a new/renewed paranoia about multithreaded programming and how seemingly safe code may not necessarily be so.
2. do a few iterations through thread 1 (e.g. n=5)
3. step darkness++ concurrently (via expand), so that darkness=1
4. step thread 0 to Monitor.Wait(sanctum)
5. the rest is straightforward.