Skip to content

Instantly share code, notes, and snippets.

@rooklift
Last active February 7, 2023 13:56
Show Gist options
  • Save rooklift/2421a9730c1af0c2306e3b23c06cf3e7 to your computer and use it in GitHub Desktop.
Save rooklift/2421a9730c1af0c2306e3b23c06cf3e7 to your computer and use it in GitHub Desktop.

If your language can generate a standalone binary for Linux, probably you can use it for Lux. This little guide details what I learned writing a Golang bot for the competition.

It all starts with main.py

The first thing Lux will do when running your bot is run (or possibly import) main.py, a Python script which will call your bot as a subprocess. This script will pass your stdout to Lux, and will pass the game state each turn to your bot.

Various main.py scripts exist now in the official Lux kits. I recommend using the JavaScript kit's main.py (yes, it's a Python script in the JavaScript kit). This version of main.py has the useful property that it adjusts what Lux sends it slightly, producing a consistently-formatted input to your bot. All you have to do is edit it so that instead of running node as its subprocess, it runs your bot instead.

Input

Every turn, the input to your compiled bot will be a single line of JSON. This brings us to a potential snag: this line can be very long, and if you just naively try to read it, you might run out of buffer space. This happened to me in Golang, since the most trivial way to read lines in Golang has a limit of 64K. Dealing with this is up to you; in my case I simply switched to Golang's streaming JSON parser.

The actual format of the object you get after parsing the JSON is fairly complex and you'll just have to figure it out for yourself.

Output

Each turn your output (to stdout) should be a JSON string followed by a newline \n character.

To understand the output format, I suggest you modify one of the starter kits to write its output to file, then study that. There are essentially 3 phases of the game, with different output formats. Some examples:

  • Bidding phase: {"faction": "FirstMars", "bid": 0}
  • Placement phase: {"spawn": [39,22], "metal": 150, "water": 150}
  • Main phase: {"factory_2": 1, "factory_4": 1, "unit_6": [[2,0,4,660,0,1],[1,0,0,200,0,1],[0,2,0,0,0,1],[3,0,0,0,0,10]]}

In the main phase, if you don't want to send an order for a unit or factory, just leave it out of the JSON. Notice too that factory orders are a single number, while units produce arrays of arrays. In Golang, it would be slightly awkward (though not really hard) to get the JSON library to produce such mixed output, so I forego the JSON library entirely and construct the output with string manipulation.

To understand the action format for units, see the advanced specs.

Uploading to Kaggle

Once you have your working bot, compile it into a Linux binary, and place it, together with the main.py file, into a .tar.gz archive. (Kaggle lies to you and tells you that you can use .zip files. You cannot.)

One final hurdle is making sure the files in your archive have the appropriate file permissions. I myself just used 0o777. If (like me) you're on Windows, setting these permissions is not so trivial, but I made a small Python script to create the archive for me. See here for the relevant help.

And that should be it. Good luck!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment