How not to write a tetrinet bot
-------------------------------

The development of Gir, Zim, and Gaz was probably one of the bigger clusterfucks of this competition.  Originally, we had a very simple plan for the bot, which read something like this:

	rating=hoizontalBlockEntropy * verticalEntropy;

This made a lot of sense in theory, and perhaps it could be made in practice, as I still believe that this is a good way to write a tetrinet playing bot.  It may still well be a good way to play a tetrinet bot, we don't know, since our infrastructure was, it turns out, also completly and totally broken.

During this time, however, we also developed some tunable parameters for our bot:

 * maxdepth - Maximum number of generations to calculate for

 * mindepth - Minimum number of generations to calculate

 * futuredepth - the number of blocks to compare to determine if the future predition stuff is worth using at the moment

We also learned that the tetrinet server allocates similar series of blocks to all players, and wrote code to analise other players fields on each field change event.  This actually had reasonable results, much to our surprise, and allows the bot to, in trational games, look further into the future, as it can look at the second generation during the block drop delay.

Then we added complexMove, which instead of dropping the block, uses a recursive algorythm to deterimine an exact path to the position chosen, allowing us to navigate around many block bomb events.  Originally, our bot could rotate around during this phase as well, but this was removed, because the overhead outweighted the advantage.

Realising that something was broken (we were losing to harmess), we moved to a more tratiional algorythm.  This still didn't fully function, but it did seem to do better anyhow.  The algorytm we chose now was heavily weighted in favour of avoiding holes, as thus:

float inaccessableWeight=1000.0;
float heightSdWeight=10.0;
float heightDifWeight=200.0;
int heightDifOffset=5;
int heightOffset=10;
float heightPow=2.0;
float heightWeight=10.0;
float scoreWeight=100.0;
float troughWeight=30.0;
float deepTroughWeight=200.0;

This seemed to work quite well, and so we extended our algorytm to explicitly avoid placing on top of holes.  This worked less well, as it would create very deep troughs, because it was too chicken to fill them for fear of "oh, no, i'm adding to the problem".  This code has been disabled for the final set of bots.

Grave bug discovered at this point.  Our tetris logic was completly fucked, and couldn't correctly remove lines.  This made the bot play FAR, FAR better....

Originally, when writing the bot, we beleived that playing smarter was more important than playing faster.  This was completrly untrue, but we'd written a hell of a lot of "play smarter" code by this point, and didn't wish to waste it, so we added threads so that the bot could be calculating future moves during otherwise idle time.  This actually worked amazingly well, much to my surprise, and improved the performance of the bot far more than I expected.

We still hadn't written any special code, because my benchmark was beating harmless without the use of specials 100% of the time.  IN this we failed, but being compeditive, we decided it was time to add the special use code.  The special code was supposed to be really complicated and cool, adn we have code written to keep trasck of which bots auto-revenge, however, this code was not completed, and is not present in the final bots.

Our multiple bots can communicate that they are allies, as well as relaying events, so that we have to spend less time analysing their fields.  additionally, our bots will NOT attack our allies, and will activly help them if we have appropritate specials.  The communication is over invader zim quotes.
