Fun, thanks for sharing. ProtonDB says[0] this runs great on Linux so I'll give it a shot. (If your game is on Steam, runs on Linux, is highly reviewed or otherwise interesting to me, and costs in the single digits, I'm probably gonna buy it.)
Hedgewars, Spring RTS and 0AD also had issues with deterministic lockstep and floating point. It wasn't as simple as just tweaking compiler flags either, unless you could control all compilers and environments which is tricky to pull off in cross-platform open source.
Hedgewars uses fixed point math. I believe Spring uses streflop now. I don't know too much about the 0AD situation.
https://m8y.org/hw/fp.html A chart of floating point variations. In time idling in the Spring and 0AD channels I picked up similar desync matrices from them.
> Sadly, the C++11 <random> library is not portable, but the excellent PCG Random library is, so I used the latter.
Yes it is. std::random_device will not give you a deterministic sequence (obviously!), but the standard PRNGs absolutely will. Check, for instance, std::mt19937, which specifies exactly what the 10,000th value has to be [1].
That's not to say that you shouldn't go with PCG. PCG is a fantastic PRNG. But claiming that the <random> PRNGs are not portable is just FUD.
The indirectly linked stackoverflow https://stackoverflow.com/questions/14840901/is-the-random-l... goes into more detail: mt19937 is, but distributions (particularly, based on my experience a few years ago, floating point ones) are not. If you have to build your own distribution functions, you may as well base them on a better PRNG than is in the C++ standard.
In the context of that sentence though, it doesn’t make any sense. PCG is a PRNG, not a library for generating distributions. In fact, the PCG documentation uses the distributions from <random>: [1].
If people want to use PCG, that’s perfectly fine, it’s a great library. My point is, there’s nothing wrong with the PRNGs in <random>, they work great. Mersenne Twister is not state of the art anymore, but I guarantee you that unless you’re doing something truly insane, neither the throughput nor the statistical properties of MT is gonna be your bottleneck.
I did something similar to this for a falling block game (for PICO-8). One fun bonus of uploading replays for validation is that you can let other people download and watch replays to see how players achieved their top scores.
In my case, I whipped up a quick-and-dirty replay viewer for my game that runs in the browser (no sound or textures or anything): https://fbg-db.netlify.app/
For the record: no one ever even attempted to cheat at my game :)
But even in that case it might be very easy to tell the AI run (i.e. a TAS) from human play. The cheater can then of course go out of their way to make TAS inputs resemble human inputs, at which point it's a battle of statistical tools.
2 seems easy to defeat. If you know you're going to slow down 30 seconds to 5 minutes, you could just send the start packet 4 minutes and 30 seconds in, instead of at the beginning.
3 seems easy to defeat too. Just add a duplicate set of fields, which default to the same values as the original ones, and have the first set control the RNG and the second set control the display. Then you can change the second set all you want.
For 2, the server can send back a random number (let's call it a nonce) for that attempt session. This nonce can be used to seed the prng such that you couldn't have started the attempt before telling the server that you're starting, only after.
3 is not fully solvable I think, it's the same class of hacks as x-raying. You can only make it really difficult. At the end of the day, you can't control what's being rendered client-side, short of cloud gaming. I have seen ML approaches to detecting behaviour server-side for things that shouldn't be humanly possible (like seeing through a wall) but it's an arms race.
Of course if someone wants to cheat at this they can, even with those deterrents. It's a fun cat and mouse game for the cheater, less so for the developer. :) I'd recommend reading Greg Gaffer's articles. He gets into a lot of detail on this in networked multiplayer games. https://gafferongames.com
17 comments
[ 4.7 ms ] story [ 58.0 ms ] thread[0] https://www.protondb.com/app/1358090/ Okay it's one person, a year ago, but for $4.49 I'll take the risk.
Edit: Running it on Mint 20, works perfectly so far.
Hedgewars uses fixed point math. I believe Spring uses streflop now. I don't know too much about the 0AD situation.
https://m8y.org/hw/fp.html A chart of floating point variations. In time idling in the Spring and 0AD channels I picked up similar desync matrices from them.
> Sadly, the C++11 <random> library is not portable, but the excellent PCG Random library is, so I used the latter.
Yes it is. std::random_device will not give you a deterministic sequence (obviously!), but the standard PRNGs absolutely will. Check, for instance, std::mt19937, which specifies exactly what the 10,000th value has to be [1].
That's not to say that you shouldn't go with PCG. PCG is a fantastic PRNG. But claiming that the <random> PRNGs are not portable is just FUD.
[1]: https://en.cppreference.com/w/cpp/numeric/random/mersenne_tw...
If people want to use PCG, that’s perfectly fine, it’s a great library. My point is, there’s nothing wrong with the PRNGs in <random>, they work great. Mersenne Twister is not state of the art anymore, but I guarantee you that unless you’re doing something truly insane, neither the throughput nor the statistical properties of MT is gonna be your bottleneck.
[1]: https://www.pcg-random.org/using-pcg-cpp.html
Avoid.
B) I loaded the page without an adblocker and didn't see anything phish-y or inappropriate.
In my case, I whipped up a quick-and-dirty replay viewer for my game that runs in the browser (no sound or textures or anything): https://fbg-db.netlify.app/
For the record: no one ever even attempted to cheat at my game :)
3 seems easy to defeat too. Just add a duplicate set of fields, which default to the same values as the original ones, and have the first set control the RNG and the second set control the display. Then you can change the second set all you want.
3 is not fully solvable I think, it's the same class of hacks as x-raying. You can only make it really difficult. At the end of the day, you can't control what's being rendered client-side, short of cloud gaming. I have seen ML approaches to detecting behaviour server-side for things that shouldn't be humanly possible (like seeing through a wall) but it's an arms race.