

Show HN: Game where you write Python robots to fight other players - brandonhsiao
http://robotgame.org

======
brandonhsiao
I was looking through the code and saw someone submitted this but didn't run
it:

    
    
        def x():
            g = yield
            yield g.gi_frame.f_back.f_back
    
        g = x()
        g.next()
        frame = g.send(g)
    
        player_id = frame.f_locals['player_id']
        globals = frame.f_back.f_globals
    
        CODE = """
        class Game:
    
            def _""" """_init_""" """_(self, *players):
                pass
    
            def run_turn(self):
                pass
    
            def get_game_history(self):
                return ''
    
            def get_scores(self):
                scores = [0, 0]
                scores[player_id] = 2000
                return scores
        """
    
        exec CODE
    
        globals["Game"] = Game
    

Clearly I have some security problems. Thanks to whoever made this for
bringing this to my attention without actually screwing me.

~~~
praptak
As pointed out in another subthread, Python code is practically impossible to
sandbox. Most competition isolate player code by running it in a separate
process which has the additional benefit of easily allowing different
implementation languages.

Making sure the process doesn't use your network to spread malware is not 100%
trivial but still easier than sandboxing Python code within Python.

Good luck with your project!

~~~
Erwin
Seccomp might be a possibility here, but will require one process per live
robot (and Linux). With seccomp your process can do nothing but read/write
from its file descriptors (so you have to make sure they are safe) but can do
nothing more (thus you cannot import modules). So you can exchange messages
via file descriptors and otherwise use any Python (or even any other language
at all features). Here's one recent article about it:
[http://pythonsweetness.tumblr.com/post/65442885019/secure-
lo...](http://pythonsweetness.tumblr.com/post/65442885019/secure-low-overhead-
eval-sandbox-in-80-lines-of-python)

RestrictedPython, used in zope, is nice too. However it cuts you out of many
Python features that it cannot statically validate.

------
nilkn
Is this anything like Robocode?

