Last weekend I finished making a copy of the B17 Flying Fortress that GE posted on Thingiverse earlier this year. To get it to print easier I split it up into individual parts instead of one printing plate and scaled it up 20% to max out the wing length on my Thing-o-Matic’s build platform. After some paint I think it looks really good.
Painting it turned out to be a big hassle. I tried using an airbrush, but I didn’t want to spend too much to start out. As a result, I spent less than $30 on the whole setup. Everything worked decently except for the little propellant can. I had seen warnings online about how poor those things were, but I figured it was an exaggeration.
It was not.
It’s Thing-o-Fun’s Functional Differential Gear System! I finished it a few weeks ago, but I just got around to taking a picture. It came out very well, except for the spot I jabbed trying to unstick the large gear from the build platform.
Over the weekend I updated my bot to use a line of sight to decide on what to do for each ant. This fixes some of the worst behaviors my ants had, but it’s not perfect. The ants no longer crowd up trying to get to food or a hill they can’t reach, but they’re still not terribly bright. I had to turn off the food reservation system because it wasn’t intelligent enough and the side effects were worse than the benefits.
So how smart is my bot now? I’m not sure. It should be better, but the AI Challenge keeps having server problems. My bot had to wait most of the weekend for games to start being played again, and they seemed to have another problem today. Because of this games aren’t happening very fast at all so my bot hasn’t had the chance to move up to it’s true rank. The AI Challenge forms have posts about alternate servers you can test you bot on, I may have to go to that.
I’m a little tired of working on the bot at this point, even though I can think of quite a few things I should do. After all the time I’ve put in lately, it would be nice to see my bot reach it’s potential (or at least where it was before the last change). The slow game rate was very demotivating.
My bot topped out around 1000th place. After a while it started to lose, which wasn’t that surprising. For various reasons, my bot is very bad on the maze maps and those seem to come up the majority of the time.
I spent the week trying to make my bot more intelligent. I’ve wanted to use gradients to give my bots marching orders, so I worked on code to do it. I wrote it over two days or so and rewrote it at least twice before I tested it as I kept thinking through the algorithm. I was really pleased when, except for one a mistyped variable name, it worked the first time.
I started testing how fast it was (since bots in the AI Challenge are limited to 3 seconds per turn) and it was great on tiny test cases. As I went to test it on random data that represented something the size of the large maps, it started crashing. I spent a bunch of time chasing down a StackOverflowError bug. I was pretty sure it was a bug in my code for quite a while, but as it turned out it’s just a known issue in Clojure, my code was technically correct. If you embed LazySeq in LazySeq in LazySeq over and over when Clojure goes to get a value it can go so deep that it runs out of stack space. The solution is to force evaluation to remove the “Lazy-ness”.
Unfortunately, things are still way too slow. Doing a full re-build every turn is never going to work, so I need to make it so I do partial updates every turn. While doing a little research I found that Clojure has a hidden queue type, which is drastically faster at removal (about 60x in a simple test case) than my List based solution.
In the mean time I have made my bot smarter. I’m hoping my bot is now up to tired toddler, but we’ll see as it starts to run games. I added a food reservation system to prevent tons of ants from getting piled up trying to get to a single piece. I also added some code to help with exploration, but I had to disable it as it caused a weird side effect I didn’t feel like debugging tonight. It actually caused more jams.
Speaking of jams, while watching my last replay I noticed an odd case. The ants are programed not to go backwards if possible. When a group of ants gets boxed in to a concave area in a map, if the outside ants push “in”, they won’t want to go backward and end up locking all the ants in. I did shuffle some code around, so this may no longer be an issue. I’ll just have to keep an eye on it.
Well it took me a few tries, but I finally managed to get a successful Skull Bowl printed. Next up, trying to make it in to bank. I’ve got a good idea of how to proceed, I just have to actually get around to it.
My bot is doing surprisingly well. It is currently the highest rated Clojure bot, and is ranked a little below 850th out of ~5700. I’m a hair under the 15th percentile.
I’ve uploaded a new version of my bot to the AI Challenge site. My bot was, I believe, the 10th best Clojure bot before I updated my code and wiped out my rating. The new code probably won’t play it’s first game until early tomorrow morning. I put in a fix for the possible issue of my ants failing to defend their hills, giving my ants courage when they could see one of my hills.
The problem with ants getting trapped that I mentioned before actually bit me. In my bot’s 5th game, it’s first move was into such a corner. As a result, it did precisely nothing the entire match, until an enemy ant kindly came along and wiped me out.
At least that’s fixed now. New intelligence rating: very tired toddler.
I really loved the MechWarrior series. Thanks to Pipakin’s MadCat Mech on Thingiverse, I now have my very own.
My bot has played two more games, and legitimately won both. But while I was thinking last night I came up with a bad realization: since my bot runs from enemy ants, it would run away from protecting the hills. This could allow a single ant to capture a hill that had lots of ants around it.
This hasn’t happened yet. I’d better put a fix in before it does.
My entry for Google’s Fall 2011 AI Challenge has been posted. In it’s first game it pulled out a decisive victory, in that it was gathering food but none of the other bots were. Still, it’s up there.
Current intelligence rating: badly sleep deprived toddler.
Right now, the logic is pretty simple. For each ant it works through a list of objectives, making the first move that an objective returns. It tries to raze opponent’s hills and gather food, all while running away from enemies. If it can’t do either of those, it will basically make a random move. There is code to prevent the ants from cycling between two squares, but it has an unintended consequence. The ants aren’t allowed to go back to the last square they were on. The leads to ants trapped on little islands surrounded by water (there are five such trapped ants in the shot above).
On the whole it works well. Since my colony spends so much time gathering food, it grows fast. The cowering I built into them helps keep them alive, and the random walking combined with the food seeking provides some exploration. In the end, the colony can grow pretty large and they tend to stay clumped up. I’d imagine I’m no match for the good bots, but I should be able to survive OK.
As I post this, there are only 25 Clojure based bots. I’m hoping to make a good showing on the list. That’s my main goal.