3 ms·
Nice hack. Yes, this is not cheat proof by any means. But Ruby is by its nature hard to prevent someone from doing whatever they want. I did try to make it sem
by reedlaw 15y ago
Nice hack. Yes, this is not cheat proof by any means. But Ruby is by its nature hard to prevent someone from doing whatever they want.
I did try to make it semi-cheat proof by using a delegator PlayerProxy that sends method calls to the real Player objects. But if you're going to read the stats of other players you must be able to call Player#stats somehow.
- cheald 15y agoIt might be worth defining some boundary conditions on what constitutes a valid player. "May not touch any other game classes/modules, except for this whitelist of methods" and "may not reimplement these methods" is a good start. As-is, there is so little direction that I'd argue that my player is valid per the letter of the rules. :P Without those constraints, there are limitless ways to cheat, especially since it's impossible to actually hide functionality in ruby (obligatory: https://github.com/fxn/i-told-you-it-was-private https://github.com/fxn/i-told-you-it-was-private ), so you have to have a set of meta-constraints in place. Regarding proxying, why not just use the Forwardable module? Though, even if you did manage to hide the critical pieces from the Player, I'd just iterate ObjectSpace to find a PlayerProxy that contains a reference to my Player. :P
- reedlaw 15y agoYou're right, but for me another challenge was to try to circumvent cheating. If I see players that try to win by pure Ruby hackery I'd like to see if there's a Ruby way to make sure that hackery doesn't work (inside Game, Player, or PlayerProxy). Is there a way in Ruby to prevent a module from overriding a method of the class in which its included?
- cheald 15y agoShort answer: No. Nothing in Ruby is truly private, and even if you did manage to hide references to something, you could always find it in ObjectSpace. I could even undefine your Game class and replace it with my own (I reject your reality, and substitute my own!) To get true cheating prevention, you'd have to do something like spawn off another Ruby process and use some kind of IPC to pass events to your "client" process and receive actions back to your "server" process. All canonical state would be held by the "server" process. This is really the classic "don't trust the client" problem that all games run into. :)
- mooom 15y agoif you force move to be an arithmetic function with inputs the stats of the game, then you can parse that the syntax of the move functions only involve arithmetic operators and some math functions (max, min, ...). This way one can't cheat in the game.
- cheald 15y agoMy #move method was perfectly innocuous; I cheated by making my player never take damage, and by giving him infinite stats. Parsing source code for "bad" stuff is generally an arms race you can't win. For actual sandboxing you need a clean environment (hence, the reference to Lua's setfenv).
- jabr 15y agoI haven't used it, but if you're running this on MRI, you might try https://github.com/tario/shikashi https://github.com/tario/shikashi