text:
Codémon, I choose you!

Your kindly neighbour, Doctor Tree, just gave you three magical creatures called Codémon. There's a battle tournament in the nearby town of Colorville. Are you the very best, like no one ever was?

Overview
This is a battle tournament. Each player controls a team of three monsters, and the objective is to knock out (kill) the other team. There are 100 rounds, with points being awarded for wins and ties. The team with the most points wins!
Monsters
A Codémon is a complicated little creature. There are five types (elements) to choose from, three stats, and three move slots on each.
Types
Each Codémon is assigned one type. The five types are Normal, Psychic, Fire, Water, and Grass. Each has its strengths and weaknesses. Damage is based on the following chart:

The numbers are damage multipliers. For instance, Fire attacking Water has a 0.5 modifier (half damage), whereas Fire attacking Grass is doubled (2).
Stats
Each monster has three stats that determine its battle abilities. Attack raises the damage it does. Defense lowers the damage it takes. Speed allows it to move before those with lower Speed.
Each monster has a starting value of 50 for each stat, and a maximum of 100. When you create your monsters, you will be able to assign 80 additional stat points (each). Remember that no individual stat can go over 100. So, you could have a 100/80/50, 90/80/60, or 65/65/100 distribution, but 120/50/60 is illegal. Any team with illegal stats is disqualified. You are not required to use all 80 points, but you probably shouldn't go with the minimum 50/50/50.
You could also consider HP a stat, but each Codémon has a non-modifiable 100 HP. When HP drops to zero, they are unable to continue fighting. HP is refilled to 100 before each battle.
Moves
Each monster knows three battle moves. The three chosen must be distinct, so no Punch/Punch/Punch.
There are 15 moves, three of each type. Each type has a direct attack, a weaker attack with an effect, and a sole effect move.
id  name        type    power   uses    usable  effect

0   Punch       N       20      -       NFWG
1   Heal        N        0      3       NFWG    Heals 50 HP
2   Slow        N       10      5       NFWG    Enemy speed x0.8
3   Pain        P       20      -       PFWG
4   Sleep       P        0      3       PFWG    No enemy action until wake
5   Weaken      P       10      5       PFWG    Enemy Atk x0.8
6   Fireball    F       20      -       NPFW
7   Burn        F        0      3       NPFW    Enemy -10 HP each turn
8   Sharpen     F       10      5       NPFW    Own Atk x1.25
9   Watergun    W       20      -       NPWG
10  Confuse     W        0      3       NPWG    Enemy may strike itself (10 power)
11  Shield      W       10      5       NPWG    Own Def x1.25
12  Vine        G       20      -       NPFG
13  Poison      G        0      3       NPFG    Enemy -5xTurns HP each turn
14  Sap         G       10      5       NPFG    Enemy Def x0.8

type refers to the type of the move. power is its striking power. uses indicates how many times it can be used per battle (- is unlimited). usable shows what types it can be used by (for example, Punch cannot be given to a Psychic type, as there is no P). effect shows what effects the moves have. There is a 75% chance of each effect working, except Heal, which always works.
For effects that change a monster's stats, effects may be stacked. For example, using Weaken twice may lower your opponent's attack to 0.64 effectiveness. Effects that do not change a monster's stats (Sleep, Burn, etc) do not stack.
Sleep puts the opponent to sleep, with a 60% chance of waking at the start of each turn. No action will be taken by sleeping monsters.
Burn damages the opponent 10 HP at the end of each turn when active. Poison works similarly, but takes an increasing amount each turn. On the first turn, it's 5, and it gains 5 each turn thereafter. So, by the fourth turn, it will be damaging for 20. These are flat damages, not affected by the monster's type or subject to bonuses.
Confusion may make a monster attack itself instead of doing what it was told to do. This attack has power 10, and has a 30% chance of happening on a given turn.
To be clear, effects last until end of battle (except Sleep, as noted above).
Moves also receive a 20% boost in power if used by a monster of the corresponding type. For example, a Grass monster using Vine is boosted, while using Punch he is not.
Secret Stats
The stats and type (but not moves) of each monster is public knowledge. Your opponents will be able to see what they're fighting, in order to choose the best action. However, there are also bonuses available that are hidden.
Specifically, after every two battles, you will be given one "bonus" stat point for each monster on your team. Points are given to all monsters, dead or alive, winner or loser. You can assign this to whichever of the three stats you choose. You cannot stack them on a single monster; each monster gets one each time. These points are immune to the 100 limit. Since there will be 100 battle rounds, this means you can get a single stat up to 149 if you allot all your bonuses to it. Again, the opponent will only see your "base" stats, so the farther into the tournament you are, the further their knowledge diverges from the truth.
Battle
Battle takes place between teams of three, with one active on each team at a time. At the start, you will be shown the opponent's team and asked to choose which monster will be your first "active" player.
After that, turns take place with the following steps:

Switch : Mandatory monster switches take place (if any)
Choose battle action
Switch : Any optional monster switches (chosen as battle action) take place
Sleep Check : Chance to wake from sleep
Attack 1 : If able, the speedier monster uses its selected move
Attack 2 : If able, the other monster uses its selected move
Effect damage : Apply burn/poison damage to living monsters

"Speedier" means the monster with the higher speed. If both speed stats are the same, it is chosen by PRNG coin flip each turn.
At the end of any turn where your active monster dies, you will be asked to choose a new active. You may also choose to switch active monsters as your move for any turn (provided you have more than one alive). Again, if you switch as your move, you will not make a battle move that turn.
Monsters are not "processed" when inactive. This means they take no burn/poison damage, poison counters won't accumulate, no wake from sleep, etc. No effects are removed or changed when switching. This isn't that other monster battling game. If you switch out with attack raised and burned, they'll still be there when you switch back in.
Effect damage takes place whether you kill your active opponent or not. In this way, members of both teams may die on a single turn.
When one team runs out of usable monsters, they lose. If both teams run out on the same turn, it's a tie. If the battle lasts for 1000 turns, it's a tie.
The formula to determine damage is:
floor((effAttack / effDefense) * movePower * typeMultiplier * moveBoost)

effAttack and effDefense are the effective stats for the monsters. Effective attack is obtained by adding Attack and Bonus Attack, then multiplying (by 0.8 or 1.25) if any effects alter it. Remember that these effects can stack.
Damage can only be 0 when the type modifier is 0 (Normal <--> Psychic) or the move's Power is 0 (Heal, Burn, etc). Otherwise the minimum is enforced at 1.
Tournament
Tournaments last for 100 rounds. In each round, the teams are shuffled and paired against each other randomly. If there are an odd number of teams, the leftover receives a bye (scores as a tie). Winning a battle earns the team 2 points, ties are worth 1, and losses nothing. The team with the most points at the end wins!
If teams are tied, a tournament with only the teams tied for first place will take place to determine tiebreaker order.
Protocol
The controller will send your program one of four commands. The first character determines the command type, with data following if necessary.
Your program will accept the command as an argument, and will respond on STDOUT within one second. Do not stay alive listening to STDIN, it won't be there. Each command will spawn a new process.
You may write data/state to disk. Place any files in a subfolder with the same name as your team. Do not write more than 32 kilobytes of data, or you will be disqualified. Data will persist between rounds, but will be cleared between tournaments.
Commands
Team Data
This is sent once at the start of the tournament to register your team. Your reply should be constant, not different for each tournament.
Query:
T

Response:
name|member0|member1|member2

name is a string with your team name. Please use alphanumeric only, for ease of parsing. memberN is a member string, giving the details of each monster:
Member string:
name:typeid:attack:defense:speed:moveid0:moveid1:moveid2

Again, 'name' is a string, this time with this monster's name. typeid is its type. Type ids are in the order shown in the chart above, with Normal=0 and Grass=4.
The next three fields are your base stats. Keep in mind the limits described in the stats section above.
The last three are your monster's moves. IDs are shown in the move chart above.
An example team data reply may look like this:
DummyTeam|DummyA:0:50:60:70:0:1:2|DummyB:0:50:60:70:0:1:2|DummyC:0:50:60:70:0:1:2

Any team that sends back garbage, ill-formatted, or illegal data here will not participate until it is fixed.
Choose Active
This is sent at the start of each battle, and when a monster dies and needs to be switched.
Query:
C#battleState

battleState shows the state of the current battle. Bear with me here, it's ugly:
yourTeamState#theirTeamState

Where XteamState looks like:
name:activeSlot|member0state|member1state|member2state

activeSlot shows which monster is currently active (0-2). The member states come in two flavors. If it's your team, it gives extra information. So,
Your memberXstate:
name:id:attack:defense:speed:hp:typeid:poisonedturns:moveCount0:moveCount1:moveCount2:bonusAttack:bonusDefense:bonusSpeed:effectid:effectid:effectid

Their memberXstate:
name:id:attack:defense:speed:hp:typeid:poisonedturns:effectid:effectid:effectid

id is simply an integer identifier you can use to keep track of monsters if you don't like using name.
attack:defense:speed are your base stats.
poisonedturns tells you how many turns you've been poisoned for.
moveCountX tells how many uses you have left for each move. If 0, it cannot be used. For unlimited moves, this will be negative.
bonus(stat) is the amount of bonus points you have assigned to each stat.
effectid is a variable-sized list of effects that have been applied to your monster. There will not be a trailing : on the string, whether there are active effects present or not. If there are stacked effects, they will show up as multiple effects in the list.
The effect ids are:
0  NONE           (should not appear, internal use)
1  POISON
2  CONFUSION
3  BURN
4  SLEEP
5  HEAL           (should not appear, internal use)
6  ATTACK_UP
7  ATTACK_DOWN
8  DEFENSE_UP
9  DEFENSE_DOWN
10 SPEED_DOWN

Response:
memberSlot

The only response required is a single number 0,1,2, telling which member you want to be active. This must be a member who is able to fight. Don't send back 1 if member 1 is dead.
Battle Action
Each turn, you need to decide what to do.
Query:
A#battleState

The battleState here is exactly as described above.
Response:
To use a move, send back the slot the move is in. For example, if I assigned Punch to slot 0, sending 0 performs Punch.
To switch to another member, send the member's slot plus ten. So to switch to member 2, send 12.
Anything not in [0,1,2,10,11,12] is considered invalid and will result in no action taken this turn.
Bonus Stats
After every two battles, you receive a secret bonus point for each team member.
Query:
B#yourTeamState

Your team state is the same as shown above, don't make me repeat it.
Response:
stat0:stat1:stat2

Your response will represent what stat to increase for each team member. Attack is 0, Defense is 1, Speed is 2.
So to raise member one's speed, member two's attack, and member three's defense, you would respond with:
2:0:1

Controller
The controller can be found on BitBucket: https://Geobits@bitbucket.org/Geobits/codemon.git
Just toss all of the compiled class files, submissions, and players.conf in a folder and run.
The controller's main class is called Tournament. Usage is:
java Tournament [LOG_LEVEL]

Log levels from 0-4 give increasing information. Level 0 runs the tournament silently and just gives the results, where level 3 gives turn-by-turn commentary. Level 4 is debug output.
You can add submissions to the tournament in players.conf Simply add the command line string needed to run the program, one per line. Lines starting with # are comments.
In your post, include the command I will need to add to my players.conf, and any compilation steps (if required).
Included is a dummy team comprised of all Normal members with the three Normal moves. They choose moves randomly and have terrible stats. Have fun beating up on them.
Misc Rules

