Why Sealab 2021? Because my 2002 entry was 'Aqua Team Hunger Farce'
I wrote a great mini language, preprocessor and simulator.
Which left no time for writing ants. Nuts.
My Ant as submitted can be found Here (same ant for lightning and final)
The code that is it generated from is Here
Python was used to write the simulator, the GUI, and the mini language that gets translated into ant-code. All that in under a thousand lines of code (including comments). In short we used python because it rules.
The 'real' problem of this year's contest was writing a thing to let you write good ants.
Here is a screenshot of my simulator in action (click for full size):

Green is food, Black is rock (so Black ants are actually Blue). The center color of the ant
is it's kind, the outer ring changes colors depending on what job the ant is doing to help
with debugging. The hexes are actually 7x7 squares, pasted over and over again and filled with the appropriate color.
The dropdowns on the left hand side change the board and the red/black programs. The buttons step
1/10/100/1000/100k turns. The buttons on the bottom change the image to a pheremone view.
The original simulator took about four hours to write, and was 600 lines of python. The execute function is dead simple:
def execute(self, ant):
if (ant.resting):
ant.resting -= 1
if (ant.resting): # still has leftover
return
func = self.states[ant.state]
func(self.board, ant) # modifies ant, and maybe board
ant.stepped += 1
return
The self.states[] array is just a bunch of function closures generated like so:
def mk_flip(maxint, st1, st2):
""" Make a flip function for the maxint/st1/st2 combo and return it """
if (st1 == st2): # No-Op, optimize it to skip the call to random
def skip_flip(bob, ant):
ant.state = st1
return
return skip_flip
def flip(bob, ant):
if (random.randint(0,maxint) == 0):
ant.state = st1
else:
ant.state = st2
return
return flip
It was easiest to write it this way, but psyco (python just in time compiler optimizer) gets very
confused and only provided 10% speedup when it didn't cause a coredump all together. It took about five minutes to run a full scale ant war,
after a half an hour of optimization (using native random for Flip, not updating the screen every time an ant moved) it took 30 seconds to
run a full scale war. Good enough, so I stopped optimizing.Once that was written we tried to write a simple Ant in raw ant-code. We failed miserably, it was impossible to keep track of state numbers. Then 'PASS' and 'REPEAT' were added as targets. That was still too hard, so labels and Goto's were added.
top:
Turn Right PASS
Turn Right PASS
Turn Right PASS
Move REPEAT PASS # move until we fail
Mark 0 PASS
Goto @top+1
This is all the functionality you need to write a decent ant, and was used to write the lightning entry.
Later I added some useful debugging stuff, like changing the ant's color.
If run with a single ant, it also has a window with the state numbers and orignal program text so you can
watch what un-munged code is being executed (picture of step-debugger).
top:
# change the ant's color ring
Type 1
# eval, raise an exception if false
Assert ant.type==1
# eval, and print to stdout
Print "eval() and print this line", ant.type, ant.dead, ant.state
Turn Around @top # expands to 'Turn Right PASS, Turn Right PASS, Turn Right @top'
Sleep 7 # expands to seven lines of 'Flip 1 PASS PASS'
Goto @fancy
fancy:
# these took hours to implement and were almost never used
Do 10
Move PASS REPEAT
EndDo
# simple var substitution
VAR use_marker=2
Mark $use_marker
# include other source files, with a set of VARS
include other.ant {'use_marker':2}
The preprocessor also makes some attempts to optimize Goto's that just goto the next line, and things like
that.So that was the end of Saturday, on Sunday I started to write very smart ants. It turns out very smart ants are incredibly slow at finding and gathering food. In the simulator picture above you can see a 'Kill Ring' of ants in the center of the Red hill, these ants never move. The two white ringed ants on the hill stay on the hill and move any food they find into the middle of the kill ring. They can't do this as fast as other ants put food on the hill.
In order to do that we have to figure out which ants are on what edge, and assign them duties depending
on where they are. Then we peel the onion a couple more times until we are in the center. The pheremones
on the hill end up looking like:
Phermone view | Ants and Objects View |
![]() | ![]() |
That's about it, if you want to run the simulator you'll need python2.3 with Tk installed and PIL (python imaging library).
Tarball of everything 12k (yes 12k for a GUI, simulator, and ant programs. python rules)
If you just want to peek,
board.py The board parser and Tk GUI, program.py The program parser and executer