note: here lies the original notes that started the problem; it's sorta out-of-date now.
█████ ▓██▓ █████░ ▓██▓ ███████ ▓███▒
█ ▓█ ▒█ █▒ █ ▒█ ▒█ █▒ █ █▓ ░█
█ █ █░ ░█ █ █ █░ ░█ █ █
█ ▒█ █ █ █ ▒█ █ █ █ █▓░
█████ █ █ █████░ █ █ █ ▓██▓
█ ░█▒ █ █ █ ▒█ █ █ █ ▓█
█ ░█ █░ ░█ █ █ █░ ░█ █ █
█ █ ▒█ █▒ █ ▒█ ▒█ █▒ █ █░ ▓█
█ ▒ ▓██▓ █████░ ▓██▓ █ ▒████░
Programming-language-agnostic robot battles
This framework is where people can write robots in their own programming language - whichever one they wish - and they'll be run and connected with a central server.
Ideas borrowed from AT Robots 2, http://necrobones.com/atrobots/ and see the specification here: http://necrobones.com/pub/atrobots/docs/atr2.txt
This framework runs in three parts:
URL reference: http://host/matches Redirects the user to the list of matches if in a browser http://host/matches?history=t Tracks the history of the match list (for long polling clients) http://host/matches?list=t JSON object of current list of matches. http://host/matches?register=t Registers a match. Returns the ID of the match along with a code so you can start it. http://host/matches/00000 Web page of certain match. http://host/matches/00000?register=t Register a slot in a match. http://host/matches/000/slot?connect=t Connect to a running match. http://host/matches/000?start=t&code=c Start a match.
Basic outline of a match:
The person writes a robot in their progamming language of choice.
The robot, when ready, connects to a unique match URL on the server. This is probably a unique, temporary URL with a special query parameter that only that instance of the robot and the server should know. Probably something like http://robotwars.com/matches/12358912/robot_982349721347 The URL should should disappear after the match is over. This method should easily do two things:
Allow the user to intervene if they wish. (e.g. the web page shows a button that says "Here is your unique URL, paste this into your code" and then they'll do just that and their robot will connect. This is useful if the user just wants to test out one simple robot without registering it against their account.
Or, allow the robot to do this in an automated fashion, for e.g. tournaments and such. The user could assign a unique ID to their robot in their source code, register that ID to their account, and then stick the robot in tournaments or whatever. It would then connect to the match. If it should go to a match right away; e.g. if another person "challenged" the robot or if it's in a tournament, the server will report its "match URL" and the client robot will connect. If not, it could tell the server that it wants to fight and go on a "challenge list" or something.
Here's an example. A simple client where the user doesn't mind copying and pasting the URL from the web page before every match could look like this:
url = raw_input("Copy+paste the URL on the web page: ")
robot = RoboLink.connect(url) if robot is none: sys.exit("Connection failed.")
while not robot.dead(): robot.shoot()
A persistent client would look more like this:
ID = md5sum("StormBot " + VERSION + external_ip) while True: if RoboLink.registered(ID): matches = RoboLink.get_pending_matches(ID) else: matches = [raw_input("Copy+paste the URL on the web page: ")]
for match in matches:
robot = RoboLink.connect(match)
if robot is none:
sys.exit("Connection failed.")
while not robot.dead():
robot.shoot()
if robot.is_winner():
print "We won! Awright!"
Of course, the API could probably abstract this quite a bit into something like:
def run_robot(robot): while not robot.dead(): robot.shoot ID = md5sum("StormBot " + VERSION + external_ip) RoboLink.persistent_connection(ID, run_robot)
which could prompt the user for a key or just run indefinitely.
This allows users to have long-standing "client robot daemons" on their computer, just waiting for a fight and connecting immediately when there is one.
The robot could optionally declare attributes about itself when it connects; say, something like this:
robot.connect_with_type({'speed': 25,
'armor': 30,
'power': 90})
The robot.signal_ready() call blocks until ALL opponents call it.
Then the match begins. Robots could do stuff like
targets = robot.scan() for bearing, position in targets: print "Robot detected at %d degrees %m away" % (bearing, position)
In this example, robot.scan() would block for a bit -- scanning takes time of course! -- and then prints all the robots that it found to the console.
When all but one robot is dead, they could call stuff like robot.dead() to find out if they're dead and robot.is_winner() to see if they are the winner, etc.