You may not read or write to any external resources (except in your own subfolder, up to 32 kB as noted above).
Your team needs to go into the tournament "blind". That means you can't analyze other people's source to figure out what a specific team/monster will do in a given situation. You can analyze your opponent's moves/stats and keep track as the tournament progresses, but no hardcoding this information in.
Do not interfere with other processes/submissions. No invoking them, using reflection to get at their data, etc. Do not mess with my computer. Just don't try it. This is at my discretion. Violators may be barred from future entry.
Contestants are limited to a maximum of two entries. If you submit more, I will only score the first two submitted. If you want to revoke one, delete it.
Entries may not exist solely to prop up other entries. Also, you may not try to indirectly disqualify other contestants (for example, using a 27M character team name to DQ players that try to write this to disk). Each submission should play to win on its own merit.
Your program may spawn a maximum of one child process at a time (total descendants, not direct). Both the main and any child processes must terminate directly after giving output. Either way, ensure you don't go over the timeout.
The tournament will be held on my computer running Ubuntu with an Intel i7 3770K processor.

Results
These are the results of the current players. It's very close between the top contenders, and I'm thinking about bumping the number of rounds up to 500 (and adjusting the spacing of bonus points to match). Any objections, comments?
------- Final Results -------

158     Happy3Campers
157     LittleKid
71      InsideYourHead
68      HardenedTrio
46      BitterRivals

Full play-by-play results on Google Drive

I wanna be the very best / Like no code ever was / To not crash is my test / To debug is my cause! / I will travel across the LAN / Scripting far and wide / Trying hard to understand / Why my BIOS fried! / Codémon, it's you and me / Golfing all the eye can see / Codémon, you're my best friend / After the program ends! / Codémon, a lang so true / No segfaults will pull us through / You teach me and I'll teach you / Codémon, gotta golf em all!

Instead of increasing the rounds to 500, it would be nice if one round would consist of everyone fighting everyone. So no more byes for an uneven number of competitors and it would be made sure that the match pairs are fair and evenly distributed.

@foobar I wanted to avoid that because it scales the battles with n^2 instead of n. With just the current 7 competitors and 100 rounds, that's 2100 battles (vs 300 as-is, and 1500 with 500 rounds). It only gets worse as more entries come in. I could scale back the # of rounds, but I hesitate to do that because of the inherent variability (regarding statuses esp), and having a multiple of 50 (for bonus points) is easier.

Doesn't this challenge requires an update? :)

@GholGoth21 Yes, I believe it does. I probably can't get to it today, but maybe tomorrow or the following day. Ping me in chat if not updated by Thursday or so if you'd like.

Happy 3 campers - PHP
A bunch of cowards who like to pelt the opposition with debilitating spells and watch them rot away.
EDIT: Mr. Lumpy has been severely chastised and won't say no bad words anymore

HandyGrass - atk:50 def:99 spd:81 Confuse Poison Heal
A venomous armless beaver who likes to confuse people with problematic handshakes

FlippyWater - atk:50 def:99 spd:81 Confuse Burn Heal
A bulletin board veteran with a soft spot for bore-me-silly talks and flame wars.

NuttyFire - atk:50 def:99 spd:81 Burn Poison Heal
Weapons of mass destruction are his favourite candies.

LumpyPhp - lines:500 clarity:05 spd:01 Gather Guess Store
Thanks to his nearly 2 digits IQ and phenomenal memory, Lumpy can guess enemy moves. Well, mostly.

Strategy
The strategy is to have adversaries poisoned, burned and confused as soon as possible.
Sleep was not used since it seemed less powerful than the 3 spells above.
Confusion is deadly in the long run, since it reduces attacks by 30% (both damage dealing and spell casting), prevents healers from healing themselves and harms heavy hitters badly (a 50 def / 100 atk monster will inflict 20 points of damage upon itself).
Once a foe is thoroughly pasted, my campers simply watch him sizzle, rot and punch himself to death.
High defense and healing are used to mitigate incoming damage during the agony.
While my 3 campers are fighting, Lumpy the magic deer watches the enemies every move, and sometimes manages to identify them. The information is fed back to our fighters, who do their best to take advantage of it.
After defense, speed is the most important stat to boost.
Initiative is crucial for applying healing before the next blow comes.
Attack is not used at all.
Are spells the ultimate weapon?
Spells like poison, burn and confuse escape the overall rock/paper/scissor logic of other attacks.
Once a monster is affected, it will continue losing HPs even after the spellcaster is dead. It is as if the ghost of the caster kept attacking him.
Besides, poison becomes quickly more powerful than a fully buffed-up massive attack (above 50 points after 5 turns).
A poisoned and burnt monster's life expectancy does not go beyond 8 turns, even with 3 healings.
As Martin's bots seem to indicate, the game balance is pretty good.
It's basically initiative that will tip the balance between pure spellcasters and pure attackers.
The code
Invoke with php campers.php
It's an ugly mess, but frankly the interface does not help either.
Now that a suitably agressive competition appeared, I implemented my long planned enemy moves guessing.
Analyzing attacks requires various aerobatic deductions and persistent storage of last turn state, which means full-scale war with the paranoid controller interface.
It ain't no pretty stuff and no six-legged jackrabbit either, but it does an adequate job.
<?php

// ============================================================================
// Game
// ============================================================================
class G {
    static $code_type = array ("Normal", "Psychic", "Fire", "Water", "Grass", "?", "self");
    static $code_move = array    ("Punch", "Heal", "Slow", "Pain", "Sleep", "Weaken", "Fireball", "Burn", "Sharpen", "Watergun", "Confuse", "Shield", "Vine", "Poison", "Sap", "?", "self", "pass");
    static $move_uses = array (1000,3,5,1000,3,5,1000,3,5,1000,3,5,1000,3,5,   2000,2000);
    static $move_type      = array (0,0,0,1,1,1,2,2,2,3,3,3,4,4,4, 5,5,5);
    static $move_dmg       = array (20,0,10,20,0,10,20,0,10,20,0,10,20,0,10,  20,10,0);
    static $move_forbidden = array (1,1,1,0,0,0,4,4,4,2,2,2,3,3,3);
    static $code_effect = array ("N", "Poison", "Confuse", "Burn", "Sleep", "H", "Sharpen", "Weaken", "Shield", "Sap", "Slow");
    static $decode_type, $decode_move, $decode_effect;
    static $damage_multiplier = array (
        array (2, 0, 1, 1, 1, 0),
        array (0, 2, 1, 1, 1, 0),
        array (1, 1,.5, 2,.5, 0),
        array (1, 1,.5,.5, 2, 0),
        array (1, 1, 2,.5,.5, 0),
        array (2, 2, 2, 2, 2,-1),
        array (9, 9, 9, 9, 9, 9, 1));
    static $atk_score = array ("Poison"=> 1002, "Confuse"=>1001, "Burn"=>1000);
    static $status_field = "atk:def:spd:hp:type:Pturns";
    static $all_moves, $strong_moves, $medium_moves, $effect_moves, $possible_moves;

    function init()
    {
        self::$status_field = explode (":", self::$status_field);
        foreach (array ("type", "move", "effect") as $table) self::${"decode_$table"} = array_flip (self::${"code_$table"});
        foreach (self::$code_move as $c=>$m)
        {
            if ($m == "?") break;
            self::$all_moves[] = new Move($m);
            if (self::$move_uses[$c] >  5) self::$strong_moves[] = $m;
            if (self::$move_uses[$c] == 5) self::$medium_moves[] = $m;
            if (self::$move_uses[$c] == 3) self::$effect_moves[] = $m;
            for ($type = 0 ; $type != 5 ; $type++) if ((self::$move_uses[$c] >  5) && (self::$move_forbidden[$c] != $type)) self::$possible_moves[$type][] = $m;
        }
    }

    function __construct ($name, $team)
    {
        $this->turn = 0;
        $this->name = $name;
        $this->team = $team;
        $this->results_pending = false;
    }

    function parse_team ($tpack, $own_team)
    {
        $pack = explode ("|", $tpack);
        list ($name,$active) = explode (":", array_shift($pack));
        if ($own_team)
        {
            $team = $this->team;
        }
        else
        {
            if (!isset($this->enemies[$name])) $this->enemies[$name] = new Team(array (new Monster (), new Monster (), new Monster ()));
            $team = $this->foes = $this->enemies[$name];
        }
        $team->active = $active;
        foreach ($pack as $i=>$mpack) $team->monster[$i]->parse_monster ($own_team, $mpack);
    }

    function choose_active ()
    {
        // detect start of round
        $team = $this->team;
        $foes = $this->foes;
        foreach ($team->monster as $i=>$m) if ($m->hp > 0) $candidate[$i] = $m;
        if (count ($candidate) == 3)
        {
            $this->results_pending = false;
            $this->round++;

            // reinitialize all monsters
            foreach (array($team, $foes) as $t)
            foreach ($t->monster as $m)
                $m->start_round();

            // guess initial opponent
            $opponent = $foes->initial_opponent();
        }
        else
        {
            $this->analyze_last_round();
            $opponent = $foes->active();
        }
        return $this->do_switch ($opponent);
    }

    function choose_attacker ($foe)
    {
        foreach ($this->team->monster as $i=>$m) if ($m->can_attack($foe)) $candidate[$i] = $m;
        if (isset($candidate))
        {
            uasort ($candidate, function ($a,$b) use ($foe) { return ($a->atk_score != $b->atk_score) ? $b->atk_score - $a->atk_score : $b->life_expectancy($foe) - $a->life_expectancy($foe); });
            return key($candidate);
        }
        return -1;
    }

    function do_switch ($foe)
    {
        $replacement = $this->choose_attacker ($foe);
        if ($replacement < 0)
        {
            $candidate =  $this->team->monster;
            uasort ($candidate, function ($a,$b) use ($foe) { return $b->life_expectancy($foe) - $a->life_expectancy($foe); });
            $replacement = key($candidate);
        }

        $this->old_own = $this->team->monster[$replacement];
        $this->old_own->attack = "pass";
        return $replacement;
    }

    function choose_action ()
    {
        $this->analyze_last_round();
        $own = $this->team->active();
        $foe = $this->foes->active();
        $this->old_own = $own;

        if ($own->hp <= $own->max_damage($foe) && $own->can_do ("Heal")) return $own->execute("Heal");
        if ($attack = $own->can_attack($foe)) return $own->execute($attack);
        if ($own->hp <= 50 && $own->can_do ("Heal")) return $own->execute("Heal");

        return 10 + $this->do_switch ($foe);
    }

    function choose_bonus()
    {
        foreach ($this->team->monster as $m)
        {
            if ($m->spd_b == 0) { $m->spd_b++; $res[] = 2; }
            else                { $m->def_b++; $res[] = 1; }
        }
        return implode (":", $res);
    }

    function parse ($parts)
    {
        self::parse_team ($parts[1], true);
        self::parse_team ($parts[2], false);
    }

    function analyze_last_round()
    {
        if ($this->results_pending)
        {
            $this->results_pending = false;

            $foes = $this->foes;
            $foe = null;
            foreach ($foes->monster as $m) if ($m->hp != $m->old->hp) $foe = $m;
            if ($foe === null) $foe = $foes->monster[$foes->active];

            $this->old_own->guess_attack($foe);
        }
    }