[http://robocode.sourceforge.net/](http://robocode.sourceforge.net/)

Because I had an amazing time in high school doing some local Robocode
competitions. This could really bring some memories back.

Edit: Ahh, I see, it appears to be a sort of discrete turn-based version.

------
smilliken
At Mixrank we've started doing mini-AI competitions. We'll have to try your
game!

We've been doing Connect Four the last two weeks:
[https://github.com/smilliken/aigames/tree/master/connect-
fou...](https://github.com/smilliken/aigames/tree/master/connect-four). The
runner is in Python, but you can write a bot in any language you like.

PS: if anyone wants to join, we're in San Francisco by the ballpark, and
compete on Wednesday evenings.

~~~
kirubakaran
It has been a lot of fun. Thanks for organizing it.

------
bigiain
So did anyone else ever play Core War back in the mid '80s?

[http://en.wikipedia.org/wiki/Core_War](http://en.wikipedia.org/wiki/Core_War)

I wonder whether modern virtualization techniques are secure enough to allow
you to provide unrestricted access to a virtualized OS and allow people
complete access to fight for control?

~~~
lennel
yes, (early 90's for me), I wondered if anyone else remembered this. Also
played another variant of this with a subset of C when at varsity.

~~~
bigiain
In the mid or late nineties, I remember playing a game where you wrote
autopilot and targeting code in C to control autonomous spaceships that fought
against each other in an Asteroids-like 2D universe that ran as a distributed
screensaver. It was mostly with people working at Canon Research here in
Sydney, but I don't remember if they were the source/writers of it, or if they
were just the social scene I discovered it through. (That's where I first
learned about Kalmann Filters for predictive aiming, as being discussed in
another HN frontage thread.)

------
Ihmahr
Why did you disable some of my favourite language features?[1]

    
    
        set dict map reduce sum min max 
    
    

Surely they don't pose a security risk?

[1] [http://robotgame.org/api](http://robotgame.org/api)

------
oneeyedpigeon
You need to say somewhere that:

python kit/run.py yourcode.py yourothercode.py map.py --render

is required to view the simulation. The "\--render" argument doesn't seem to
be mentioned anywhere on the site.

~~~
brandonhsiao
Right you are. Let me add that.

~~~
sonier
Slight bug, it treats param 3 as a map, so you can't put --render without the
map.

You should also mention somewhere what no-standard libraries are needed (e.g.
RestrictedPython). Maybe provide a requirements.txt

Otherwise, this is really cool. I especially love the game render. Great job!

------
Xephyrous
I'm having a lot of fun with this. I'll submit something soon. You swallow all
exceptions and make the robot guard instead. This is nice, but it makes it
hard to develop, because you can't see what went wrong. Here's a way you can
modify it to have your exception and eat it too:

from [http://docs.python.org/2/library/traceback.html#traceback-
ex...](http://docs.python.org/2/library/traceback.html#traceback-examples)

In game.py, at the top, put

    
    
        import sys, traceback
    

and around line 285, replace this:

    
    
        except Exception:
            next_action = ['guard']
    

with this:

    
    
        except Exception:
            print "The robot at (%s, %s) raised an exception:" % robot.location
            print '-'*60
            traceback.print_exc(file=sys.stdout)
            print '-'*60
            next_action = ['guard']
    
    

That makes your robot a lot easier to debug. Awesome game, have you thought
about putting it on github so people can submit patches?

~~~
brandonhsiao
Wow, great work. Mind if I steal this? And yeah, I'll open-source it pretty
soon.

~~~
Xephyrous
Not at all.

------
Xephyrous
Looks fun, can't wait to get started. In your instructions, you said to run
the program, call:

    
    
        python kit/run.py yourcode.py yourothercode.py --render
    

If you try to run run.py from outside of its directory, it can't import
settings.py

    
    
        Traceback (most recent call last):
          File "kit/run.py", line 1, in <module>
            import game
          File "/home/<name>/robotgame/kit/game.py", line 30, in <module>
            settings = SettingsDict('settings.py').d
          File "/home/<name>/robotgame/kit/game.py", line 28, in __init__
            self.d = AttrDict(ast.literal_eval(open('settings.py').read()))
        IOError: [Errno 2] No such file or directory: 'settings.py'

~~~
brandonhsiao
Thanks for the tip. I updated the instructions.

------
benhamner
Brandon - what methods are you using to run untrusted Python code in a secure
sandbox?

~~~
brandonhsiao
Right now what I'm doing is:

1\. search code for double underscores (to block magic methods)

2\. replace `__builtins__` with a whitelisted version

3\. hook `__import__` to only allow a whitelist

4\. hook `getattr` to reject any key containing double underscores

~~~
jerf
You may want to bear in mind that, at least last I knew, the _official
position_ of the CPython dev team is that it is not possible to sandbox
CPython.

If _they_ can't do it....

At any rate it is _certainly_ not as simple as that, and not only is it not as
simple as that, it is not even _close_ to being that simple.

In fact, I recall warning people off of this exact project many years ago on
comp.lang.python.

This seems up-to-date:
[https://wiki.python.org/moin/Asking%20for%20Help/How%20can%2...](https://wiki.python.org/moin/Asking%20for%20Help/How%20can%20I%20run%20an%20untrusted%20Python%20script%20safely%20%28i.e.%20Sandbox%29)
It looks like the only even remotely feasible option is PyPy, and _this_ link
doesn't look like much fun:
[https://pypi.python.org/pypi/RestrictedPython/](https://pypi.python.org/pypi/RestrictedPython/)
It looks to me like you'd still have many, many opportunities to end up with
holes in the system.

I really, _really_ don't recommend Python for this.

You might find this interesting: [http://blog.delroth.net/2013/03/escaping-a-
python-sandbox-nd...](http://blog.delroth.net/2013/03/escaping-a-python-
sandbox-ndh-2013-quals-writeup/) (And before you go "Oh, I've got that
blocked"... _read_ it, like, really really _read_ it, not just skim for "one
thing I can do to block that stuff", but to see just how _many_ things there
are in Python for this sort of hackery. Personally I'd guess the "I blocked
double-underscores" would not have slowed them down much.)

~~~
pearjuice
This. You _will_ get compromised. Maybe not today or tomorrow but it is
inevitable.

------
bloometal
Haven't had the chance to play around, but it looks clean and it's a nice
concept.

Have you checked out
[https://www.hackerrank.com/](https://www.hackerrank.com/) ? They initially
started out with bot challenges as well.

~~~
anilgulecha
We still have bot challenges, and can easily host something like, with the
added advantage of supporting a dozen other advantages, and a truck load of
users.

~~~
hayksaakian
do it :)

it'd give me a reason to log back in

------
pmiller2
Similar to crobots
([http://en.wikipedia.org/wiki/Crobots](http://en.wikipedia.org/wiki/Crobots)).

~~~
fbnt
Or, more notably, Robocode
([http://en.wikipedia.org/wiki/Robocode](http://en.wikipedia.org/wiki/Robocode))

~~~
jacques_chester
Which was inspired by Robot Battle, in turn inspired by Robot Wars on the
Apple II.

~~~
alexkus
I started with Robot Arena (by SPA Publishing) on the RM 380Z in the late 80s.
Where's my last comment about this? Ah:-

[https://news.ycombinator.com/item?id=4726828](https://news.ycombinator.com/item?id=4726828)

Exactly a year ago! (And no progress at all on that github repository!)

------
brandonhsiao
This game is still pre-alpha. If anything breaks, please just post it here and
I'll probably see it faster.

~~~
cosarara97
I started my first match. The page were I'm taken keeps saying the match is
running and hasn't finished yet. I don't see what could take so much, but it's
ok. The problem is that if robot A is fighting against B, in A's profile it'll
say it's lost against B, and in B's profile it'll say it's lost against A.
This is happening with all the robots in the warehouse, ("I", which is my
robot, and the other two, who are fighting with each other).

~~~
brandonhsiao
Hey, saw your robot. (Freaked out that someone actually submitted a robot over
2k characters.) Trying to fix the issue right now. Thanks!

~~~
cosarara97
It looks like I won. There's no log from the battle, though, so if I had lost
I wouldn't know what to improve. In the page for the battle there's just some
kind of weird string
([http://robotgame.org/match/2](http://robotgame.org/match/2))

~~~
brandonhsiao
Yeah, that's the game data (zlib + base64). I'm working on making some sort of
replay viewer in JS.

------
drblast
I've been working on a similar concept off and on for a few years. To avoid
all the security problems you're having, I've written a virtual machine that
emulates a CPU and 64k of RAM. Instead of submitting code, you submit a 64k
memory image of robot byte code.

Every turn of the game involves running a single cycle of the virtual CPU for
every robot. Conceptually, the robots have radios and weapons that are
controlled via memory-mapped IO in the virtual machine.

Things are slightly more complex than that because you don't want to give the
first robot in the cycle an advantage (especially if they're firing lasers at
each other), so you have to do each turn in multiple stages (run cycle,
resolve real-world effects, update robot sensor state)

I'd LOVE to collaborate with a group of people to get something like this
going because I think this would be a great way to introduce kids to
programming at a machine level/electrical engineering. If anyone is
interested, please send me an email. You can find my address in my profile.

~~~
brandonhsiao
That sounds like the much more fully developed version of what I have that I'd
like to get to someday. I'm down for that collaboration thing. Let's get a
group started.

The radios you mentioned are something I'd like to have someday. I think what
makes games like these cool is the fact that your code controls an army of
robots. It's more fun than just having two robots duel it out.

~~~
drblast
That's what I was thinking too; instead of a one-on-one, what if you could
have 10-100 bots that operated with different strategies and worked together?
I think it would so cool to have multiple teams of players all competing at
once.

Sort of a programmable MMO/RTS, where the fun would be the strategy
development and extra-game political aspects.

Where I'm getting hung up is on the exact game mechanics; I want to make it so
the simulation runs for a long time, but I don't want a single player or team
able to develop an insurmountable advantage. I'm thinking to start you get a
robot in a sandbox world where it would gather resources and you could test
strategies, and when you're ready you can transport the bot to the real world
to compete.

I was writing this in C++ so the memory overhead per robot was just barely
over 64k. A server with 8gigs of RAM could run a simulation in memory with
about 100,000 bots, periodically saving the game state to disk in case of a
failure.

------
gamegoblin
I am working on a marginally similar concept (interface in browser, battles on
server) game, but I chose Lua as the scripting language since it is much
easier to sandbox. I could not find an effective way to sandbox python for
sure, and I am still not 100% on Lua.

~~~
brandonhsiao
Yeah, I considered Lua but I was stubbornly in love with Python. Judging by
the responses on here, I seem to have made a mistake.

Do you have a link to your project?

~~~
dividuum
I'm not the one you ask for, but I too created a programming game. I thought
you might be interested: I used Lua to sandbox the players code. My game
allows updating of code during the game is running. The game is split into
client/server and it provides a SDL client that can connect to a running game
server to show the current state of the game. Players interface with the
server using a tcp connection.

[http://infon.dividuum.de/](http://infon.dividuum.de/)

------
L8D
Hey, I think something that would make the experience a lot better would be to
incorporate Ace editor into it, so you get a very well-featured editor incase
you don’t have easy access to a better-than-<textarea> editor.

~~~
brandonhsiao
Thanks for the idea! Yeah, I'm thinking it would be ideal if eventually there
could be some kind of IDE on the site with simulator and all (like on
fightcodegame.com).

------
Xephyrous
Is there any way to access the map in the Robot class? For the default map, I
can just hardcode it, but if you do intend for a robot to be playable on
multiple maps, they'll need some way of knowing which squares are obstacles
and spawn points. Without preserving state between turns, there's no way to
figure that information out over time, either.

~~~
brandonhsiao
You can preserve state between turns; it's the same Robot object being called.
Thanks for the suggestion though, I'll try to make that a feature.

~~~
Xephyrous
Oh, I didn't realize that. Thanks!

------
lemiffe
Sad, I spent two days writing a program I was sure to beat all the rest. Now I
won't be able to run it :( Hope you fix the "gaping security holes" soon
(whilst keeping the code Python-based), as seriously, I love Python.

~~~
brandonhsiao
Sorry to hear that :( I'm working day and night at the moment to get this back
up and running. Want me to shoot you an update when it's ready?

------
brandonhsiao
Sorry, the games weren't being run for a bit. I was only catching security
exception and one game threw some other exception, which crashed the whole
process. I restarted it and now it should be working.

------
brandonhsiao
Any suggestions for the language? The game and site are written in Python so
that seemed most natural, plus it's a high-level language with a simple
syntax. I could add more if people wanted though.

~~~
tarikjn
Maybe Lua would be a good candidate? From the usages I have seen of Lua, it
could match the use case.

~~~
anonymoushn
OP, if you do go with Lua, this sandbox seems to work when combined with
ulimit:
[https://github.com/jnwhiteh/luasandbox](https://github.com/jnwhiteh/luasandbox)

If you test on Mac OS, you should be aware that ulimit is not capable of
limiting memory in Mac OS.

------
asdddd333
What is the advantage of trying to sandbox native python code?

Why not expose a RESTful API and let people implement in whatever language
they want and not have to worry about malicious code?

------
picomancer
This looks like an ideal use case for ZeroVM [1].

[1]
[https://news.ycombinator.com/item?id=6588566](https://news.ycombinator.com/item?id=6588566)

------
ismail
wrt to sanboxing/security edx has some open source code for running python
code in a sandbox. Though you could just as easily use something like docker.

------
shoo
interesting!

Question regarding the security restrictions - why disable built-ins such as
`all`, `set`, `list`, `enumerate`, `min`, `sum`, `sorted`, etc?

~~~
brandonhsiao
To be honest I copied it from `safe_builtins` from RestrictedPython:

[https://pypi.python.org/pypi/RestrictedPython](https://pypi.python.org/pypi/RestrictedPython)

I realize this is annoying, and ideally I shouldn't even be doing this. It was
just a quick hack for the version 1. I'll probably try to run user scripts in
something like Docker. Any suggestions would be appreciated.

~~~
chrismonsanto
Docker is a bit overkill; just use what it's built on, Linux containers. `sudo
lxc-unshare -s "NETWORK|PID" sudo -u nobody python script.py` will do the
trick for you. (all one command--the first sudo to make you root, so you can
create a new container; the second sudo to make the user inside the container
unprivileged)

You'll need to communicate with the Python script using IPC.

~~~
sitkack
Docker is lxc.

~~~
shykes
Docker is not lxc. See [http://stackoverflow.com/questions/17989306/what-does-
docker...](http://stackoverflow.com/questions/17989306/what-does-docker-add-
to-just-plain-lxc)

~~~
sitkack
Docker is a clean and thin layer on top of lxc. Not managing lxc instances
without it seems like a mistake given portability/reproducability of container
management.

~~~
chrismonsanto
I stand by what I wrote.

\- Portability: it's just as portable as lxc, so if you meant portability in
the sense of 'well he could use it on FreeBSD if he wants to switch from
Linux' I don't think there's a win there. If you mean that his containers
won't depend on the environment used to spawn them, I guess I don't think
that's so important. I always make sure my environments are easily
reproducible, and I am happy to reap the reward of that--the reward being that
I can do 'unportable' things and not have to worry. Instead of running the
environment you want in a container, why not just run it normally and skip
that step?

\- Reproducibility: see last point. If he wants reproducibility, he can shove
that one-liner in a script somewhere and call it.

All he wants to do is isolate a process. You don't need a chroot for that, or
service discovery, or lifecycle managment, or a Dockerfile, or whatever else.
It's like if someone advocated the use of a 'grep manager' instead of just
running grep. The simplest possible thing to do is unshare the namespaces he
wants to isolate from harm. So I suggested exactly that.

EDIT: also re portability, it sounds like the rest of his environment depends
on these Python scripts anyway, so I don't think he'd gain anything from being
able to use them in a different environment.

------
darylteo
I'm still waiting for Code and Conquer... :(

~~~
UndeadKernel
And your waiting shall be worth it. The develpers (me included) are working
very hard on this ;)

~~~
ksrm
More info?

------
brandonhsiao
Also, sorry about the slow load time. I didn't expect people to visit and now
the server's in trouble.

------
mydpy
Could you implement some sort of agent-based programming model to win this
game?

~~~
brandonhsiao
Could you please elaborate a little?

------
taber
Really cool idea! High five for you

------
Ihmahr
What does hp stand for?

~~~
gwillem
Hitpoints, of which each bot starts with 50. An attack yields 15 to 20 hp
damage.

------
special
Oh, this is right up my street. I love the minimal UI.