    function process ($line)
    {
        $parts = explode ("#", $line);
        switch ($parts[0])
        {
        case "T": // register for tournament
            echo "$this->name|$this->team";
            break;
        case "C": // designate active monster
            $this->parse ($parts);
            echo $this->choose_active();
            break;
        case "A": // choose round action
            $this->parse ($parts);
            echo $this->choose_action();

            // save current state
            foreach (array($this->team, $this->foes) as $t)
            foreach ($t->monster as $m)
            {
                unset ($m->old);
                $m->old = clone ($m);
            }
            $this->results_pending = true;
            break;
        case "B": // distribute stat bonus
            echo $this->choose_bonus();
            break;
        }

    }
}
G::init();

// ============================================================================
// Move
// ============================================================================
class Move {
    function __construct ($move)
    {
        $this->register($move);
    }

    function register ($move)
    {
        $this->type = G::$decode_move[$move];
        $this->reinit();
    }

    function reinit()
    {
        $this->uses = G::$move_uses[$this->type];
    }

    function __tostring() { return G::$code_move[$this->type]."($this->uses)"; }
}

// ============================================================================
// Monster
// ============================================================================
class Monster {
    function __construct ($name="?", $type="?", $atk=100, $def=100, $spd=100, $m0="?", $m1="?", $m2="?")
    {
        $this->name = $name;
        $this->type = G::$decode_type[$type];
        $this->atk  = $atk;
        $this->def  = $def;
        $this->spd  = $spd;
        $this->hp   = 100;
        $this->move = array (new Move($m0), new Move($m1), new Move($m2));
        $this->atk_b = 0;
        $this->def_b = 0;
        $this->spd_b = 0;
        foreach (G::$code_effect as $e) $this->$e = 0;
    }

    function __tostring ()
    {
        return implode (":", array (
            $this->name,
            $this->type,
            $this->atk,
            $this->def,
            $this->spd,
            $this->move[0]->type,
            $this->move[1]->type,
            $this->move[2]->type));
    }

    function start_round()
    {
        foreach ($this->move as $m) $m->reinit();
    }

    function parse_monster ($own_team, $spack)
    {
        $pack = explode (":", $spack);
        $name = array_shift ($pack); // get name
        array_shift ($pack); // skip id
        if ($this->name == "?") $this->name = $name; // get paranoid
        else if ($this->name != $name) die ("expected $this->name, got $name");

        // store updated values
        foreach (G::$status_field as $var) $this->$var = array_shift ($pack);
        if ($own_team)
        {
            foreach ($this->move as $m) $m->new_count = array_shift($pack);
            $pack = array_slice ($pack, 3); // these are maintained internally
        }
        $var = array();
        foreach ($pack as $e) @$var[G::$code_effect[$e]]++;
        foreach (G::$code_effect as $e) $this->$e = @$var[$e]+0;
    }

    function damage_recieved ($attack, $foe=null)
    {
        if ($attack == "self") $foe = $this;
        $a = G::$decode_move[$attack];
        $type = G::$move_type[$a];
        $dmg = g::$move_dmg[$a];

        if ($dmg == 0) return 0;

        $atk = ($foe ->atk+$foe ->atk_b) * pow (.8, ($foe ->Weaken - $foe ->Sharpen));
        $def = ($this->def+$this->def_b) * pow (.8, ($this->Sap    - $this->Shield ));

        $boost = ($foe->type == $type) ? 1.2 : 1;
        return max (floor ($dmg * $atk / $def * $boost * G::$damage_multiplier[$this->type][$type]), 1);
    }

    function guess_attack_from_effect ($attacks)
    {
        foreach ($attacks as $status) if ($this->$status != $this->old->$status) return $status;
        return "?";
    }

    function guess_attack_from_damage ($foe, $damages)
    {
        $select = array();
        foreach (G::$possible_moves[$foe->type] as $attack)
        {
            $dmg = $this->damage_recieved ($attack, $foe);
            foreach ($damages as $damage) if ($damage != 0 && abs ($dmg/$damage-1) < 0.1) $select[$attack] = 1;
        }
        $res = array();
        foreach ($select as $a=>$x) $res[] = $a;
        return $res;
    }

    function guess_attack ($foe)
    {
        $attempt = G::$decode_move[$this->old->attack];
        $success = ($this->old->attack == "pass");
        foreach ($this->move as $m)
        {
            if ($m->type == $attempt)
            {
                if ($m->new_count == $m->uses-1)
                {
                    $m->uses--;
                    $success = true;
                }
                break;
            }
        }

        $possible = array();
        $attack = $this->guess_attack_from_effect (array("Burn", "Confuse", "Poison", "Sleep", "Slow", "Weaken", "Sap"));
        if ($attack == "?") $attack = $foe->guess_attack_from_effect (array("Sharpen", "Shield"));
        if ($attack == "?")
        {
            $foe_damage = $this->old->hp - $this->hp - (10 * $this->Burn + 5 * $this->Pturns*$this->Poison);
            if ($this->old->attack == "Heal" && $success) $foe_damage += 50;
            $possible_dmg[] = $foe_damage;
            //;!;if ($this->Confuse) $possible_dmg[] = $foe_damage + $this->damage_recieved ("self");
            $possible = $this->guess_attack_from_damage ($foe, $possible_dmg);
            if (count ($possible) == 1) $attack = $possible[0];
        }
        if ($attack == "?")
        {
            $own_damage = $foe->old->hp - $foe->hp
                        - (10 * $foe->Burn + 5 * $foe->Pturns*$foe->Poison)
                        + $foe->damage_recieved ($this->attack);
            if (abs ($own_damage/50+1) < 0.1) $attack = "Heal";
        }
        if ($attack != "?")
        {
            $type = G::$decode_move[$attack];
            if ($attack != "?")
            {
                foreach ($foe->move as $m) if ($m->type == $type) goto found_old;
                foreach ($foe->move as $m) if ($m->type == 15) { $m->register($attack); goto found_new; }
            }
            found_new:
            found_old:
        }
    }

    function max_damage($foe)
    {
        $dmg = 0;
        foreach ($foe->move as $m) $dmg = max ($dmg, $this->damage_recieved (G::$code_move[$m->type], $foe));
        return $dmg;
    }

    function expected_damage ($foe)
    {
        return $this->max_damage($foe) + 10 * $this->Burn + 5 * ($this->Pturns+1);
    }

    function life_expectancy ($foe)
    {
        $hp = $this->hp;
        $poison = $this->Pturns;
        $heal = $this->can_do ("Heal");
        $dmg = $this->max_damage($foe);
        for ($turn = 0 ; $hp > 0 && $turn < 10; $turn++)
        {
            $hp -= 10 * $this->Burn + 5 * $poison;
            if ($poison > 0) $poison++;
            $hp -= $dmg;
            if ($hp <= 0 && $heal > 0) { $hp+=50; $heal--; }
        }
        return 100 * $turn + $this->hp;
    }

    function can_attack ($foe)
    {
        $attack = false;
        if ($this->hp > 0)
        {
            if      (!$foe->Poison  && $this->can_do ("Poison" )) $attack = "Poison";
            else if (!$foe->Confuse && $this->can_do ("Confuse")) $attack = "Confuse";
            else if (!$foe->Burn    && $this->can_do ("Burn"   )) $attack = "Burn";
        }
        $this->atk_score = ($attack === false) ? 0 : G::$atk_score[$attack];
        return $attack;
    }

    function can_do($move)
    {
        $type = G::$decode_move[$move];
        foreach ($this->move as $m) if ($m->type == $type && $m->uses > 0) return $m->uses;
        return false;
    }

    function execute($move)
    {
        $type = G::$decode_move[$move];
        foreach ($this->move as $i=>$m) if ($m->type == $type)
        {
            if ($m->uses > 0)
            {
//;!;               $m->uses--;
                $this->attack = $move;
            }
            else $this->attack = "pass";
            return $i;
        }
        die ("$this asked to perform $move, available ".implode(",", $this->move));
    }
}

// ============================================================================
// Team
// ============================================================================
class Team {
    function __construct ($members)
    {
        $this->monster = $members;
    }

    function __tostring()
    {
        return implode ("|", $this->monster);
    }

    function active ()
    {
        return $this->monster[$this->active];
    }

    function initial_opponent()
    {
        return $this->monster[0];
    }
}

// ============================================================================
// main
// ============================================================================
$input = $argv[1];

$team_name = "H3C";
$mem_file = "$team_name/memory.txt";
$trc_file = "$team_name/trace.txt";
if (!file_exists($team_name)) mkdir($team_name, 0777, true) or die ("could not create storage directory '$team_name'");
if ($input == "T") array_map('unlink', glob("$team_name/*.txt"));

if (file_exists($mem_file)) $game = unserialize (file_get_contents ($mem_file));
else
{
    $team = new Team (
        array (
            new Monster ("Handy" , "Grass" , 50, 99, 81, "Confuse", "Poison", "Heal"),
            new Monster ("Nutty" , "Fire"  , 50, 99, 81, "Burn"   , "Poison", "Heal"),
            new Monster ("Flippy", "Water" , 50, 99, 81, "Confuse" , "Burn" , "Heal")));
    $game = new G($team_name,$team);
}

$game->process ($input);
file_put_contents ($mem_file, serialize($game));

Results
LittleKid is still menacing, but my trio beat his venomous freaks by a fair margin.
Martin's bots are doomed by their lack of initiative, and increasing their speed would require to lower attack, which would blunt their edge in damage dealing capacity.
The new contenders from planet JavaScript are on par with the team in a one-on-one, but they fare worse against other competitors. They actually help decreasing LittleKid's score :).
So it seems my cuddly friends remain kings of the hill - for now...
170             H3C
158             Nodemon
145             LittleKid
55              InsideYourHead
42              HardenedTrio
30              BitterRivals

And I don't have PHP on mine either. I'd expect you to mop the floor with the Metapods though, since they go for a slow strat and would get poisoned to death.

...and burned to a crisp :D. That's the trouble with complicated rules: a dominant strategy is very likely to emerge. Since there is no protection against these spells, they might be codémon's fat man and little boy.

I'd compare it more to a non-transitive game like scissors, paper, rock — since effects take a while, a full-attack team should be able to take you down :)

Mmm... I hope so. That would make the game more interesting. These spells are outside the rock/paper/scissors logic though, so it's more a matter of which method produces more damage.

Yes, this is what I imagined as soon as I see no remedy for Poison and Burn. Thank you for bringing my dream to life.

I don't know what changed, but this bot now sometimes faults out, returning wtf?!? for a battle action (usually before 15 rounds have played). I'd like to wait for you and MezzoEmrys to get your bots fixed before running another official scoring.

That's Mr. Lumpy expressing his puzzlement when he detects more than 3 different attacks from the same adversary :). I have a fixed version nearly complete, but I'm in the middle of some other thing right now, so the fix will be posted in a day or so.

@Geobits OK, Mr. Lumpy should behave now. Sorry for the delay.

HardenedTrio, Python 3
Since Geobits was nice enough to give us two submissions, I thought I'd submit something silly for the first one :P
The party is three Codemon (Metapod1, Metapod2, Metapod3) with the same stats and moves:

80 attack, 100 defense, 50 speed
Punch, Heal, Shield Harden

All bonus points are also assigned to defense.

from collections import namedtuple
import sys

BattleState = namedtuple("BattleState", ["us", "them"])
TeamState = namedtuple("TeamState", ["name", "active", "members"])
MemberState = namedtuple("MemberState", ["name", "id", "attack", "defense", "speed", "hp",
                                         "typeid", "poisonedturns", "otherstats"])

def parse_battle_state(state):
    return BattleState(*map(parse_team_state, state.split("#")))

def parse_team_state(state):
    na, *members = state.split("|")
    name, active = na.split(":")
    return TeamState(name, int(active), list(map(parse_member_state, members)))

def parse_member_state(state):
    name, id_, attack, defense, speed, hp, typeid, poisonedturns, *rest = state.split(":")
    return MemberState(name, int(id_), float(attack), float(defense), float(speed),
                       float(hp), int(typeid), int(poisonedturns), rest)

command = sys.argv[1].strip()

if command.startswith("T"):
    print("HardenedTrio|Metapod1:0:80:100:50:0:1:11|"
          "Metapod2:0:80:100:50:0:1:11|Metapod3:0:80:100:50:0:1:11")

elif command.startswith("C"):
    battle_state = parse_battle_state(command[2:])

    for i, codemon in enumerate(battle_state.us.members):
        if codemon.hp > 0:
            print(i)
            break

elif command.startswith("A"):
    battle_state = parse_battle_state(command[2:])
    current_codemon = battle_state.us.members[battle_state.us.active]

    if current_codemon.hp < 50 and int(current_codemon.otherstats[1]) > 0:
        print(1) # Heal up if low

    elif int(current_codemon.otherstats[2]) > 0:
        print(2) # Harden!

    else:
        print(0) # Punch!

elif command.startswith("B"):
    print("1:1:1")

Run with
py -3 <filename>

(or with python/python3 instead of py depending on your installation)

What doesn't kill you, makes you harden.

@FryAmTheEggman Metapod, HARDEN!

I'm trying to read your code, but got confused at int(current_codemon.otherstats[1])>0.  That returns true if he has a status effect?  And he only uses harden if he has two status effects?

@MooingDuck For your Codemon you've got moveCounts before the effectids, so it's checking whether it can still use Harden. I got lazy with parsing, which is why it's lumped into there.

@Sp3000: Oh! Right! HAHAHA!

LittleKid, Java
A little kid found 3 identical codémons and trained them. They are very annoying with their heal+poison attacks. Using only normal-type codémons removes the need to pair them up against specific enemies, since poison works well against all types.
public class LittleKid {

    public static void main(String[] args) {
        if(args.length < 1){
            System.out.println("Geobits says you can't do this.");
            System.exit(0);
        }

        String[] sections = args[0].split("#");
        String me, them, out = "";
        switch(sections[0]){
            case "T":
                out = "LittleKid";
                out += "|Poisoner:0:80:100:50:0:1:13";
                out += "|Poisoner:0:80:100:50:0:1:13";
                out += "|Poisoner:0:80:100:50:0:1:13";
                break;
            case "B":
                out = "1:1:1";
                break;
            case "C":
                me = sections[1];
                them = sections[2];
                int pick = 0;

                if(!isAlive(me, pick)){
                    for(int i=0;i<3;i++){
                        if(isAlive(me,i))
                            pick = i;
                    }
                }

                out = String.valueOf(pick);
                break;
            case "A":
                me = sections[1];
                them = sections[2];
                int active = getActive(me);
                int enemyActive = getActive(them);
                if (getField(me, HP, active) < 50 && getField(me, MOVE1, active) != 0) {
                    out = "1";
                } else if (getEffectCount(them, POISON, enemyActive, false) < 1 && getField(me, MOVE2, active) != 0) {
                    out = "2";
                } else {
                    out = "0";
                }
                break;
            default:
                out = "Invalid query from controller.";
        }
        System.out.println(out);
    }

    static boolean isAlive(String teamState, int who){
        return getField(teamState, HP, who) > 0;
    }

    static int getActive(String teamState){
        return Integer.parseInt(teamState.split("\\|")[0].split(":")[1]);
    }

    static int getField(String teamState, int field, int who){
        String[] fields = teamState.split("\\|")[who+1].split(":");
        return Integer.parseInt(fields[field]);
    }

    static int getEffectCount(String teamState, int effect, int who, boolean mine){
            String[] fields = teamState.split("\\|")[who+1].split(":");
            int count = 0;
            for(int i=mine?14:8;i<fields.length;i++){
                if(Integer.parseInt(fields[i]) == effect)
                    count++;
            }
            return count;
    }

    final static int ID =       1;
    final static int ATTACK =   2;
    final static int DEFENSE =  3;
    final static int SPEED =    4;
    final static int HP =       5;
    final static int TYPE =     6;
    final static int MOVE0 =    8;
    final static int MOVE1 =    9;
    final static int MOVE2 =    10;

    final static int POISON =           1;
}

"Geobits says you can't do this" :D

Seems poison is the real A-bomb in this game :)

Inside Your Head, Ruby

Brian: Psychic, Attack: 100, Defence: 50, Speed: 80, Pain, Fireball, Watergun
Elemon1: Psychic, Attack: 100, Defence: 50, Speed: 80, Fireball, Watergun, Vine
Elemon2: Psychic, Attack: 100, Defence: 50, Speed: 80, Fireball, Watergun, Vine

TEAM_SPEC = "InsideYourHead"+
            "|Brian:1:100:50:80:3:6:9"+
            "|Elemon1:1:100:50:80:6:9:12"+
            "|Elemon2:1:100:50:80:6:9:12"

def parse_battle_state request
    request.map do |team_state|
        state = {}
        parts = team_state.split '|'
        state[:active] = parts.shift.split(':')[1].to_i
        state[:monsters] = parts.map do |monster_state|
            monster = {}
            parts = monster_state.split(':')
            monster[:name] = parts[0]
            monster[:hp] = parts[5].to_i
            monster[:type] = parts[6].to_i
            monster
        end
        state
    end
end

request = ARGV[0].split '#'
case request.shift
when 'T'
    puts TEAM_SPEC
when 'C'
    battle_state = parse_battle_state request
    my_state = battle_state[0]
    puts my_state[:monsters].find_index {|monster| monster[:hp] > 0}
when 'A'
    battle_state = parse_battle_state request
    my_state, their_state = *battle_state
    my_monster = my_state[:monsters][my_state[:active]]
    their_monster = their_state[:monsters][their_state[:active]]
    puts [1,0,1,2,0][their_monster[:type]]
when 'B'
    puts '0:0:0'
end

Run with
ruby InsideYourHead.rb

This doesn't work very well against Manu's bot, but it beats the other three. The team and monster names are pretty random... I might change them if I come up with something better
The strategy is pretty simple: attack! All three monsters only have pure attack moves, and they choose their move based on the opponent's monster's type.
I might experiment with throwing in a Heal later.

Hehe this becomes more interesting. I knew I could count on you for that, Martin :)

Nodémon - Javascript
Since status appears to be the dominant strategy, this team focuses on speed to get statuses like poison and confusion onto the opponents first, and then stalls out with heal and/or sleep while the opponent wastes away.
I don't have PHP installed so this isn't tested against the Campers, but it seems to be a decent competitor for LittleKid in my trials (and decimates Bitter Rivals).
/*jshint node:true*/
'use strict';

var fs = require('fs');

var dataFile = 'Nodemon/data.json';
function getData(callback) {
  fs.readFile(dataFile, 'utf8', function(err, contents) {
    var data = {round: 0};

    if(!err) {
      data = JSON.parse(contents);
    }

    callback(data);
  });
}

function saveData(data, callback) {
  fs.mkdir('Nodemon', function() {
    fs.writeFile(dataFile, JSON.stringify(data), callback);
  });
}

var effect = {
  poison: '1',
  confusion: '2',
  burn: '3',
  sleep: '4',
  heal: '5',
  attackUp: '6',
  attackDown: '7',
  defenseUp: '8',
  defenseDown: '9',
  speedDown: '10'
};

function parseMemberCommon(args) {
  return {
    name: args[0],
    id: args[1],
    baseAttack: +args[2],
    baseDefense: +args[3],
    baseSpeed: +args[4],
    hp: +args[5],
    typeId: args[6],
    poisonedTurns: +args[7],
    effects: args.slice(8)
  };
}

function parseOwnMember(arg) {
  var args = arg.split(':');

  var ownArgs = args.splice(8, 6);

  var member = parseMemberCommon(args);

  member.moveCount = [
    +ownArgs[0],
    +ownArgs[1],
    +ownArgs[2]
  ];

  member.bonusAttack = +ownArgs[3];
  member.bonusDefense = +ownArgs[3];
  member.bonusSpeed = +ownArgs[3];

  return member;
}

function parseOpponentMember(arg) {
  return parseMemberCommon(arg.split(':'));
}

function parseTeamStateCommon(arg, memberParse) {
  var args = arg.split(':');
  var state = {
    name: args[0],
    members: []
  };
  args = arg.substring(state.name.length + 1).split('|');
  var activeSlot = args[0];
  for(var index = 1; index < args.length; index++) {
    state.members.push(memberParse(args[index]));
  }
  state.activeMember = state.members[activeSlot];
  return state;
}

function parseOwnState(arg) {
  return parseTeamStateCommon(arg, parseOwnMember);
}

function parseOpponentState(arg) {
  return parseTeamStateCommon(arg, parseOpponentMember);
}

function parseBattleState(arg) {
  var args = arg.split('#');
  return {
    own: parseOwnState(args[0]),
    opponent: parseOpponentState(args[1])
  };
}

function teamData() {

  saveData({round:0}, function() {
    console.log('Nodemon|' +
      'Charasaur:0:50:80:100:10:13:1|' +
      'Bulbtortle:4:50:80:100:10:13:1|' +
      'Squirtmander:1:50:80:100:10:13:4');
  });
}

function getActiveIndex(battleState) {
  for(var index = 0; index < battleState.own.members.length; index++) {
    var member = battleState.own.members[index];
    if(member.hp > 0) {
      return index;
    }
  }
}

function chooseActive(arg) {
  var battleState = parseBattleState(arg);

  getData(function(data) {
    var allFull = true;
    for(var index = 0; index < battleState.opponent.members.length; index++) {
      var member = battleState.opponent.members[index];
      if(!data.maxSpeed || member.baseSpeed > data.maxSpeed) {
        data.maxSpeed = member.baseSpeed;
      }
      if(member.hp < 100) {
        allFull = false;
      }
    }

    if(allFull) {
      data.round++;
    }

    saveData(data, function() {
      console.log(getActiveIndex(battleState));
    });
  });
}

function useMove(moves, battleState) {
  var fighter = battleState.own.activeMember;

  for(var moveIndex = 0; moveIndex < moves.length; moveIndex++) {
    var move = moves[moveIndex];
    if(fighter.moveCount[move]) {
      return move;
    }

    for(var memberIndex = 0; memberIndex < battleState.own.members.length; memberIndex++) {
      var member = battleState.own.members[memberIndex];

      if(member.hp > 0 && member.moveCount[move] > 0) {
        return 10 + memberIndex;
      }
    }
  }

  return -1;  //do nothing
}

function battleAction(arg) {
  var battleState = parseBattleState(arg);

  var fighter = battleState.own.activeMember;
  var opponent = battleState.opponent.activeMember;

  var attemptedMoves = [];

  if(opponent.effects.indexOf(effect.poison) === -1) {
    attemptedMoves.push(1);
  }

  if(opponent.effects.indexOf(effect.confusion) === -1) {
    attemptedMoves.push(0);
  }

  if(fighter.name === 'Squirtmander') {
    //sleep
    if(opponent.effects.indexOf(effect.sleep) === -1) {
      attemptedMoves.push(2);
    }
  }
  else {
    //heal
    if(fighter.hp <= 60) {
      attemptedMoves.push(2);
    }
  }

  console.log(useMove(attemptedMoves, battleState));
}

function bonusStats(arg) {
  var teamState = parseOwnState(arg);

  getData(function(data) {
    var result = '1:';

    if(data.round % 4 === 0) {
      result += '1:';
    }
    else {
      result += '2:';
    }
    if(teamState.members[2].baseSpeed + teamState.members[2].bonusSpeed > data.maxSpeed + (data.round / 2)) {
      result += '1';
    }
    else {
      result += '2';
    }
    console.log(result);
  });
}

var actions = {
  'T': teamData,
  'C': chooseActive,
  'A': battleAction,
  'B': bonusStats
};

var arg = process.argv[2];
actions[arg[0]](arg.substring(2));

Run with
node nodemon
P.S. Apologies to nodemon.

This is escalating to a server-side script global war :D

Bitter Rivals - Java
A Grass/Fire/Water team that likes to switch it up.
Greenosaur
Has at least neutral coverage on anyone. High speed to make up for lack of defense.
Type: Grass
Attack:   80     Vine
Defense:  50     Punch
Speed:   100     Pain

Searizard
Tries to Sap enemies with with low attack. Burns and Fireballs after that.
Type: Fire
Attack:  100     Fireball
Defense:  50     Burn
Speed:    80     Sap

Blastshield
Uses Shield to enhance its already high defense. Heals when necessary.
Type: Water
Attack:   80     Watergun
Defense: 100     Shield
Speed:    50     Heal

Code
This is also included with the controller. This is a competing team, unlike DummyTeam. The command needed for players.conf is:
java BitterRivals

public class BitterRivals {

    public static void main(String[] args) {
        if(args.length < 1){
            System.out.println("You're not doing this right. Read the spec and try again.");
            System.exit(0);
        }

        String[] sections = args[0].split("#");
        String me, them, out = "";
        switch(sections[0]){
            case "T":
                out = "BitterRivals";
                out += "|Greenosaur:4:80:50:100:12:0:3";
                out += "|Searizard:2:100:50:80:6:7:14";
                out += "|Blastshield:3:80:100:50:9:11:1";
                break;
            case "B":
                out = "2:0:1";
                break;
            case "C":
                me = sections[1];
                them = sections[2];

                int pick = 0;
                switch(getField(them, TYPE, getActive(them))){
                    case 0:
                    case 1:
                    case 3:
                        pick = 0;
                        break;
                    case 2:
                        pick = 2;
                        break;
                    case 4:
                        pick = 1;
                        break;
                }

                if(!isAlive(me, pick)){
                    for(int i=0;i<3;i++){
                        if(isAlive(me,i))
                            pick = i;
                    }
                }

                out = pick + "";
                break;
            case "A":
                me = sections[1];
                them = sections[2];
                int active = getActive(me);
                int oType = getField(them, TYPE, getActive(them));
                switch(active){
                    case 0:         // Greenosaur
                        switch(oType){
                            case 0:
                            case 4:
                                out = "1";
                                break;
                            case 1:
                                out = "2";
                                break;
                            case 3:
                                out = "0";
                                break;
                            case 2:
                                if(isAlive(me, 2)){
                                    out = "12";
                                } else if(isAlive(me, 1)){
                                    out = "11";
                                } else {
                                    out = "1";
                                }
                                break;
                        }
                        break;
                    case 1:         // Searizard
                        if(oType == 3){
                            if(isAlive(me, 0)){
                                out = "10";
                                break;
                            } else if(isAlive(me, 2)){
                                out = "12";
                                break;
                            }
                            if(getEffectCount(them, BURN, getActive(them), false) < 1 && getField(me, MOVE1, active) > 0){
                                out = "1";
                            } else if(getField(me, MOVE2, active) > 0){
                                out = "2";
                            } else {
                                out = "3";
                            }
                        } else {
                            if(getField(them, ATTACK, getActive(them)) < 80){
                                if(getEffectCount(them, DEFENSE_DOWN, getActive(them), false) < 1 && getField(me, MOVE2, active) > 0){
                                    out = "2";
                                    break;
                                } else if(getEffectCount(them, BURN, getActive(them), false) < 1 && getField(me, MOVE1, active) > 0){
                                    out = "1";
                                    break;
                                }
                            }
                            out = "0";
                        }
                        break;
                    case 2:         // Blastshield
                        if(oType == 4){
                            if(isAlive(me, 1)){
                                out = "11";
                                break;
                            } else if(isAlive(me, 0)){
                                out = "10";
                                break;
                            }
                        }
                        if(getField(me, HP, active) < 50 && getField(me, MOVE2, active) > 0){
                            out = "2";
                        } else if(getEffectCount(me, DEFENSE_UP, active, true) < 3 && getField(me, MOVE1, active) > 0){
                            out = "1";
                        } else {
                            out = "0";
                        }
                        break;
                }
                break;
            default:
                out = "Invalid query from controller.";
        }
        System.out.println(out);
    }

    static boolean isAlive(String teamState, int who){
        return getField(teamState, HP, who) > 0;
    }

    static int getActive(String teamState){
        return Integer.parseInt(teamState.split("\\|")[0].split(":")[1]);
    }

    static int getField(String teamState, int field, int who){
        String[] fields = teamState.split("\\|")[who+1].split(":");
        return Integer.parseInt(fields[field]);
    }

    static int getEffectCount(String teamState, int effect, int who, boolean mine){
            String[] fields = teamState.split("\\|")[who+1].split(":");
            int count = 0;
            for(int i=mine?14:8;i<fields.length;i++){
                if(Integer.parseInt(fields[i]) == effect)
                    count++;
            }
            return count;
    }

    final static int ID =       1;
    final static int ATTACK =   2;
    final static int DEFENSE =  3;
    final static int SPEED =    4;
    final static int HP =       5;
    final static int TYPE =     6;
    final static int PTURNS =   7;
    final static int MOVE0 =    8;
    final static int MOVE1 =    9;
    final static int MOVE2 =    10;
    final static int HA =       11;
    final static int HD =       12;
    final static int HS =       13;

    final static int POISON =           1;
    final static int CONFUSION =        2;
    final static int BURN =             3;
    final static int SLEEP =            4;
    final static int ATTACK_UP =        6;
    final static int ATTACK_DOWN =      7;
    final static int DEFENSE_UP =       8;
    final static int DEFENSE_DOWN =     9;
    final static int SPEED_DOWN =       10;
}

Error 310 : Too Many Redirects - C++
A highly trained and organized team to counter the ravages of poison
For three weeks, I hardly trained my codémons. I formed several teams. And finally, I am ready to face this challenge.
To answer all my poisoner opponents, I formed a team with very different codémons, each with a specific role.

Antidote
Type : Normal - atk:50 def:100 spd:80 - Poison/Burn/Heal
Antidote loves poison. So much so that I can't stop him from rushing to poison attacks.

Zen
Type : Fire - atk:100 def:80 spd:50 - Poison/Vine/Heal
Zen is a very surprising codémon which accommodates with all effects. He prefers to watch his enemies strive and exhaust against his silence.

Triforce
Type : Psychic - atk:88 def:60 spd:82 - Fireball/Watergun/Vine
Triforce is a classic codémon, always ready to fight. This one uses his psychic force to control the three elements and inflict as much damages as possible.

You can download the team here :
Linux :
http://dl.free.fr/iHYlmTOQ2
launch with ./Error310TMR
Windows :
http://dl.free.fr/vCyjtqo2s
launch with ./Error310TMR.exe
The code is a complete c++ project. I don't know how to publish it.
$ wc -l src/*
    165 src/BruteForce.cpp
     26 src/BruteForce.h
    349 src/Codemon.cpp
     77 src/Codemon.h
     21 src/Logger.cpp
     35 src/Logger.h
    105 src/NoTimeToExplain.cpp
     27 src/NoTimeToExplain.h
    240 src/Recoverator.cpp
     31 src/Recoverator.h
     26 src/StrManip.cpp
     16 src/StrManip.h
    303 src/Team.cpp
     68 src/Team.h
     88 src/TooManyRedirects.cpp
     24 src/TooManyRedirects.h
     87 src/Unrecoverable.cpp
     27 src/Unrecoverable.h
     59 src/enums.cpp
    119 src/enums.h
     68 src/main.cpp
   1961 total

But it is very effective :
------- Final Results -------

176     Error310TMR
131     H3C
130     LittleKid
121     Nodemon
58      InsideYourHead
47      HardenedTrio
37      BitterRivals

FairyTale
A fairly generic middle-of-the-road team. Based on three archetypes who try to do their thing, and switch out if they can't do their thing at all.
This team was created before it seemed like poison was the new meta, I haven't really been keeping up with changing my team since I originally made it, most of the time was spent just trying to get the parsing down. I haven't been able to get the Tournament running yet to test it, but it's been a pretty busy week. If this one doesn't actually work like it seems to with my test data, I'll apply some more shine to it after work.
#!/bin/perl
use 5.20.0;
use strict;

use constant MINE => 0;
use constant THEIRS => 1;

$_ = $ARGV[0];

if(/^T/){
    say 'FairyTale|Fairy:1:89:90:51:3:4:13|Dragon:2:100:50:80:6:1:8|Assassin:0:70:60:100:0:1:10';

} elsif(/^C#(.*)/){
    my $state = readBattleState($1);
    if($state->[MINE]->{$state->[MINE]->{slot}}{hp}){
        say $state->[MINE]->{slot};
    } elsif($state->[MINE]->{($state->[MINE]->{slot}+1)%3}{hp}){
        say (($state->[MINE]->{slot}+1)%3);
    } else {
        say (($state->[MINE]->{slot}+2)%3);
    }

} elsif(/^A#(.*)/){
    my $state = readBattleState($1);
    my @actives = (
        $state->[MINE]->{$state->[MINE]->{slot}},
        $state->[THEIRS]->{$state->[THEIRS]->{slot}}
    );
    if($state->[MINE]->{slot} == 0){
        if(!exists($actives[THEIRS]{effects}{4}) && $actives[MINE]{pp}->[1]){
            say 1;
        } elsif(!exists($actives[THEIRS]{effects}{1}) && $actives[MINE]{pp}->[2]) {
            say 2;
        } elsif(!$actives[THEIRS]{type}) {
            if($state->[MINE]->{($state->[MINE]->{slot}+1)%3}{hp} > 0){
                say (($state->[MINE]->{slot}+1)%3);
            } elsif($state->[MINE]->{($state->[MINE]->{slot}+2)%3}{hp} > 0) {
                say (($state->[MINE]->{slot}+2)%3);
            } else {
                say 0;
            }
        } else {
            say 0;
        }
    } elsif($state->[MINE]->{slot} == 1){
        if(!exists($actives[MINE]{effects}{6}) && $actives[MINE]{pp}->[2]){
            say 2;
        } elsif ($actives[MINE]{hp} > 10 && $actives[MINE]{hp} < 50 && $actives[MINE]{pp}->[1]){
            say 1;
        } else {
            say 0;
        }
    } elsif($state->[MINE]->{slot} == 2){
        if(!exists($actives[MINE]{effects}{6}) && $actives[MINE]{pp}->[2]){
            say 2;
        } elsif ($actives[MINE]{hp} > 10 && $actives[MINE]{hp} < 50 && $actives[MINE]{pp}->[1]){
            say 1;
        } elsif($actives[THEIRS]{type} == 1) {
            if($state->[MINE]->{($state->[MINE]->{slot}+1)%3}{hp} > 0){
                say (($state->[MINE]->{slot}+1)%3);
            } elsif($state->[MINE]->{($state->[MINE]->{slot}+2)%3}{hp} > 0) {
                say (($state->[MINE]->{slot}+2)%3);
            } else {
                say 0;
            }
        } else {
            say 0;
        }
    }

} elsif(/^B#(.*)/){
    my $state = readTeam($1, 1);
    say '1:0:2';
}

sub readBattleState {
    local $_ = $_[0];
    if(/^(.*?)#(.*?)$/){
        my @teams;
        $teams[0] = readTeam($1, 1);
        $teams[1] = readTeam($2, 0);
        return \@teams;
    }
}

sub readTeam {
    my $isMine = $_[1];
    local $_ = $_[0];
    if(/.*?:(?<slot>.*?)\|(.*?)\|(.*?)\|(.*?)$/){
        my %team;
        $team{slot} = $1;
        $team{0} = $isMine ? readYourMember($2) : readTheirMember($2);
        $team{1} = $isMine ? readYourMember($3) : readTheirMember($3);
        $team{2} = $isMine ? readYourMember($4) : readTheirMember($4);
        return \%team;
    }
    return 0;
}

sub readYourMember {
    local $_ = $_[0];
    if(/(?<name>.*?):(?<id>.*?):(?<atk>.*?):(?<def>.*?):(?<spd>.*?):(?<hp>.*?):(?<type>.*?):(?<poison>.*?):(?<move0>.*?):(?<move1>.*?):(?<move2>.*?):(?<batk>.*?):(?<bdef>.*?):(?<bspd>.*?)(?<effects>(?::.*)|$)/){
        my %effects = map { $_ => 1 } readEffects($+{effects});
        my %member = (
            name   => $+{name},
            id     => $+{id},
            hp     => $+{hp},
            atk    => $+{atk}+$+{batk},
            def    => $+{def}+$+{bdef},
            spd    => $+{spd}+$+{bspd},
            type   => $+{type},
            pp     => [$+{move0}, $+{move1}, $+{move2}],
            poistrn=> $+{poison},
            effects=> \%effects
        );
        return \%member;
    }
}

sub readTheirMember {
    local $_ = $_[0];
    if(/(?<name>.*?):(?<id>.*?):(?<atk>.*?):(?<def>.*?):(?<spd>.*?):(?<hp>.*?):(?<type>.*?):(?<poison>.*?)(?<effects>(?::.*)|$)/){
        my %effects = map { $_ => 1 } readEffects($+{effects});
        my %member = (
            name   => $+{name},
            id     => $+{id},
            hp     => $+{hp},
            atk    => $+{atk},
            def    => $+{def},
            spd    => $+{spd},
            type   => $+{type},
            poistrn=> $+{poison},
            effects=> \%effects
        );
        return \%member;
    }
    return 0;
}

sub readEffects {
    local $_ = $_[0];
    my @retval = /:([^:]*)/g;
    if(!@retval){
        @retval = (0);
    }
    return @retval;
}

Run with
perl fairytale.pl

This bot gets kicked out for trying to 'choose active' dead members after the first dies. It never gets past the first battle that I can see.

Really? I thought I had gotten that bug worked out before, maybe this is an older version of that code...

Dont forget that when a codemon is knocked out, his healpoints decrease at 0 or less. So the if($state->[MINE]->{$state->[MINE]->{slot}}{hp}) statement will not work correctly without >0.

Ah, yeah, that would do it.

Dummy Team - Java
(non-competing CW)
This is a dummy team to practice on. It's all normal types, which choose randomly between their moves (Punch, Heal, Slow) each turn. Have fun with it.
public class DummyTeam {

    public static void main(String[] args) {
        if(args.length < 1){
            System.out.println("You need to run this from the tournament. Try to keep up.");
            System.exit(0);
        }

        String[] sections = args[0].split("#");
        String out = "";
        switch(sections[0]){
            // team data
            //      sends back all Normal types with minimum stats and Normal moves (randomized name suffixes to distinguish in tests)
            case "T":
                out = "DummyTeam";
                for(int i=0;i<3;i++)
                    out += "|Dummy"+((char)(Math.random()*26)+65) + i + ":0:50:50:50:0:1:2";
                break;
            // bonus points
            //      shoves them all in defense every time
            case "B":
                out = "1:1:1";
                break;
            // choose active
            //      picks last active if alive, otherwise loops to find first living member
            case "C":
                String[] team = sections[1].split("\\|");
                int current = Integer.parseInt(team[0].split(":")[1]);
                if(Integer.parseInt(team[current+1].split(":")[5]) > 0){
                    out = current + "";
                } else {
                    for(int i=1;i<team.length;i++){
                        if(Integer.parseInt(team[i].split(":")[5]) > 0){
                            out = (i - 1) + "";
                        }
                    }
                }
                break;
            // choose action
            //      chooses a random move. does not check if it ran out of uses, so wastes turns quite often
            case "A":
                out = ((int)(Math.random()*3)) + "";
                break;
            default:
                out = "Invalid query from controller.";
        }
        System.out.println(out);
    }

}


text:
Is this even a word?
Your should write a program or function that takes a 4-character string as input and outputs a value indicating if the string is an English word or not. You are allowed to make mistakes in 15% of the provided testcases.
Input details:
Input is a 4-character string containing only the lowercase English letters (a-z).
Output details:
If the input is an English word you should output a boolean true or an integer 1.
If the input isn't an English word you should output a boolean false or an integer 0.
Word lists
list of 4-letter English words (2236 words)
list of 4-letter non-word strings (2236 strings)
The non-word list contains uniformly randomly generated letter sequences with the real words removed from them.
Testing
Your program or function should make no more than 15% mistakes on the given word lists together. That means you can give wrong output for 670 of the 4472 provided inputs.
You should post the testing program or function too so others could check your answer. The length of your testing program doesn't count into your submissions score.
Standard loopholes are disallowed.
Your program shouldn't use any external sources e.g. accessing web or reading from file.
This is code-golf so the shortest program or function wins.

... so If I just read your words file into an array and a for-each match on input and break on true, that would satisfy your requirements (and be 100% correct for provided inputs)? Or were you looking for an algorithm?

That array has to be part of the code. (I guess). @randomra - care mentioning that you cannot read/access the word list from anywhere..

Edited to clarify.

@BryanDevaney you should only hard code 85% of the list

Would using the clipboard be "using external resources or reading a file"?

@TeunPronk Yes.

@randomra ah well. It was worth a try since it's not in the loopholes xD

@dwana Just a FYI for those implementing. 85% is a-s. you can safely disgard all inputs starting t-z.

It's so easy even a monkey could do it

A few answers so far have demonstrated that this is basically probabilistic regex golf. Does it really make sense to keep this as code golf with full program source instead of a regex?

@Sparr There's still other ways to do the problem, like in this question

"Is this even a word?" Yes. [<- 4 chars]

"Is this even a word?" All evens are words, therefore the italic one is a word.

Ruby, 29 bytes
->s{!s[/[^aeiou]{3}|[jqxz]/]}

Hopefully I've got this right - it's my first time programming in Ruby. I actually did all my testing in Python, but import re was far too long for me.
This is an anonymous function which takes in a string and outputs true/false accordingly. It uses a regex which looks for one of the following two things:

Three consonants in a row
Contains one of jqxz

If either of these are present, we classify the input as not a word.
The function matches 2030 words (incorrectly failing on 206) and fails on 1782 non-words (incorrectly matching 454), for a total of 660 misclassifications. Tested on ideone.
Thanks to @MartinBüttner for the Ruby help. Martin also points out that a full program takes the same number of bytes:
p !gets[/[^aeiou]{3}|[jqxz]/]

Also thanks to user20150203 for simplifying the regex.

Ruby, 1586 1488 1349 1288 1203 bytes
For a bonus, here's a function with a much longer regex:
->s{!s[/[^aeiouyhs]{3}|[^aeiouy]{4}|q[^u]|^x|^[bdf][^aeioulry]|^[cgkprtwy][mfdsbktjgxpc]|^a[aoz]|^e[hf]|^i[ea]|^o[ecy]|^u[^ltnspgr]|[bdgktyz][cgmpw]$|[fhpvx][^aieoflnrsty]$|eh$|i[iyh]|[wkybp]z|[dghz]t|[fjzsv]y.|h[ns].|ae.|y.?[yifj]|[ejo]..[iuw]|[inv]..[gpuvz]|[eu].[jqwx]|[vyz][^t][fhmpqy]|i[^ae][fjqrv]|[ospen].?j|[ceg][iuy][ghkoux]|[bcpx]f|[hnuy]w|[ghnw]b|[txz]n|[jk]r|.[fjuyz]u|[hnt]ia|lsy|.p.o|.l.l|.tas|zal|f.p|eeb|wei|.sc.|.pl|yat|hov|hab|aug|v.re|aba|ohu|ned|s.dd|uc$|nux|oo$|dgo|lix|wua|v.o|vo$|ryo|wue|dk|oic|yol|.tr|yrb|oba|ruh|c.ls|idd|chn|doy|ekh|tk|lke|asl|cir|eez|asc|uil|iou|m..p|awt|irp|zaa|td|swk|ors|phe|aro|yps|q.e|ati|ibt|e.mo|we.y|p.de|ley|eq|tui|e..g|sps|akh|dny|swr|iul|.t.t|.tao|rcy|.p.y|idi|j.o|.kl|oms|ogi|jat|.lis|mye|uza|rsi|.ala|ibo|ipi|yaa|eun|ruy|wog|mm$|oex|koi|uyn|.hid|osc|ofe|w.op|auc|uzy|yme|aab|slm|oza|.fi|bys|z.e|nse|faf|l.h|f.va|nay|hag|opo|lal|seck|z.b|kt|agl|epo|roch|ix.|pys|oez|h.zi|nan|jor|c.ey|dui|ry.d|.sn|sek|w.no|iaz|ieb|irb|tz.|ilz|oib|cd|bye|ded|f.b|if$|mig|kue|ki.w|yew|dab|kh.|grs|no.t|cs.|.n.m|iea|y.na|vev|eag|el[uz]|eo[dkr]|e[hlsu]e|e[dho]l|eov|e[adp]y|r[grt]u|yn[klo]|.[^ilv].v|s[bdgqrz]|m[dfghrz]|[vpcwx]{2}|^[hjlmnvz][^aeiouy]|^[drw]l|l[hnr]/]}

I wanted to show that regex can still beat compression, so this one classifies every given case correctly. The regex itself is a bit like exponential decay — the first bits match a lot of non-words, then every bit after matches fewer and fewer until I gave up and just concatenated the rest (about 200 or so) at the end. Some of the ones that were left looked surprisingly like real words (such as chia which is a word).
I threw the regex at my regex golf cleaner which I wrote for another challenge — it golfed about 300 bytes before I had to try shuffling things around manually. There's still a fair bit to be golfed though.

user20150203 (lacking the rep to comment) suggested the following in an edit which I rejected based on this discussion: "Edit by a new user without reputation: ->s{!s[/[^aeiou]{3}|[jqxz]/]} has only 29 bytes and matches 2030 words (incorrectly failing on 206) and fails on 1782 non-words (incorrectly matching 454), for a total of 660 misclassifications."

That's weird, I thought I'd tested removing each char - must have forgotten about v. Thanks user20150203!

@Sp3000 Do you grant me authorization to use your regex in an answer for me? I will credit you with reputation (if possible) and all credits will be pointed out in the answer.

@IsmaelMiguel Is it just a language where it's much shorter to write a function for a regex match? If so I admit I'm a little curious... (so I can steal it for next time!)

@Sp3000 It isn't shorter. But I just want to post something. Has been a long time since I posted anything here anyway. And it will expand my knowledge a little. So, it's a win-win situation for me. And I will grant you some reputation, if possible, so, it's a win for you too (possibly).

@Alex I don't understand the reference... Can you explain, please?

@Alex Depending on how many years ago, I didn't even had internet. Or knew how to watch videos. I will watch it later. Thanks for explaining.

Groovy, 77 74
x={it==~/^(?!.+[jq]|[^aeiou][^aeiouhlr]|.[^aeiouy]{3}|.[x-z])|^s[cknptw]/}

I wrote the test program in Java, which you can find in this Gist on Github. Here is the output from my test program:
Good: 2135 1708
Bad: 101 528

(Failed 629 test cases)
P.S. I think this is going to end up a regex golf problem extremely soon...
If Sp3000's answer (the function) is to be converted to Groovy, it will end up with the same character count. As named function:
x={it!=~/[^aeiou]{3}|[jqxz]/}

or unnamed function:
{i->i!=~/[^aeiou]{3}|[jqxz]/}

it can only fail 335 cases ;) but still pretty neat though

this feels so wrong, yet it works ^^

@TeunPronk: (2236+2236) * 0.15 = 670.8. so you can fail 670. I think you have forgotten about classifying the non-words correctly. "Your program or function should make no more than 15% mistakes on the given word lists together." (emphasis mine)

@NeilSlater Aah, Yup, I only considered the correct ones. My bad ^^

Javascript, 1626 bytes:
I wanted to go for a solution which for each character has a clue of which one might come after. Not that short, but no regex and a fairly good result (words: 101 mistakes, non-words, 228 mistakes)
v=function(w){var g={a:{b:3,c:4,d:4,m:6,f:1,r:14,g:4,i:6,x:2,k:2,l:10,n:12,s:6,p:4,t:7,u:2,v:3,w:3,y:3,h:1,z:1},b:{b:3,a:19,e:19,y:3,l:6,o:17,u:12,i:9,s:9,r:6},e:{d:7,l:8,t:4,s:10,n:11,e:10,r:10,c:2,x:2,w:4,a:13,f:1,p:2,g:2,v:1,b:1,m:3,u:1,i:1,k:1,y:2},l:{e:16,y:5,a:16,b:1,f:2,l:12,m:2,o:14,p:1,s:2,u:8,d:4,i:10,k:3,t:5},o:{s:7,g:3,e:3,k:3,n:10,m:4,p:5,w:6,b:3,c:2,t:6,a:5,d:5,h:1,i:2,l:8,o:9,r:8,u:4,y:2,v:2,z:1,f:2,x:1},u:{t:8,e:5,m:7,s:11,a:2,n:13,r:15,d:6,c:4,f:1,g:5,l:9,y:1,z:1,b:5,j:1,x:1,p:2,k:1,i:2},c:{e:9,h:12,i:2,r:6,t:3,o:20,k:15,a:16,l:6,u:8,y:1},h:{e:21,r:2,a:22,i:15,o:20,u:15,n:3,l:1,y:1},i:{d:8,m:5,n:18,r:7,a:2,s:8,v:2,l:13,t:10,b:1,e:6,k:2,p:5,g:3,c:6,o:2,f:2,z:1},m:{e:19,s:8,a:21,i:12,m:1,o:15,y:2,b:4,p:8,n:1,u:8},n:{e:18,u:3,a:9,d:10,n:4,o:7,s:11,t:11,g:10,k:6,i:5,y:2,c:1},r:{e:18,s:4,y:4,a:16,c:1,g:1,i:12,m:3,p:2,t:4,b:1,d:4,k:4,n:5,r:2,o:11,l:2,u:6,f:1},t:{a:14,s:17,e:18,i:9,o:15,h:10,t:3,y:2,c:1,z:1,u:5,r:5,w:2},d:{a:14,d:4,s:10,e:22,y:8,i:12,o:14,r:4,u:10,l:1},f:{a:16,f:6,e:12,y:1,i:14,l:13,o:16,r:7,u:7,t:7,n:1,s:1},g:{a:16,e:12,o:17,u:7,s:18,g:1,y:2,i:8,l:4,n:2,h:3,r:9,w:1},j:{a:25,i:7,e:14,o:25,u:29},k:{i:23,s:6,e:41,u:6,a:10,l:2,n:8,o:2,h:1,y:1},p:{s:12,e:20,a:19,y:2,i:13,t:2,u:10,l:5,o:13,r:4},s:{o:8,i:8,e:13,k:6,h:10,s:8,t:14,y:1,p:5,c:2,l:6,a:10,m:1,n:2,u:4,w:2},v:{a:18,e:47,i:22,o:8,y:6},y:{l:4,e:18,s:20,d:3,n:8,r:8,t:4,a:14,k:1,m:1,o:8,x:3,p:3,u:4,v:1},q:{u:100},w:{a:24,e:17,l:4,r:3,s:10,n:6,y:2,k:1,d:1,t:1,i:17,u:1,o:10,h:4},x:{e:35,i:18,l:6,o:6,a:6,t:12,y:18},z:{z:10,y:10,a:3,e:43,r:3,o:17,i:10,u:3}},p=1,x,y,i=0;for(;i<3;){x=w[i],y=w[++i];p*=g[x]&&g[x][y]||0}return p>60}

Here's a working implementation http://fiddle.jshell.net/jc73sjyn/
In short: the Object g holds the characters from a to z (as keys), and for each of them, there is a set of characters (also as keys) that each represent a character that may come after, along with its probability percentage. Where no object exists, there is no probability.
The 3 scores (4 letters -> 3 evaluations) are multiplied, and a word with a score of 60 and above is considered a real word.
Example: for the word 'cope' there are three lookups:
g[c][o] = 20
g[o][p] = 5
g[p][e] = 20
score = 20 * 5 * 20 = 2000, which is more than 60, so that one is valid.
(I'm quite new with javascript, so there might be ways to make it shorter that I don't know of.)
LATE EDIT:
Completely irrelevant by now, but I evaluated my way to a more correct g:
g={a:{b:7,c:4,d:4,m:6,f:2,r:14,g:4,i:6,x:2,k:2,l:10,n:12,s:6,p:4,t:7,u:2,v:3,w:12,y:3,h:1,z:1},b:{b:10,a:19,e:19,y:3,l:6,o:17,u:10,i:9,s:9,r:3},e:{d:7,l:8,t:4,s:10,n:11,e:10,r:10,c:2,x:2,w:4,a:13,f:1,p:2,g:2,v:20,b:3,m:3,u:1,i:1,k:1,y:2},l:{e:16,y:5,a:16,b:1,f:2,l:12,m:2,o:14,p:1,s:6,u:61,d:1,i:10,k:3,t:5},o:{s:7,g:3,e:3,k:3,n:20,m:4,p:5,w:6,b:3,c:2,t:6,a:5,d:5,h:10,i:2,l:8,o:3,r:8,u:4,y:2,v:2,z:1,f:20,x:1},u:{t:8,e:5,m:7,s:11,a:2,n:13,r:15,d:6,c:1,f:10,g:5,l:9,y:1,z:1,b:5,j:1,x:1,p:2,k:1,i:2},c:{e:9,h:20,i:2,r:6,t:20,o:15,k:15,a:15,l:6,u:8,y:1},h:{e:21,r:2,a:7,i:15,o:20,u:15,n:10,l:0,y:1},i:{d:8,m:5,n:18,r:7,a:5,s:8,v:2,l:13,t:20,b:1,e:21,k:2,p:5,g:20,c:4,o:2,f:2,z:1},m:{e:10,s:8,a:21,i:12,m:1,o:15,y:2,b:4,p:2,n:1,u:8},n:{e:18,u:3,a:9,d:3,n:4,o:20,s:2,t:11,g:10,k:6,i:5,y:2,c:1},r:{e:15,s:4,y:4,a:16,c:1,g:1,i:12,m:3,p:2,t:4,b:1,d:4,k:4,n:5,r:2,o:11,l:2,u:20,f:1},t:{a:14,s:15,e:18,i:2,o:15,h:10,t:3,y:2,c:1,z:1,u:5,r:5,w:2},d:{a:14,d:4,s:10,e:61,y:8,i:12,o:7,r:3,u:10,l:0},f:{a:5,f:6,e:12,y:1,i:3,l:13,o:16,r:7,u:20,t:4,n:1,s:1},g:{a:16,e:12,o:17,u:7,s:18,g:0,y:2,i:8,l:3,n:2,h:3,r:9,w:1},j:{a:8,i:7,e:14,o:5,u:29},k:{i:3,s:20,e:41,u:6,a:10,l:20,n:8,o:2,h:1,y:1},p:{s:12,e:20,a:5,y:2,i:13,t:4,u:10,l:3,o:13,r:4},s:{o:8,i:8,e:13,k:6,h:10,s:8,t:14,y:1,p:5,c:2,l:2,a:10,m:2,n:6,u:8,w:2},v:{a:10,e:20,i:22,o:6,y:6},y:{l:6,e:15,s:20,d:3,n:8,r:8,t:4,a:4,k:1,m:1,o:3,x:3,p:3,u:1,v:1},q:{u:100},w:{a:24,e:17,l:4,r:2,s:3,n:6,y:20,k:1,d:1,t:1,i:17,u:6,o:10,h:20},x:{e:35,i:6,l:3,o:6,a:6,t:3,y:7},z:{z:10,y:10,a:3,e:43,r:1,o:8,i:7,u:1}}

New results:
words: 53 mistakes, non-words: 159 mistakes
http://fiddle.jshell.net/jc73sjyn/2/

I should add that the numbers were found through evaluation of the 2236 correct words. For every letter i would simply calculate the rounded percentage of each successor. I considered doing the same for the wrong words and somehow subtract them, but I think that would make the evaluation less clever and more taking advantage of the limited set of wrong words.

I've managed to reduce your code as much as I could. I've eaten around 80 bytes. Not much, but it's smaller. Here's the code: http://pastebin.com/fkPW0D92 . I've replaced ALL the numbers that were repeated more than 3 times and still removed lots of bloat from your for loop.

Forgot to mention: it only works on Firefox/Firebug console. This uses the new ES6 big-arrow notation to create functions. You can replace w=> by function(w) and it will work for every browser.

Python 2, 5254 bytes
This solution separates the good words into two halves. The lookup first checks the first 2 characters to find the right string, then looks for the second 2 characters in that string. Not very compact, but quick to write. This method matches every word without mistakes.
d='''gwenyn
guamlflllpmsnsrushsttsys
grabadamayegeweyidiminipisitowub
gyro
gearldlsmsnentrmts
gagsilinitlellltmengpepsrbryshspteulvewkze
goadalatbidsesffghldlfnengodofreryshtoutwn
gnataw
gladeeenowueut
giftldllltnannnonsrdrlrtstve
wrapenit
leadafakanaparekeresftgsnandnsntonsssttsvivywd
labsceckcydsdygsidinirkembmempnandnengospsrdrkrsshssstteuevawnwsyszy
loadafanbecickebftgogsiniskilambmenengokomonopotrdresesssttsudutvewews
tubebsckftgsnerfrn
trapayeeekimioipodotoyueuk
liarceckdsedeneseufeftkelalymambmempndnenkntonpssasespssstve
toadbyddesgoilldllmbneninsokolpsrernrysstourwnys
luckcyiskellmpndngrarerkshsttetz
thaianataweaemeneyinisorudugus
tickdedyedereslellltmemsnansntnypsretots
teamarasemenllndnsntrmssstxt
lylennnxonrare
dockdderesgegslellmenensomorperasetetsugvewnze
typepo
yokerkstur
dialcedoedemesetgskellmemsnengntonpsrertscshskve
yagilenkrdrnwn
deadafalanarbtckedemeperfyllmonsntnyskuswy
yearaslllp
dadadedshllelilymemnmpmsnanererkrnrtshtatevevywnysze
dyadedereskene
dualbsckctelesetkelllymbmpnengnknnpeskstty
drabagamawewipopugum
yves
yubakiri
quadayipitiz
iranaqesisksmaon
emilitma
elbakslamsse
endsidosvy
eire
zincon
ekedes
eels
eddyengeitna
egangsos
eachrlrnrprssestsyts
echo
ebbsen
eyederes
examecit
ezra
etch
ewenes
eveneril
wokelfmbngntodofolosrdrerkrmrnve
epic
espy
erasgoicieikisneosrs
rubebsbydedygsinlempngnsntshssstthts
ryan
readalamapardodsedefelidinlymynandnenontstub
raceckftgegsidilinkemompmsndngnkntpepsptreshsptetsulveysze
itchelem
roadamarbebsckdedslellmempofokomotpesasesssythtsutvewewsxy
rhea
ribscacechckcodedsftgagsllmemsndngnkotpepsscsesktetz
beadakamanaratauckdsefeneperesetgslallltlyndntnzrnrtsssttatsvy
weakanarbbbsdsedekephrldllntptrestts
babebychckdegsilitjakekuldlelilklllmndnengnknsrbrdrerkrnrrrsrtseshskssthtsudwlys
wacodeftgegshlilitkelkllltndnengntrdrermrnrprsrtryshspvexyys
blabedewipobocotowueumur
juandddedodygslympnengnknorareryst
boaratbscadedyergshrilisldllltmbndnengnnnyobokomonorosotrergrnsessthutwlwsydys
biasbsdedsenerkelelkllndngninsrdtets
wickdeerfegsldlellltlyndnengnknspereryseshspthtstt
whatenimipitizom
buckdddsffgslblkllmpmsnknsntoyrlrnrprrrtryshssstsyttyszz
joanbsdyelesgshninkeltsetsveys
jigsll
braeaganasatayedewieigimowyn
jeaneperffrksttsws
byrdte
wynn
ooze
onceeslytousyx
omanenit
olafavdyeggain
okay
oilsly
ohio
offs
oddsesinor
obeyoe
oaksrsthts
ivan
stabaganarayemepewiropowubudunyx
oxen
owedeneslsns
ovalenerid
ouchrsstts
otisto
oslo
oralesgyinly
opalecelentsus
vialcedaederesetewlenesatato
citety
chadaoaparatefenewicinipitopouum
coalataxbbcackcodedyedgshnilinkeldleltmbmeneokolonoppepspyrdrerkrnstsytsvewlwszy
cladamanapawayioipodogotubueuj
cabsdyfegeinkelflllmmempnensntpepsrdrerlrprrrsrtseshsksttsve
cedellltntrn
czar
cyst
zoneomosrn
crabagamayeeewibopowuduxuz
cubabebsedesffllltpsrbrdrerlrsrtsptets
vealdaergailinlannntrarbrnrystto
prayepeyimodoposow
pubsffghkelllpmampnsntnypapsrerrshsststt
smogugut
pylere
jabsckdeilkemsnersvawszz
paceckctdsgeidilinirlelllmlolsnengnsntparcrerkrrrsrtsosssttethtsulvewnwsys
peakalarasatckekelepergsltndnhnnnsntrkrusttetsws
phil
picackcteresgskelellmpnengnknsntonpesassthtstttyus
isisle
planayeaodotowoyugumus
hydemn
hubsckeseygeghgollmempmsngnknsntrdrlrtshskts
hickdeghkellltndntpsresstsve
hoaresffgsldlelmlymemoneodofokopotpepipsrnsesturwewlyt
haagasckhnilirlelfllltmsndngnsrdrerkrmrprtshtetsulvewkyszezy
headalaparatbeckedelirldlllmlpmpmsnsrarbrdrerorrrsssws
meadalanateketltmondnsnureshsstatetsws
macechdeidiliminkelelillltmanennnsnypsrcrerkrsrtrxryshsksssttethtsttulwryayoze
utah
moanatbsckdeenhrldlellnankntodonorotpsrernssstthvews
micaceckenkeldlelkllmindneninkntpsraressst
upon
twasiginos
podsemetgokelelklllompndngnyolorpepsrerkrtseshsttsurut
muchckddffgsirlellngseshsksttettzo
ulan
undoitixixto
imps
ugly
tabsckctftgsilkelelkllmengnkospepsrartskssteutxi
myrath
illsly
vailinlenensrysestts
acesheidmeneretats
abbabebyedeletlelyosut
adamdsen
agaredeeeresogue
afar
aidadedsmsnursry
swabamanapatayimum
akin
ajarax
amenesidmookosyl
alanarasbaeceeexfagalymamsoepssoumva
analdyewnaneonsitetitsus
aqua
apedesexse
asiaks
arabchcocseaesgoidmsmypats
auntrato
atomop
awayedlsry
averidisivonow
ayes
axedeleresisleon
icedeson
ibexidis
ideaemlelyol
igor
ifni
niceckghlenaneps
usederes
noahdedselllneokonrarmseteun
nagsgyilirmepsrysashtetourvyzi
nealaratckedffilllonrosssttsvawswtxt
voidltsstews
zulu
nudellmbnsts
franauayedeeeteyogomye
urdugeisnssa
fueljillmendnkrsrysesszz
ionstawa
facectdegsilinirkelkllmengnsrermsttetsunwnze
fearatedelesetllltndrnssud
zealrostus
fiateffegsjilelllmndnenknnnsrermshsksttsve
flagakamapatawaxeaedeeewexipitogopowueux
foalamciesgsgyilldlkndntodolotrdrerkrmrtssulurwl
kahnlinentrlrptetz
incachdodyksnsto
keelenepmpntptrnrrys
kickdselevllndngnkrksstets
spanatecedinitotunur
kochng
kneeewitobotowox
subschckdsedesezitlkmsngnknsrerf
klanux
skewidiminipisitye
siamanckdeftghgnkhlkllloltmsnengnknspsrerstetstuvaze
shameaedinipitodoeopotowunut
soakaparbsckdadsfaftilldlelomengnsnyonotrertulupurwnya
snagapipobowubug
kudohnrdrt
slabamapatavayedewidimipitobopotowugumur
scabanarotowud
sackfegagegsidilkelelkltlzmenandnengnkpsrarishteudulvewsys
sealamanarasatctedekemenepereslfllmindntptrfthtswsxy'''
w=raw_input()
s=[t[2:] for t in d.split() if t[:2]==w[:2]]
print s and w[2:] in [s[0][i:i+2] for i in range(0,len(s[0]),2)]

Word VBA, 25 Bytes
Anonymous VBE immediate window function that takes input as the current selection and outputs if it is a word as boolean to the VBE immediate window.
?CheckSpelling(Selection)

Tester Function
The below function was used to test the above function against the testcases. The function failed 9.07 percent of the cases (396 of the actual words and 10 of the fake words)
i=0:For Each w In Split(Selection,vbcr):i=i-CheckSpelling(w):Next:?i" were recognized as words

C# WPF, 110 139
Shorter
bool F(string s){var t=new TextBox();t.SpellCheck.IsEnabled=true;t.Text=s;return t.GetSpellingError(0)==null;}

Old answer
public bool F(string s){TextBox t=new TextBox();t.SpellCheck.IsEnabled=true;t.Text=s;SpellingError e=t.GetSpellingError(0);return e==null;}

Does it take the default locale? :)

@RobAu Not sure, first time I used it.

You could make it quite a bit shorter by using varand not introducing variables unless necessary.

Mathematica, 33 bytes
Hey, somebody had to do it!
Length[DictionaryLookup[Input[]]]

Self-explanatory.

Lexurgy, 106 bytes
Lexurgy, despite the fact it's meant for constructed languages, can be used for natural language processing as well.
Keeps the input if it thinks it's a word, and an empty string if it thinks it's not.
Reimplements @Sp3000's regex, so this fails at the same rate (660 misclassifications).
Class V {a,e,i,o,u}
Class F {j,q,x,z}
a propagate:
[]? !@V !@V !@V []?=>*
[]=>*/{_ @F,@F _}
v:
@F=>*

Explanation:
# Define the classes
Class V {a,e,i,o,u}
Class F {j,q,x,z} # forbidden letters

a propagate:           # while the input is changed from last iteration:
[]? !@V !@V !@V []?=>* #   remove `[^aeiou]{3}`
[]=>*/{_ @F,@F _}      #   remove any letters next to the forbidden ones
v:                     # then:
@F=>*                  #   remove the forbidden letters

Javascript ES6, 32 bytes:
Using the regex from @Sp3000 answer:
s=>!/[^aeiou]{3}|[jqxz]/.test(s)

This creates an anonymous function. To use it, you simply wrap it around ().
Example:
(s=>!/[^aeiou]{3}|[jqxz]/.test(s))('word')

This has exactly the same fail rate as @Sp3000, and returns true or false accordingly.
All credits due to @Sp3000 for letting me use his regex.

@Sp3000 But then you won't be able to call it. This is the same as F = function(s) { return /[^aeiou]{3}|[jqxz]/.test(s) }.

@Sp3000 I know it works, but you have to spend more bytes to use it.

@Sp3000 DANG it! One step away from shortening it :/ Thanks for the tip. I've updated it.

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes