text:
Scriptbot Warz!
Scriptbot Warz!

The results are in and Assassin is our champion, winning 2 of 3 matches! Thanks to everyone who submitted their Scriptbots! Special thanks to horns for BestOpportunityBot which displayed excellent pathing and made full use of all action options.
Map 1
Assassin took out BestOpportunityBot early on, and the rest of the match was pretty boring. Detailed play-by-play here.

Assassin: 10 HP, 10 Damage Dealt, 3 Damage Taken
The Avoider v3: 10 HP, 0 Damage Dealt, 0 Damage Taken
Gotta Finish Eating: 10 HP, 0 Damage Dealt, 0 Damage Taken
BestOpportunityBot: 0 HP, 3 Damage Dealt, 10 Damage Taken

Map 2
BestOpportunityBot did most of the work on this match, but Assassin was able to take him out in the end. Detailed play-by-play here.

Assassin: 2 HP, 10 Damage Dealt, 9 Damage Taken
BestOpportunityBot: 0 HP, 32 Damage Dealt, 10 Damage Taken
The Avoider v3: 0 HP, 0 Damage Dealt, 12 Damage Taken
Gotta Finish Eating: 0 HP, 0 Damage Dealt, 11 Damage Taken

Map 3
BestOpportunityBot pushed everyone into traps on this match. Very cool. Detailed play-by-play here.

BestOpportunityBot: 10 HP, 30 Damage Dealt, 0 Damage Taken
Assassin: 0 HP, 0 Damage Dealt, 0 Damage Taken
Gotta Finish Eating: 0 HP, 0 Damage Dealt, 0 Damage Taken
The Avoider v3: 0 HP, 0 Damage Dealt, 0 Damage Taken

Thanks for your answers! Since there are just 4 Scriptbots, we are abandoning the tournament plans for three free-for-all matches, one on each of the maps below. The scriptbot with the highest win record wins. In the event of a tie, we will enter into sudden death wherein the scriptbot who breaks the tie first wins.

Your task, should you choose to accept it, is to code a Scriptbot which can traverse an ASCII map and destroy its opponents. Each battle will take the form of a random-starting-order turn-based game where each Scriptbot has a chance to spend their energy points (EP) to take actions. The GameMaster script will feed input to, and interpret output from each Scriptbot.
Environment
Each Scriptbot is contained within its own directory where it can read from the map and stats files and read/write to the data file. The data file can be used to store any persistent information you might find useful.
The stats File
The stats file contains information about your opponents and is formatted as follows. Each player is represented on a separate row. The first column is a player ID (@ means you). The second column is the health of that player.
1,9HP
@,10HP
3,9HP
4,2HP

The map File
The map file might look something like this...
####################
#   #          #   #
# 1 #          # 2 #
#                  #
###              ###
#                  #
#      #           #
#       #     !    #
#        #         #
#       !####      #
#      ####!       #
#         #        #
#    !     #       #
#           #      #
#                  #
###              ###
#                  #
# 3 #          # @ #
#   #          #   #
####################

... or this...
######################################
#       # 1        #   @             #
#       #          #          #!     #
#       #          #          ####   #
#  #    #  #       #         !#!     #
#  #    #  #       #      #####      #
#  ###     #    ####    #         #  #
#          #    #!      ###       #  #
#  ######  #    #       #     #####  #
#  #!      #    ######  #        !#  #
#  ###     #            #         #  #
#  #    2  #            #   4     #  #
######################################

... or this...
###################
###!!!!!!#!!!!!!###
##!             !##
#! 1     !     2 !#
#!       !       !#
#!               !#
#!               !#
#!      !!!      !#
## !!   !!!   !! ##
#!      !!!      !#
#!               !#
#!               !#
#!       !       !#
#! 3     !     @ !#
##!             !##
###!!!!!!#!!!!!!###
###################

... or it might look totally different. Either way, the characters used and their meaning will remain the same:

# A wall, impassable and impenetrable.
1, 2, 3... A number representing an enemy player. These numbers correspond to the player ID in the stats file.
! A trap. Scriptbots who move onto these locations will die immediately.
@ Your Scriptbot's location.
 Open space which you are free to move around in.

Gameplay
The GameMaster script will assign a random starting order to the Scriptbots. The Scriptbots are then invoked in this order while they are still alive. Scriptbots have 10 Health Points (HP), and start with 10 Energy Points (EP) each turn, which they may use to move or attack. At the start of each turn, a Scriptbot will heal for one HP, or be granted one additional EP if already at 10 HP (thus running may be a viable strategy at times).
The battle ends when only one Scriptbot survives or when 100 turns have passed. If multiple Scriptbots are alive at the end of a battle, their place is determined based on the following criteria:

Most health.
Most damage dealt.
Most damage taken.

Scriptbot Input
The GameMaster will print the battle map to a file named map which the Scriptbot will have access to read from. The map might take any form, so it is important that the Scriptbot be able to interpret it. Your Scriptbot will be invoked with one parameter indicating EP. For example...
:> example_scriptbot.py 3

The Scriptbot will be invoked until it spends all of its EP or a maximum of 10 11 times. The map and stats files are updated before each invocation.
Scriptbot Output
Scriptbots should output their actions to stout. A list of possible actions are as follows:

MOVE <DIRECTION> <DISTANCE>
Costs 1 EP per DISTANCE. The MOVE command moves your Scriptbot around the map. If there is something in the way such as a wall or another Scriptbot, the GameMaster will move your Scriptbot as far as possible. If a DISTANCE greater than the Scriptbot's remaining EP is given, the GameMaster will move the Scriptbot until its EP runs out. DIRECTION may be any compass direction of N, E, S, or W.
PUSH <DIRECTION> <DISTANCE>
Costs 1 EP per DISTANCE. The PUSH command enables a Scriptbot to move another Scriptbot. The Scriptbot issuing the command must be directly next to the Scriptbot being pushed. Both Scriptbots will move in the direction indicated if there is not an object blocking the Scriptbot being pushed. DIRECTION and DISTANCE are the same as for the MOVE command.
ATTACK <DIRECTION>
Costs one EP. The ATTACK command deals 1 damage to any Scriptbot directly next to the issuing Scriptbot and in the direction specified. DIRECTION is the same as for the MOVE command.
PASS
Ends your turn.

Supported Languages
To keep this reasonable for me, I will accept the following languages:

Java
Node.js
Python
PHP

You are limited to libraries which are commonly packaged with your languages out of the box. Please do not make me locate obscure libraries to make your code work.
Submission and Judging
Post your Scriptbot source code below and give it a cool name! Please also list the version of the language you used. All Scriptbots will be reviewed for tomfoolery so please comment well and do not obfuscate your code.
You may submit more than one entry, but please make them totally unique entries, and not versions of the same entry. For instance, you may want to code a Zerg Rush bot and a Gorilla Warfare bot. That's fine. Do not post Zerg Rush v1, Zerg Rush v2, etc.
On November 7th I will collect all answers and those which pass the initial review will be added to a tournament bracket. The champion gets the accepted answer. The ideal bracket is shown below. Since there will likely not be exactly 16 entries, some brackets may end up being only three or even two bots. I will try to make the bracket as fair as possible. Any necessary favoritism (in the event that a bye week is needed for instance) will be given to the bots which were submitted first.
BOT01_
BOT02_|
BOT03_|____
BOT04_|    |
           |
BOT05_     |
BOT06_|___ |
BOT07_|  | |
BOT08_|  | |_BOT ?_
         |___BOT ?_|
BOT09_    ___BOT ?_|___CHAMPION!
BOT10_|  |  _BOT ?_|
BOT11_|__| |
BOT12_|    |
           |
BOT13_     |
BOT14_|____|
BOT15_|
BOT16_|

Q&A
I'm sure I've missed some details, so feel free to ask questions!

May we trust that a map file is always surrounded by # symbols? If not, what happens in the event that a bot attempts to walk off the map? - BrainSteel

Yes the map will always be bounded by # and your Scriptbot will start inside of these bounds.

If there is no bot present in the direction specified in a PUSH command, how does the command function? - BrainSteel

The GameMaster will do nothing, zero EP will be spent, and the Scriptbot will be called again.

Do unused EP accumulate? - feersum

No. Each Scriptbot will start the round/turn with 10 EP. Any EP not spent will go to waste.

I think I've got it, but just to clarify: with bots A and B, is the order of events A@10EP->MOVE MAP_UPDATE B@10EP->PUSH MAP_UPDATE A@9EP->ATTACK MAP_UPDATE B@9EP->ATTACK ..., or A@10EP->MOVE A@9EP->ATTACK ... MAP_UPDATE B@10EP->PUSH B@9EP->ATTACK ... MAP_UPDATE? In other words, is all action in one controller-bot query loop atomic? If so, why the loop? Why not return a single file with all the actions to be completed? Otherwise bots will have to write out their own state files to keep track of multi-action sequences. The map/stats file will only be valid prior to the first action. - COTO

Your second example is close, but not quite right. During a turn, the Scriptbot is invoked repeatedly until their EP is spent, or a maximum of 11 times. The map and stats files are updated before each invocation. The loop is useful in the event that a bot gives invalid output. The GameMaster will deal with the invalid output and involke the bot again, giving the bot a chance to correct for it's mistake.

will you release the GameMaster script for testing? - IchBinKeinBaum

The GameMaster script will not be released. I would encourage you to create a map and stats file to test your bot's behavior.

If robotA pushes robotB into a trap, is robotA credited with "damage dealt" points equal to the current health of robotB? -  Mike Sweeney

Yes, that is a good idea. A bot will be granted damage points equal to the health of a any bot that it pushes into a trap.

May we trust that a map file is always surrounded by # symbols? If not, what happens in the event that a bot attempts to walk off the map?

@BrainSteel Yes the map will always be bounded by # and your Scriptbot will start inside of these bounds.

If you're sure you've missed something, why not post it in the sandbox?

If there is no bot present in the direction specified in a PUSH command, how does the command function?

@MartinBüttner I've thought this through quite thoroughly. I was just trying to be friendly and make it clear that questions are welcome.

@BrainSteel If the PUSH is invalid, the GameMaster script will do nothing, zero EP will be spent, and the Scriptbot will be called again.

I assume EP is 1 per DISTANCE for MOVE/PUSH, but what's the EP cost for ATTACK? You say the program will be invoked a maximum of 10 times, but what if I start the turn with 11 EP (from being at 10 HP)?

Do unused EP accumulate? 2. What is meant by The map might take any form ?

Will a PASS option be added, or must I use all my EP each turn on real actions?

@Geobits ATTACK is 1 EP. I have clarified this in the list of actions. I have also changed the max calls to 11. I have added PASS as an option. I also tried to add a visual bracket for clarification for the tournament style. Thank you! @ferrsum No EP does not accumulate. I have added that to the Q&A.

@Geobits As in a typical bracket, a Scriptbot will get one entry into the tournament and when they're out, they're out.

I guess the only question I have left about the bracket is: Assuming the number of entries isn't a perfect power of 4, how are the blanks handled? Will you add a dummy bot to fill them, use a bye system, or something else?

@Geobits There will be no dummy bots. I will try to make the bracket as fair as possible with the submissions that I am given. I have updated the Submission and Judging section with more info. Thanks!

I think I've got it, but just to clarify: with bots A and B, is the order of events A@10EP->MOVE MAP_UPDATE B@10EP->PUSH MAP_UPDATE A@9EP->ATTACK MAP_UPDATE B@9EP->ATTACK ..., or A@10EP->MOVE A@9EP->ATTACK ... MAP_UPDATE B@10EP->PUSH B@9EP->ATTACK ... MAP_UPDATE? In other words, is all action in one controller-bot query loop atomic? If so, why the loop? Why not return a single file with all the actions to be completed? Otherwise bots will have to write out their own state files to keep track of multi-action sequences. The map/state file will only be valid prior to the first action.

Shouldn't the ranking be most HP, most damage dealt, least damage taken? Surely a bot that takes less damage is better than one that takes more.
Also will you release the GameMaster script for testing?

@COTO I've answered in the Q&A section and also clarified the main document.

@IchBinKeinBaum I think that point can be argued. I would say that taking more damage indicates that your battle was tougher and so you deserve to win. I hope that it will not come to that level of detail. If you can think of a better third rank criteria, I am willing to replace damage taken. The GameMaster script will not be released. I would encourage you to create a map and stats file to test your bot's behavior.

Does the rule above During a turn, the Scriptbot is invoked repeatedly until their EP is spent, or a maximum of 11 times mean that if robotA is next to robotB, it can attack 10 (or 11) times and kill robotB? Put another way, if I have 5 health points left and I leave my robot within 5 spaces of another robot, that robot can move and kill my robot in one turn, before I could act?

@Mike yes, that's right.

For our own testing in movement and such, will you/could you provide a handful of maps that may be used in the simulation?

If robotA pushes robotB into a trap, is robotA credited with "damage dealt" points equal to the current health of robotB?

@BrainSteel Sure, I will work on a few maps. Look for them in the main document soon.

@MikeSweeney; I think you have the same idea I do, lol.  I was going to code "It's a tarp" bot (or maybe, a homage to Soul Asylum "I want somebody to shove"), and just push everyone into traps, lol.

@MikeSweeney Yes, that is a good idea. A bot will be granted damage points equal to the health of a any bot that it pushes into a trap.

Also, I think you should ensure your random starting points are at least subject to a criteria that no bot is within immediate death distance of other bot(s).  In other words, it's not really fair if bot A starts close enough to a set of bots (B, C, etc) who can move close to it and attack it to death before bot A even has a chance to execute.  Or, at the very least, configure the bracket system in such a way that all bots execute at least once before they are eliminated....

@DreamWarrior I should clarify. The order is random. The starting position will be predefined so that no one bot can kill another bot on their first turn.

Assassin (Java 1.7)
Tries to kill enemies whenever possible, otherwise moves one field. It is pretty good in finding the path to an enemy, but doesn't do anything to hide from other bots.
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

public class Assassin {
    private final Path dataPath = Paths.get("data");
    private final Path mapPath = Paths.get("map");
    private final Path statsPath = Paths.get("stats");
    private final List<Player> players = new ArrayList<>();
    private final int energy;
    private Map map = null;

    public Assassin(int energy) {
        this.energy = energy;
    }

    private void doSomething() {
        if (dataFileEmpty()) {
            calculateTurn();
        }
        printStoredOutput();
    }

    private boolean dataFileEmpty() {
        try {
            return !Files.exists(dataPath) || Files.size(dataPath)  == 0;
        } catch (IOException e) {
            return true;
        }
    }

    private void printStoredOutput() {
        try {
            List<String> lines = Files.readAllLines(dataPath, StandardCharsets.UTF_8);
            //print first line
            System.out.println(lines.get(0));
            //delete first line
            lines.remove(0);
            Files.write(dataPath, lines, StandardCharsets.UTF_8);
        } catch (IOException e) {
            System.out.println("PASS");
        }
    }

    private void calculateTurn() {
        try {
            readStats();
            readMap();
            if (!tryKill())  {
                sneakCloser();
            }
        } catch (IOException e) {}
    }

    private void readStats() throws IOException{
        List<String> stats = Files.readAllLines(statsPath, StandardCharsets.UTF_8);
        for (String stat : stats) {
            String[] infos = stat.split(",");
            int hp = Integer.parseInt(infos[1].replace("HP", ""));
            players.add(new Player(stat.charAt(0), hp));
        }
    }

    private void readMap() throws IOException{
        List<String> lines = Files.readAllLines(mapPath, StandardCharsets.UTF_8);
        Field[][] fields = new Field[lines.size()][lines.get(0).length()];
        for (int row = 0; row < lines.size(); row++) {
            String line = lines.get(row);
            for (int col = 0; col < line.length(); col++) {
                fields[row][col] = new Field(line.charAt(col), row, col);
            }
        }
        map = new Map(fields);
    }

    private boolean tryKill() {
        Field me = map.getMyField();
        for (Field field : map.getEnemyFields()) {
            for (Field surrField : map.surroundingFields(field)) {
                List<Direction> dirs = map.path(me, surrField);
                if (dirs != null) {
                    for (Player player : players) {
                        //can kill this player
                        int remainderEnergy = energy - dirs.size() - player.hp;
                        if (player.id == field.content && remainderEnergy >= 0) {
                            //save future moves
                            List<String> commands = new ArrayList<>();
                            for (Direction dir : dirs) {
                                commands.add("MOVE " + dir + " 1");
                            }
                            //attacking direction
                            Direction attDir = surrField.dirsTo(field).get(0);
                            for (int i = 0; i < player.hp; i++) {
                                commands.add("ATTACK " + attDir);
                            }
                            if (remainderEnergy > 0) {
                                commands.add("PASS");
                            }
                            try {
                                Files.write(dataPath, commands, StandardCharsets.UTF_8);
                            } catch (IOException e) {}
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

    private void sneakCloser() {
        Field me = map.getMyField();
        for (Direction dir : Direction.values()) {
            if (!map.move(me, dir).blocked()) {
                List<String> commands = new ArrayList<>();
                commands.add("MOVE " + dir + " 1");
                commands.add("PASS");
                try {
                    Files.write(dataPath, commands, StandardCharsets.UTF_8);
                } catch (IOException e) {}
                return;
            }
        }
    }

    public static void main(String[] args) {
        try {
            new Assassin(Integer.parseInt(args[0])).doSomething();
        } catch (Exception e) {
            System.out.println("PASS");
        }
    }

    class Map {
        private Field[][] fields;

        public Map(Field[][] fields) {
            this.fields = fields;
        }

        public Field getMyField() {
            for (Field[] rows : fields) {
                for (Field field : rows) {
                    if (field.isMyPos()) {
                        return field;
                    }
                }
            }
            return null; //should never happen
        }

        public List<Field> getEnemyFields() {
            List<Field> enemyFields = new ArrayList<>();
            for (Field[] rows : fields) {
                for (Field field : rows) {
                    if (field.hasEnemy()) {
                        enemyFields.add(field);
                    }
                }
            }
            return enemyFields;
        }

        public List<Field> surroundingFields(Field field) {
            List<Field> surrFields = new ArrayList<>();
            for (Direction dir : Direction.values()) {
                surrFields.add(move(field, dir));
            }
            return surrFields;
        }

        public Field move(Field field, Direction dir) {
            return fields[field.row + dir.rowOffset][field.col + dir.colOffset];
        }

        public List<Direction> path(Field from, Field to) {
            List<Direction> dirs = new ArrayList<>();
            Field lastField = from;
            boolean changed = false;

            for (int i = 0; i < energy && lastField != to; i++) {
                List<Direction> possibleDirs = lastField.dirsTo(to);
                changed = false;
                for (Direction dir : possibleDirs) {
                    Field nextField = move(lastField, dir);
                    if (!nextField.blocked()) {
                        lastField = nextField;
                        changed = true;
                        dirs.add(dir);
                        break;
                    }
                }
                if (!changed) {
                    return null; //not possible
                }
            }
            if (lastField != to) {
                return null; //not enough energy
            }
            return dirs;
        }
    }

    class Field {
        private char content;
        private int row;
        private int col;

        public Field(char content, int row, int col) {
            this.content = content;
            this.row = row;
            this.col = col;
        }

        public boolean hasEnemy() {
            return content == '1' || content == '2' || content == '3' || content == '4';
        }

        public List<Direction> dirsTo(Field field) {
            List<Direction> dirs = new ArrayList<>();
            int distance = Math.abs(row - field.row) + Math.abs(col - field.col);

            for (Direction dir : Direction.values()) {
                int dirDistance = Math.abs(row - field.row + dir.rowOffset) +
                        Math.abs(col - field.col + dir.colOffset);
                if (dirDistance < distance) {
                    dirs.add(dir);
                }
            }
            if (dirs.size() == 1) { //add near directions
                for (Direction dir : dirs.get(0).nearDirections()) {
                    dirs.add(dir);
                }
            }
            return dirs;
        }

        public boolean isMyPos() {
            return content == '@';
        }

        public boolean blocked() {
            return content != ' ';
        }
    }

    class Player {
        private char id;
        private int hp;

        public Player(char id, int hp) {
            this.id = id;
            this.hp = hp;
        }
    }

    enum Direction {
        N(-1, 0),S(1, 0),E(0, 1),W(0, -1);

        private final int rowOffset;
        private final int colOffset;

        Direction(int rowOffset, int colOffset) {
            this.rowOffset = rowOffset;
            this.colOffset = colOffset;
        }

        public Direction[] nearDirections() {
            Direction[] dirs = new Direction[2];
            for (int i = 0; i < Direction.values().length; i++) {
                Direction currentDir = Direction.values()[i];
                if (Math.abs(currentDir.rowOffset) != Math.abs(this.rowOffset)) {
                    dirs[i%2] = currentDir;
                }
            }
            return dirs;
        }
    }
}

What version of Java was this written in?

@Nate I used 1.7.

The Avoider v3
A simple minded bot. It is afraid of other robots and traps. It will not attack. It ignores the stats file and does not think ahead at all.
This is mainly a test to see how the rules would work, and as a dumb opponent for other competitors.
Edit: Now will PASS when no MOVE is better.
Edit2: Robots can be '1234' instead of '123'
The Python Code:
import sys
maxmoves = int(sys.argv[1])

ORTH = [(-1,0), (1,0), (0,-1), (0,1)]
def orth(p):
    return [(p[0]+dx, p[1]+dy) for dx,dy in ORTH]

mapfile = open('map').readlines()[::-1]
arena = dict( ((x,y),ch)
    for y,row in enumerate(mapfile)
    for x,ch in enumerate(row.strip()) )
loc = [loc for loc,ch in arena.items() if ch == '@'][0]

options = []
for direc in ORTH:
    for dist in range(maxmoves+1):
        newloc = (loc[0]+direc[0]*dist, loc[1]+direc[1]*dist)
        if arena.get(newloc) in '#!1234':
            break
        penalty = dist * 10  # try not to use moves too fast
        if newloc == loc:
            penalty += 32   # incentive to move
        for nextto in orth(newloc):
            ch = arena.get(nextto)
            if ch == '#':
                penalty += 17  # don't get caught againt a wall
            elif ch in '1234':
                penalty += 26  # we are afraid of other robots
            elif ch == '!':
                penalty += 38  # we are very afraid of deadly traps
        options.append( [penalty, dist, direc] )

penalty, dist, direc = min(options)
if dist > 0:
    print 'MOVE', 'WESN'[ORTH.index(direc)], dist
else:
    print 'PASS'  # stay still?

elif ch in '123': You want to look for at least 1234. If you are bot 3, the opponent list would be 124.

@Nate Thanks. I have changed the bot. You might want to make this clear in the rules. I might not be the only one that has misunderstood this.

BestOpportunityBot
This ended up being a little longer than I intended...and I'm not sure if I understand the rules for turns completely, so we'll see how this does.
from sys import argv
from enum import IntEnum

with open("map") as map_file:
    map_lines = map_file.read().splitlines()

with open("stats") as stats_file:
    stats_data = stats_file.read().splitlines()

ep = argv[1]

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(lhs, rhs):
        if (type(rhs) == tuple or type(rhs) == list):
            return Point(lhs.x + rhs[0], lhs.y + rhs[1])
        return Point(lhs.x + rhs.x, lhs.y + rhs.y)

    def __sub__(lhs, rhs):
        if (type(rhs) == tuple or type(rhs) == list):
            return Point(lhs.x - rhs[0], lhs.y - rhs[1])
        return Point(lhs.x - rhs.x, lhs.y - rhs.y)

    def __mul__(lhs, rhs):
        return Point(lhs.x * rhs, lhs.y * rhs)

    def __str__(self):
        return "(" + str(self.x) + ", " + str(self.y) + ")"

    def __repr__(self):
        return "(" + str(self.x) + ", " + str(self.y) + ")"

    def __eq__(lhs, rhs):
        return lhs.x == rhs.x and lhs.y == rhs.y

    def __hash__(self):
        return hash(self.x) * 2**32 + hash(self.y)

    def reverse(self):
        return Point(self.y, self.x)

dirs = (Point(0, 1), Point(1, 0), Point(0, -1), Point(-1, 0))

class Bot:
    def __init__(self, pos, ch, hp):
        self.pos = pos
        self.ch = ch
        self.hp = hp

    def __str__(self):
        return str(self.pos) + " " + str(self.ch) + " " + str(self.hp)

    def __repr__(self):
        return str(self.pos) + " " + str(self.ch) + " " + str(self.hp)

class MyBot(Bot):
    def __init__(self, pos, ch, hp, ep):
        self.ep = ep
        super().__init__(pos, ch, hp)

    def __str__(self):
        return super().__str__() + " " + self.ep

    def __repr__(self):
        return super().__repr__() + " " + self.ep

class Arena:
    def __init__(self, orig_map):
        self._map = list(zip(*orig_map[::-1]))
        self.bots = []
        self.me = None

    def __getitem__(self, indexes):
        if (type(indexes) == Point):
            return self._map[indexes.x][indexes.y]
        return self._map[indexes[0]][indexes[1]]

    def __str__(self):
        output = ""
        for i in range(len(self._map[0]) - 1, -1, -1):
            for j in range(len(self._map)):
                output += self._map[j][i]
            output += "\n"
        output = output[:-1]
        return output

    def set_bot_loc(self, bot):
        for x in range(len(self._map)):
            for y in range(len(self._map[x])):
                if self._map[x][y] == bot.ch:
                    bot.pos = Point(x, y)

    def set_bots_locs(self):
        self.set_bot_loc(self.me)
        for bot in self.bots:
            self.set_bot_loc(bot)

    def adjacent_bots(self, pos=None):
        if type(pos) == None:
            pos = self.me.pos
        output = []
        for bot in self.bots:
            for d in dirs:
                if bot.pos == pos + d:
                    output.append(bot)
                    break
        return output

    def adjacent_bots_and_dirs(self):
        output = {}
        for bot in self.bots:
            for d in dirs:
                if bot.pos == self.me.pos + d:
                    yield bot, d
                    break
        return output

    def look(self, position, direction, distance, ignore='', stopchars='#1234'):
        current = position + direction
        output = []
        for i in range(distance):
            if (0 <= current.x < len(self._map) and
                0 <= current.y < len(self._map[current.x]) and
                (self[current] not in stopchars or self[current] in ignore)):
                output += self[current]
                current = current + direction
            else:
                break
        return output

    def moveable(self, position, direction, distance):
        current = position + direction
        output = []
        for i in range(distance):
            if (0 <= current.x < len(self._map) and
                0 <= current.y < len(self._map[current.x]) and
                self[current] == ' '):
                output += self[current]
            else:
                break
        return output

    def danger(self, pos, ignore=None): # damage that can be inflicted on me
        output = 0
        adjacents = self.adjacent_bots(pos)
        hps = [bot.hp for bot in adjacents if bot != ignore]
        if len(hps) == 0:
            return output

        while max(hps) > 0:
            if 0 in hps:
                hps.remove(0)

            for i in range(len(hps)):
                if hps[i] == min(hps):
                    hps[i] -= 1
                output += 1
        return output

    def path(self, pos): # Dijkstra's algorithm adapted from https://gist.github.com/econchick/4666413
        visited = {pos: 0}
        path = {}

        nodes = set()

        for i in range(len(self._map)):
            for j in range(len(self._map[0])):
                nodes.add(Point(i, j))

        while nodes:
            min_node = None
            for node in nodes:
                if node in visited:
                    if min_node is None:
                        min_node = node
                    elif visited[node] < visited[min_node]:
                        min_node = node

            if min_node is None:
                break

            nodes.remove(min_node)
            current_weight = visited[min_node]

            for _dir in dirs:
                new_node = min_node + _dir
                if self[new_node] in ' 1234':
                    weight = current_weight + 1
                    if new_node not in visited or weight < visited[new_node]:
                        visited[new_node] = weight
                        path[new_node] = min_node

        return visited, path

class MoveEnum(IntEnum):
    Null = 0
    Pass = 1
    Attack = 2
    Move = 3
    Push = 4

class Move:
    def __init__(self, move=MoveEnum.Null, direction=Point(0, 0), distance=0):
        self.move = move
        self.dir = direction
        self.dis = distance

    def __repr__(self):
        if self.move == MoveEnum.Null:
            return "NULL"
        elif self.move == MoveEnum.Pass:
            return "PASS"
        elif self.move == MoveEnum.Attack:
            return "ATTACK " + "NESW"[dirs.index(self.dir)]
        elif self.move == MoveEnum.Move:
            return "MOVE " + "NESW"[dirs.index(self.dir)] + " " + str(self.dis)
        elif self.move == MoveEnum.Push:
            return "PUSH " + "NESW"[dirs.index(self.dir)] + " " + str(self.dis)

arena = Arena(map_lines)
arena.me = MyBot(Point(0, 0), '@', 0, ep)

for line in stats_data:
    if line[0] == '@':
        arena.me.hp = int(line[2:-2])
    else:
        arena.bots.append(Bot(Point(0, 0), line[0], int(line[2:-2])))

arena.set_bots_locs()

current_danger = arena.danger(arena.me.pos)

moves = [] # format (move, damage done, danger, energy)

if arena.me.ep == 0:
    print(Move(MoveEnum.Pass))
    exit()

for bot, direction in arena.adjacent_bots_and_dirs():
    # Push to damage
    pushable_to = arena.look(arena.me.pos, direction,
                             arena.me.ep + 1, ignore=bot.ch)
    if '!' in pushable_to:
        distance = pushable_to.index('!')
        danger = arena.danger(arena.me.pos + (direction * distance), bot)
        danger -= current_danger
        moves.append((Move(MoveEnum.Push, direction, distance),
                      bot.hp, danger, distance))

    # Push to escape
    pushable_to = arena.look(arena.me.pos, direction,
                             arena.me.ep + 1, ignore=bot.ch, stopchars='#1234!')
    for distance in range(1, len(pushable_to)):
        danger = arena.danger(arena.me.pos + (direction * distance), bot)
        danger += bot.hp
        danger -= current_danger
        moves.append((Move(MoveEnum.Push, direction, distance),
                      0, danger, distance))

    # Attack
    bot.hp -= 1
    danger = arena.danger(arena.me.pos) - current_danger
    moves.append((Move(MoveEnum.Attack, direction), 1, danger, 1))
    bot.hp += 1

culled_moves = []

for move in moves: # Cull out attacks and pushes that result in certain death
    if current_danger + move[2] < arena.me.hp:
        culled_moves.append(move)

if len(culled_moves) == 1:
    print(culled_moves[0][0])
    exit()
elif len(culled_moves) > 1:
    best_move = culled_moves[0]

    for move in culled_moves:
        if move[1] - move[2] > best_move[1] - best_move[2]:
            best_move = move
        if move[1] - move[2] == best_move[1] - best_move[2] and move[3] < best_move[3]:
            best_move = move

    print (best_move[0])
    exit()

# Can't attack or push without dying, time to move

moves = []

if current_danger > 0: # Try to escape
    for direction in dirs:
        moveable_to = arena.moveable(arena.me.pos, direction, ep)

        i = 1

        for space in moveable_to:
            danger = arena.danger(arena.me.pos + (direction * i))
            danger -= current_danger
            moves.append((Move(MoveEnum.Move, direction, i), 0, danger, i))
            i += 1

    if len(moves) == 0: # Trapped and in mortal danger, attack biggest guy
        adjacents = arena.adjacent_bots()
        biggest = adjacents[0]
        for bot in adjacents:
            if biggest.hp < bot.hp:
                biggest = bot
        print (Move(MoveEnum.Attack, biggest.pos - arena.me.pos))
        exit()

    best_move = moves[0]
    for move in moves:
        if ((move[2] < best_move[2] and best_move[2] >= arena.me.hp) or
            (move[2] == best_move[2] and move[3] < best_move[3])):
            best_move = move

    print(best_move[0])
    exit()

else: # Seek out closest target with lower health
    distances, path = arena.path(arena.me.pos)

    bot_dists = list((bot, distances[bot.pos]) for bot in arena.bots)

    bot_dists.sort(key=lambda x: x[1])

    target = bot_dists[0]

    for i in range(len(bot_dists)):
        if bot_dists[i][0].hp <= arena.me.hp:
            target = bot_dists[i]
            break

    pos = target[0].pos
    for i in range(target[1] - 1):
        pos = path[pos]

    print (Move(MoveEnum.Move, pos - arena.me.pos, 1))
    exit()

# Shouldn't get here, but I might as well do something
print (Move(MoveEnum.Pass))

what version of python did you write this in?

@Nate 3.4.1 on win32

Thanks for submitting this one @horns. It was really fun to watch!

Gotta Finish Eating
Python:
import sys
print 'PASS'

I lol'd at that — and why the hell import sys?

@tomsmeding Well I had to copy some stuff. And I thought in case I ever need to read some args :) when I finish eating, of course.

authors: 信无双2娱乐代理--平台总代

authors: 宇博娱乐代理--平台总代

authors: 安信8娱乐代理--平台总代

authors: 开丰娱乐代理--平台总代

authors: 摩臣5娱乐代理--平台总代

authors: 杏悦2娱乐代理--平台总代

authors: 杏盛娱乐代理--平台总代

authors: 海豚之星娱乐代理--平台总代

authors: 顺盈娱乐代理--平台总代


text:
Leave your mark!
In this challenge, you'll need to edit a grid of characters to make a program that does a task, while ensuring that you leave a lasting mark on the grid.
Task
The task to perform is determined by when you answer. Specifically, for the nth answer, divide n by 5, and if the remainder is...

0. Read a positive integer from STDIN (or closest alternative) and print its square.
1. Print the value of n9-n8+n7-...-n2+n-1.
2. Read a string from STDIN (or closest alternative) and print it, reversed.
3. Print the name of the language being used.
4. Print the first 99 Fibonacci numbers, with some delimiter.

In all cases, "print" means to STDOUT or closest alternative. Leading or trailing whitespace is okay. A full program is required, not just a function.
Answering (please read before posting)

This is a "sequential answering" challenge. Answers have a specific order. If the previous answer, chronologically, was titled Answer n, your answer should be titled Answer n+1.

All answers are 100 characters (in printable ASCII) long, divided into ten rows. Each row is separated by a newline. I have already posted the first answer.
Once an answer has been verified by another user (in a comment), any user, except for the one who gave the previous answer, can submit the next answer, pursuant to the following rules:
For each answer after the first, change at least one character (but not newlines) in the previous answer to another printable ASCII character achieve the correct task. You may not add, remove, or move any characters. You may use any language with a readily available compiler or interpreter.
Furthermore, you must specify one character you changed to be your "mark". You want to maximize the longevity of your mark. If your mark is first changed by the answer five after yours, its lifespan is 4 (four other answers left it untouched). If no one ever removes your mark, then the lifespan is the total number of other answers after it.
If you answer multiple times, you may have multiple existing marks at once.
If your answer is found incorrect, please delete it if there are no subsequent valid answers. Otherwise, do not delete or change your answers.
Scoring
Your score is the sum of your marks' longevities, divided by the total number of characters you changed. Subtract 5% from your score for each answer past the first.
For example, suppose I answer three times. First with 5 changes and a mark longevity of 3, then 4 changes and 20, then 1 change and a longevity of 7. My score is now
((3 + 20 + 7) / (5 + 4 + 1)) * (100% - 10%) = 2.7.

There is no rule against answering multiple times in a row?

@feersum Correct.

@MartinBüttner Then you'll lose 20% of your score.

@MartinBüttner Do you think that's really the best strategy?

@MartinBüttner Fine, you win.

The definition of mark longevity should be changed to the difference between answer numbers. Otherwise all scores can be 0.

Agree. As of now every answer has removed the previous mark (and all scores except the latest are 0). It doesn't make sense not to change it, since it only costs one char more at most, and you effectively erase the last entry from scoring (except for a 5% penalty to their next answer, which will probably end up a 0 anyway ;).

@Geobits The latest answer always scores 0 (under either definition).

@feersum A strange game. The only winning move is not to play.

Answer 2, CJam, 6 changed
"lass Fun{
 public
  static
void main(
 String[]
args) {
System.out
.print(0);
  }
}";lW%

The mark is the ; in the last line.
Test it here.

Verified; works.

Answer 5, Deadfish, changes 4
Deadfish has no input, thus the closest alternative to STDIN is that the number is already stored in the counter. Note that the language can't handle numbers over 255, so the "input" must be between 0 and 15 inclusive.
The j in statjc is the mark.
 var  Fun,
 publjc,
  statjc,
v=2;  f3r(
 S =[1,1];
v<99;){
S[v]=S[v-1
]+S[v++-2]
  o
alert(S)

This should work in theory, although I haven't found a way to test it. (I changed  S =[0,1]; to  S =[1,1];, by the way, but it shouldn't affect your score.)

@hsl Surely you can manage to run one of the 68 interpreters on the esolang page. But be warned many are deliberately broken in the spirit of the language.

I was actually using the Stack Snippet version, but I didn't see how to run it. This one's really simple because it just has an s and an o, though.

@hsl The other Deadfish interpreter on the same page works better. Make sure to uncheck the 'ASCII/Unicode' box.

Answer 3, CJam, 8 changed
"lass Fun{
 public
  static
void main(
 String[]
args) {
System.out
.print(0);
  }
";"CJam"

Changed the mark (;) from Answer 2.
My mark is the second " on the last line.
Test it here.

Verified this one.

Answer 6, CJam, changes 13
"var  Fun,
 publjc,
";8638UY5"
v=2;  f3r(
 S =[1,1];
v<99;){
S[v]=S[v-1
]+S[v++-2]
  o
alert(S)";

Try it online here
My mark is the last ;

I wrote a program to test this, and I came up with the same answer.  Word says it has 100 chars counting spaces and 10 lines, so I think it is good.

Answer 4, JavaScript, 56 changed

 var  Fun,
 public,
  static,
v=2;  for(
 S =[1,1];
v<99;){
S[v]=S[v-1
]+S[v++-2]
  }
alert(S)

Removed the previous mark. My mark is the } in the second-to-last line. Unfortunately, JavaScript rounds the really big FIbonacci numbers, but I think it works. (Note that there should be a leading space and 2 trailing spaces that are automatically removed.)

I think it works.

Actually it is invalid ... one of the lines has 11 characters.

It should be fixed now.

Answer 7, ><>, changes 14
i:0(  !#?^
 publjc,
";8638UY5o
v=2;  f3r:
 S =[1,1];
v<99;){  !
S[v]=S[v-?
]+S[v++-2l
  o
alert(S)"~

My mark is the # on the first line.

This question is stupid. Makes the user easily go an extra mile to remove the previous mark. I vote to close it.

Answer 1, Java
class Fun{
 public
  static
void main(
 String[]
args) {
System.out
.print(0);
  }
}

Shouldn't you have specified a mark in the first answer?

@FireFly I don't think it's fair to let myself get points for a mark, since I got to make the whole grid.

source: Stack Exchange

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

sort: votes


text:
Are You the One? (Mastermind Derivative)
I've got a tough one for you!
My girlfriend recently came across a new show on MTV (USA). It's a terrible show, and everyone on it is trashy, but the "game" is pretty interesting.  From Wikipedia:

Are You The One? follows 20 people who are living together in Hawaii to find their perfect match. If the 10 men and 10 women are
  able to correctly choose all ten perfect matches in ten weeks, they
  will gain $1 million to split among them.

Now for the game portion (also from Wikipedia):

Each episode the cast will pair up with who they believe their perfect
  match is to compete in a challenge. The winners of the challenge will
  go on a date, and have a chance to test their match in the truth
  booth. The cast members will choose one of the winning couples to go
  to the truth booth to determine if they are a perfect match or not.
  This is the only way to confirm matches. Each episode ends with a matching ceremony where the couples will be told how many perfect
  matches they have, but not which matches are correct.

TL;DR:  This is a Mastermind derivative ( M(10,10) to be specific). The rules of the game are as follows:

You start with 2 sets of 10, let's call them Set A:
{A,B,C,D,E,F,G,H,I,J} and Set 2: {1,2,3,4,5,6,7,8,9,10}
The computer creates a solution (not visible to you) in the form
of {A1,B2,C3,D4,E5,F6,G7,H8,I9,J10}, where the members in set A are
mapped 1-to-1 to set 2. Another example of a solution could be
{A2,B5,C10,D8,E1,F7,G6,H4,I9,J3}.
Before your first turn, you get to ask if a single, particular
pair of your choice is correct. Your question would be in the form
of {A1} (e.g. {C8}), and you receive either a 1 (meaning correct) or
0 (meaning your guess is incorrect).
Your first actual turn. You make your first guess in the form of
{A1,B2,C3,D4,E5,F6,G7,H8,I9,J10}, or any permutation of your choice.
Your guess cannot contain multiples of any item i.e. a guess of {A1,A2,A3,A4,A5,B6,B7,B8,B9,B10} is NOT a valid guess. After each
turn, the computer tells you the number of correct matches, but
NOT which matches are correct.
Repeat steps 3 and 4 until you get every match correct (i.e. a
response of 10), or until your 10 moves are up (whichever is
sooner). If you solve it before or on your 10th turn, you win $1
million. Otherwise, you lose, and some people (or letters and
numbers) go home alone to spend eternity with their 10 cats.

This is NOT a shortest code contest. The person who can solve a random matching in the least average number of guesses will be the winner. Clever game playing and calculation speed will also likely factor in. I am assuming the average number of turns will almost certainly be greater than 10, so the odds of you winning the $1 million prize (presumably paid by MTV, not me) is slim. Just how impossible is it for the cast to win the grand prize?
Note: Putting it in the {A1, B2, ...} format is not necessarily required. I simply used that form in the question to make it absolutely clear what the puzzle is. If you do not put it in this form, please just explain how to call it.
Good luck!

If you want the person who can solve it in the least average guesses to win, why not make that the winning criteria? I can't see any reason this should be a popularity contest when a perfectly valid win condition is staring us in the face.

As far as I can tell the question doesn't have anything to do with optimally playing Mastermind. It asks for a game that allows a user to play it.

@Geobits Wasn't sure how people would respond to that. I agree that's a better criteria though. It just might be hard to judge.

@Feersum I am asking for the optimal strategy. Fewest average number of turns to guess the solution will be the accepted answer.

Then pop-contest is not the tag for this.

@hosch250 Updated criterion for winner

OK, seems pretty good.

7 upvotes, 2 favorites, and no answers. I knew this was a tough one!

Python 2 (run faster if run using Pypy)
Believed to almost always guess the correct pairing in 10 rounds or lower
My algorithm is taken from my answer for mastermind as my hobby (see in Ideone). The idea is to find the guess which minimize the number of possibilities left in the worst case. My algorithm below just brute force it, but to save time, it just pick random guess if the number of possibilities left is larger than RANDOM_THRESHOLD. You can play around with this parameter to speed things up or to see better performance.
The algorithm is quite slow, on average 10s for one run if run using Pypy (if using normal CPython interpreter it's around 30s) so I can't test it on the whole permutations. But the performance is quite good, after around 30 tests I haven't seen any instance where it can't find the correct pairing in 10 rounds or lower.
Anyway, if this is used in real life show, it has plenty of time before the next round (one week?) so this algorithm can be used in real life =D
So I think it's safe to assume that on average this will find the correct pairings in 10 guesses or lower.
Try it yourself. I might improve the speed in the next few days (EDIT: it seems difficult to further improve, so I'll just leave the code as is. I tried only doing random pick, but even at size=7, it fails in 3 of the 5040 cases, so I decided to keep the cleverer method). You can run it as:
pypy are_you_the_one.py 10

Or, if you just want to see how it works, input smaller number (so that it runs faster)
To run a full test (warning: it'll take very long for size > 7), put a negative number.
Full test for size=7 (completed in 2m 32s):

...
(6, 5, 4, 1, 3, 2, 0): 5 guesses
(6, 5, 4, 2, 0, 1, 3): 5 guesses
(6, 5, 4, 2, 0, 3, 1): 4 guesses
(6, 5, 4, 2, 1, 0, 3): 5 guesses
(6, 5, 4, 2, 1, 3, 0): 6 guesses
(6, 5, 4, 2, 3, 0, 1): 6 guesses
(6, 5, 4, 2, 3, 1, 0): 6 guesses
(6, 5, 4, 3, 0, 1, 2): 6 guesses
(6, 5, 4, 3, 0, 2, 1): 3 guesses
(6, 5, 4, 3, 1, 0, 2): 7 guesses
(6, 5, 4, 3, 1, 2, 0): 7 guesses
(6, 5, 4, 3, 2, 0, 1): 4 guesses
(6, 5, 4, 3, 2, 1, 0): 7 guesses
Average count: 5.05
Max count    : 7
Min count    : 1
Num success  : 5040

If RANDOM_THRESHOLD and CLEVER_THRESHOLD are both set to a very high value (like 50000), it'll force the algorithm to find the optimal guess that minimizes the number of possibilities in the worst case. This is very slow, but very powerful. For example, running it on size=6 asserts that it can find the correct pairings in maximum 5 rounds.
Although the average is higher compared to using the approximation (which is 4.11 rounds on average), but it always succeeds, even more with one round left to spare. This further strengthen our hypothesis that when size=10, it should almost always find the correct pairings in 10 rounds or less.
The result (completed in 3m 9s):

(5, 4, 2, 1, 0, 3): 5 guesses
(5, 4, 2, 1, 3, 0): 5 guesses
(5, 4, 2, 3, 0, 1): 4 guesses
(5, 4, 2, 3, 1, 0): 4 guesses
(5, 4, 3, 0, 1, 2): 5 guesses
(5, 4, 3, 0, 2, 1): 5 guesses
(5, 4, 3, 1, 0, 2): 5 guesses
(5, 4, 3, 1, 2, 0): 5 guesses
(5, 4, 3, 2, 0, 1): 5 guesses
(5, 4, 3, 2, 1, 0): 5 guesses
Average count: 4.41
Max count    : 5
Min count    : 1
Num success  : 720

The code.
from itertools import permutations, combinations
import random, sys
from collections import Counter

INTERACTIVE = False
ORIG_PERMS = []
RANDOM_THRESHOLD = 100
CLEVER_THRESHOLD = 0

class Unbuffered():
    def __init__(self, stream):
        self.stream = stream

    def write(self, data):
        self.stream.write(data)
        self.stream.flush()

    def __getattr__(self, attr):
        self.stream.getattr(attr)
sys.stdout = Unbuffered(sys.stdout)

def init(size):
    global ORIG_PERMS
    ORIG_PERMS = list(permutations(range(size)))

def evaluate(solution, guess):
    if len(guess) == len(solution):
        cor = 0
        for sol, gss in zip(solution, guess):
            if sol == gss:
                cor += 1
        return cor
    else:
        return 1 if solution[guess[0]] == guess[1] else 0

def remove_perms(perms, evaluation, guess):
    return [perm for perm in perms if evaluate(perm, guess)==evaluation]

def guess_one(possible_perms, guessed_all, count):
    if count == 1:
        return (0,0)
    pairs = Counter()
    for perm in possible_perms:
        for pair in enumerate(perm):
            pairs[pair] += 1
    perm_cnt = len(possible_perms)
    return sorted(pairs.items(), key=lambda x: (abs(perm_cnt-x[1]) if x[1]<perm_cnt else perm_cnt,x[0]) )[0][0]

def guess_all(possible_perms, guessed_all, count):
    size = len(possible_perms[0])
    if count == 1:
        fact = 1
        for i in range(2, size):
            fact *= i
        if len(possible_perms) == fact:
            return tuple(range(size))
        else:
            return tuple([1,0]+range(2,size))
    if len(possible_perms) == 1:
        return possible_perms[0]
    if count < size and len(possible_perms) > RANDOM_THRESHOLD:
        return possible_perms[random.randint(0, len(possible_perms)-1)]
    elif count == size or len(possible_perms) > CLEVER_THRESHOLD:
        (_, next_guess) = min((max(((len(remove_perms(possible_perms, evaluation, next_guess)), next_guess) for evaluation in range(len(next_guess))), key=lambda x: x[0])
                               for next_guess in possible_perms if next_guess not in guessed_all), key=lambda x: x[0])
        return next_guess
    else:
        (_, next_guess) = min((max(((len(remove_perms(possible_perms, evaluation, next_guess)), next_guess) for evaluation in range(len(next_guess))), key=lambda x: x[0])
                               for next_guess in ORIG_PERMS if next_guess not in guessed_all), key=lambda x: x[0])
        return next_guess

def main(size=4):
    if size < 0:
        size = -size
        init(size)
        counts = []
        for solution in ORIG_PERMS:
            count = run_one(solution, False)
            counts.append(count)
            print '%s: %d guesses' % (solution, count)
        sum_count = float(sum(counts))
        print 'Average count: %.2f' % (sum_count/len(counts))
        print 'Max count    : %d' % max(counts)
        print 'Min count    : %d' % min(counts)
        print 'Num success  : %d' % sum(1 for count in counts if count <= size)
    else:
        init(size)
        solution = ORIG_PERMS[random.randint(0,len(ORIG_PERMS)-1)]
        run_one(solution, True)

def run_one(solution, should_print):
    if should_print:
        print solution
    size = len(solution)
    cur_guess = None
    possible_perms = list(ORIG_PERMS)
    count = 0
    guessed_one = []
    guessed_all = []
    while True:
        count += 1
        # Round A, guess one pair
        if should_print:
            print 'Round %dA' % count
        if should_print:
            print 'Num of possibilities: %d' % len(possible_perms)
        cur_guess = guess_one(possible_perms, guessed_all, count)
        if should_print:
            print 'Guess: %s' % str(cur_guess)
        if INTERACTIVE:
            evaluation = int(raw_input('Number of correct pairs: '))
        else:
            evaluation = evaluate(solution, cur_guess)
            if should_print:
                print 'Evaluation: %s' % str(evaluation)
        possible_perms = remove_perms(possible_perms, evaluation, cur_guess)

        # Round B, guess all pairs
        if should_print:
            print 'Round %dB' % count
            print 'Num of possibilities: %d' % len(possible_perms)
        cur_guess = guess_all(possible_perms, guessed_all, count)
        if should_print:
            print 'Guess: %s' % str(cur_guess)
        guessed_all.append(cur_guess)
        if INTERACTIVE:
            evaluation = int(raw_input('Number of correct pairs: '))
        else:
            evaluation = evaluate(solution, cur_guess)
            if should_print: print 'Evaluation: %s' % str(evaluation)
        if evaluation == size:
            if should_print:
                print 'Found %s in %d guesses' % (str(cur_guess), count)
            else:
                return count
            break
        possible_perms = remove_perms(possible_perms, evaluation, cur_guess)

if __name__=='__main__':
    size = 4
    if len(sys.argv) >= 2:
        size = int(sys.argv[1])
        if len(sys.argv) >= 3:
            INTERACTIVE = bool(int(sys.argv[2]))
    main(size)

This is truly incredible. I have ran it 100 more times, and it has yet to take more than 10 guesses to find the solution. I've seen a couple 10's, and even a couple 6's. (You say you haven't seen any instance where it can't find the correct pairing under 10 rounds. That should probably say "in 10 or less rounds", but that's just semantics.) This is fantastic! I'd assume your lambda value is some sort of measurement of entropy which allows you to make the optimal guess, but I don't see how or where it is set. This is just me being dense, not an indictment of your program. Incredible work!

It's trying to minimize the number of possibilities left in the worst case (the len(remove_perms ...) part). And yes, I meant in <=10 rounds =). Btw in the code above the really optimal guess is never made, since I put CLEVER_THRESHOLD=0, which means it'll only try to guess from the list of possibilities, although the optimal guess might be outside of this set. But I decided to disable that to save time. I added full test for size=7, showing that it always succeeds.

I have been running your code overnight with 'Clever Threshold = 0' (starting from (9,8,7,6,5,4,3,2,1,0) and working backwards through all the permutations). I am only 2050 through so far, but there has been 13 cases where it has taken 11 turns. Sample print out - (9, 8, 7, 4, 0, 6, 3, 2, 1, 5): 9 guesses, Average count: 8.29, Max count : 11, Min count : 4, Num success : 2037, Num evaluated: 2050. If 'Clever Threshold' was properly set, I bet those 11's would become 10's. Still, on average, 8.3 is pretty magnificent.

@dberm22: Yes, thank you for running this slow algorithm overnight! I ran full test on size=8 and found that the latest version has only 40308 successes (instead of 40320) if this setting is used. But that's still 99.97% success rate! Guess we can make the TV show organizer goes bankrupt.

Fast Multi-Threaded C++ Version
I know it's been a while since this thread was active, but I have a cool addition to share: Here's a C++ implementation of the minimax algorithm for Are You The One?, which uses multi-threading to speed up the evaluation of each possible guess.
This version is much faster than the Python version (over 100x faster when original Python version is set to maximum RANDOM_THRESHOLD and CLEVER_THRESHOLD). It doesn't use any random guessing, but rather evaluates all permutations and submits as its guess the permutation that eliminates the greatest number of possible solutions (given the worst-case response).
For smaller games, calling "ayto -n" will run the game on all n! possible hidden matchings, and will give you a short summary of the results at the end.
Since it's still intractable to evaluate all 10! possible hidden matchings, if you call "ayto 10", for example, the simulator makes its fixed first three guesses, then runs minimax to choose its guess and assumes that it was given the worst-case evaluation. This leads us down a "worst-case path" to a hidden vector that is presumably in the class of vectors that takes the algorithm a maximum number of guesses to identify. This conjecture has not been tested.
Up to n = 9, there hasn't been a simulation that has taken more than n turns to solve.
To test this yourself, an example compilation would be the following:
g++ -std=c++11 -lpthread -o ayto ayto.cpp

Here's a small example with output:
$ ./ayto -4
Found (0, 1, 2, 3) in 2 guesses.
Found (0, 1, 3, 2) in 3 guesses.
Found (0, 2, 1, 3) in 2 guesses.
Found (0, 2, 3, 1) in 3 guesses.
Found (0, 3, 1, 2) in 2 guesses.
Found (0, 3, 2, 1) in 2 guesses.
Found (1, 0, 2, 3) in 1 guesses.
Found (1, 0, 3, 2) in 3 guesses.
Found (1, 2, 0, 3) in 3 guesses.
Found (1, 2, 3, 0) in 3 guesses.
Found (1, 3, 0, 2) in 3 guesses.
Found (1, 3, 2, 0) in 3 guesses.
Found (2, 0, 1, 3) in 3 guesses.
Found (2, 0, 3, 1) in 3 guesses.
Found (2, 1, 0, 3) in 3 guesses.
Found (2, 1, 3, 0) in 3 guesses.
Found (2, 3, 0, 1) in 3 guesses.
Found (2, 3, 1, 0) in 3 guesses.
Found (3, 0, 1, 2) in 3 guesses.
Found (3, 0, 2, 1) in 3 guesses.
Found (3, 1, 0, 2) in 3 guesses.
Found (3, 1, 2, 0) in 3 guesses.
Found (3, 2, 0, 1) in 3 guesses.
Found (3, 2, 1, 0) in 3 guesses.
***** SUMMARY *****
Avg. Turns: 2.75
Worst Hidden Vector: (0, 1, 3, 2) in 3 turns.

Code
/* Multithreaded Mini-max Solver for MTV's Are You The One? */

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cassert>
#include <algorithm>
#include <numeric>
#include <string>
#include <vector>
#include <map>
#include <thread>
#include <cmath>

#define TEN_FACT (3628800)
#define NUM_CHUNKS (8)

using std::cout;
using std::cin;
using std::endl;
using std::vector;
using std::string;
using std::map;
using std::pair;
using std::find;
using std::abs;
using std::atoi;
using std::next_permutation;
using std::max_element;
using std::accumulate;
using std::reverse;
using std::thread;

struct args {
    vector<string> *perms;
    vector<string> *chunk;
    pair<string, int> *cd;
    int thread_id;
};

void simulate_game(const string &hidden, map<string, int> &turns_taken,
                   bool running_all);
bool picmp(const pair<string, int> &p1, const pair<string, int> &p2);
double map_avg(const map<string, int> &mp);
int nrand(int n);
int evaluate(const string &sol, const string &query);
vector<string> remove_perms(vector<string> &perms, int eval, string &query);
pair<string, int> guess_tb(vector<string> &perms, vector<string> &guessed_tb, int turn);
pair<string, int> guess_pm(vector<string> &perms, vector<string> &guessed, int turn);
void make_chunks(vector<string> &orig, vector<vector<string> > &chunks, int n);
string min_candidate(pair<string, int> *candidates, int n);
void get_score(struct args *args);
int wc_response(string &guess, vector<string> &perms);
bool prcmp(pair<int, int> x, pair<int, int> y);
void sequence_print(string s);
struct args **create_args(vector<string> &perms, pair<string, int> *cd, vector<string> &chunk, int thread_id);

vector<string> ORIGPERMS;

int main(int argc, char **argv)
{
    int sz;
    map<string, int> turns_taken;
    const string digits = "0123456789";
    bool running_all = false;

    if (argc != 2) {
        cout << "usage: 'ayto npairs'" << endl;
        return 1;
    } else {
        if ((sz = atoi(argv[1])) < 0) {
            sz = -sz;
            running_all = true;
        }
        if (sz < 3 || sz > 10) {
            cout << "usage: 'ayto npairs' where 3 <= npairs <= 10" << endl;;
            return 1;
        }
    }

    // initialize ORIGPERMS and possible_perms
    string range = digits.substr(0, sz);
    do {
        ORIGPERMS.push_back(range);
    } while (next_permutation(range.begin(), range.end()));

    if (running_all) {
        for (vector<string>::const_iterator it = ORIGPERMS.begin();
             it != ORIGPERMS.end(); ++it) {
            simulate_game(*it, turns_taken, running_all);
        }
        cout << "***** SUMMARY *****\n";
        cout << "Avg. Turns: " << map_avg(turns_taken) << endl;
        pair<string, int> wc = *max_element(turns_taken.begin(),
                                            turns_taken.end(), picmp);
        cout << "Worst Hidden Vector: ";
        sequence_print(wc.first);
        cout << " in " << wc.second << " turns." << endl;
    } else {
        string hidden = ORIGPERMS[nrand(ORIGPERMS.size())];
        simulate_game(hidden, turns_taken, running_all);
    }

    return 0;
}

// simulate_game:  run a single round of AYTO on hidden vector
void simulate_game(const string &hidden, map<string, int> &turns_taken,
                   bool running_all)
{
    vector<string> possible_perms = ORIGPERMS;
    pair<string, int> tbguess;
    pair<string, int> pmguess;
    vector<string> guessed;
    vector<string> guessed_tb;
    int e;
    int sz = hidden.size();

    if (!running_all) {
        cout << "Running AYTO Simulator on Hidden Vector: ";
        sequence_print(hidden);
        cout << endl;
    }

    for (int turn = 1; ; ++turn) {
        // stage one: truth booth
        if (!running_all) {
            cout << "**** Round " << turn << "A ****" << endl;
            cout << "Num. Possibilities: " << possible_perms.size() << endl;
        }
        tbguess = guess_tb(possible_perms, guessed_tb, turn);
        if (!running_all) {
            cout << "Guess: ";
            sequence_print(tbguess.first);
            cout << endl;
            e = tbguess.second;
            cout << "Worst-Case Evaluation: " << e << endl;
        } else {
            e = evaluate(hidden, tbguess.first);
        }
        possible_perms = remove_perms(possible_perms, e, tbguess.first);

        // stage two: perfect matching
        if (!running_all) {
            cout << "Round " << turn << "B" << endl;
            cout << "Num. Possibilities: " << possible_perms.size() << endl;
        }
        pmguess = guess_pm(possible_perms, guessed, turn);

        if (!running_all) {
            cout << "Guess: ";
            sequence_print(pmguess.first);
            cout << endl;
            e = pmguess.second;
            cout << "Worst-Case Evaluation: " << e << endl;
        } else {
            e = evaluate(hidden, pmguess.first);
        }
        if (e == sz) {
            cout << "Found ";
            sequence_print(pmguess.first);
            cout << " in " << turn << " guesses." << endl;
            turns_taken[pmguess.first] = turn;
            break;
        }

        possible_perms = remove_perms(possible_perms, e, pmguess.first);
    }
}

// map_avg:  returns average int component of a map<string, int> type
double map_avg(const map<string, int> &mp)
{
    double sum = 0.0;

    for (map<string, int>::const_iterator it = mp.begin();
         it != mp.end(); ++it) {
        sum += it->second;
    }

    return sum / mp.size();
}

// picmp:  comparison function for pair<string, int> types, via int component
bool picmp(const pair<string, int> &p1, const pair<string, int> &p2)
{
    return p1.second < p2.second;
}

// nrand:  random integer in range [0, n)
int nrand(int n)
{
    srand(time(NULL));

    return rand() % n;
}

// evaluate:  number of black hits from permutation or truth booth query
int evaluate(const string &sol, const string &query)
{
    int hits = 0;

    if (sol.size() == query.size()) {
        // permutation query
        int s = sol.size();
        for (int i = 0; i < s; i++) {
            if (sol[i] == query[i])
                ++hits;
        }
    } else {
        // truth booth query
        if (sol[atoi(query.substr(0, 1).c_str())] == query[1])
            ++hits;
    }

    return hits;
}

// remove_perms:  remove solutions that are no longer possible after an eval
vector<string> remove_perms(vector<string> &perms, int eval, string &query)
{
    vector<string> new_perms;

    for (vector<string>::iterator i = perms.begin(); i != perms.end(); i++) {
        if (evaluate(*i, query) == eval) {
            new_perms.push_back(*i);
        }
    }

    return new_perms;
}

// guess_tb:  guesses best pair (pos, val) to go to the truth booth
pair<string, int> guess_tb(vector<string> &possible_perms,
                           vector<string> &guessed_tb, int turn)
{
    static const string digits = "0123456789";
    int n = possible_perms[0].size();
    pair<string, int> next_guess;

    if (turn == 1) {
        next_guess.first = "00";
        next_guess.second = 0;
    } else if (possible_perms.size() == 1) {
        next_guess.first = "0" + possible_perms[0].substr(0, 1);
        next_guess.second = 1;
    } else {
        map<string, double> pair_to_count;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                pair_to_count[digits.substr(i, 1) + digits.substr(j, 1)] = 0;
            }
        }

        // count up the occurrences of each pair in the possible perms
        for (vector<string>::iterator p = possible_perms.begin();
             p != possible_perms.end(); p++) {
            int len = possible_perms[0].size();
            for (int i = 0; i < len; i++) {
                pair_to_count[digits.substr(i, 1) + (*p).substr(i, 1)] += 1;
            }
        }

        double best_dist = 1;
        int perm_cnt = possible_perms.size();
        for (map<string, double>::iterator i = pair_to_count.begin();
             i != pair_to_count.end(); i++) {
            if (find(guessed_tb.begin(), guessed_tb.end(), i->first)
                == guessed_tb.end()) {
                // hasn't been guessed yet
                if (abs(i->second/perm_cnt - .5) < best_dist) {
                    next_guess.first = i->first;
                    best_dist = abs(i->second/perm_cnt - .5);
                    if (i->second / perm_cnt < 0.5) // occurs in < half perms
                        next_guess.second = 0;
                    else                            // occurs in >= half perms
                        next_guess.second = 1;
                }
            }
        }
    }

    guessed_tb.push_back(next_guess.first);

    return next_guess;
}

// guess_pm:  guess a full permutation using minimax
pair<string, int> guess_pm(vector<string> &possible_perms,
                           vector<string> &guessed, int turn)
{
    static const string digits = "0123456789";
    pair<string, int> next_guess;
    vector<vector<string> > chunks;
    int sz = possible_perms[0].size();

    // on first turn, we guess "0, 1, ..., n-1" if truth booth was correct
    // or "1, 0, ..., n-1" if truth booth was incorrect
    if (turn == 1) {
        int fact, i;
        for (i = 2, fact = 1; i <= sz; fact *= i++)
            ;
        if (possible_perms.size() == fact) {
            next_guess.first = digits.substr(0, sz);
            next_guess.second = 1;
        } else {
            next_guess.first = "10" + digits.substr(2, sz - 2);
            next_guess.second = 1;
        }
    } else if (possible_perms.size() == 1) {
        next_guess.first = possible_perms[0];
        next_guess.second = possible_perms[0].size();
    } else {
        // run multi-threaded minimax to get next guess
        pair<string, int> candidates[NUM_CHUNKS];
        vector<thread> jobs;
        make_chunks(ORIGPERMS, chunks, NUM_CHUNKS);
        struct args **args = create_args(possible_perms, candidates, chunks[0], 0);

        for (int j = 0; j < NUM_CHUNKS; j++) {
            args[j]->chunk = &(chunks[j]);
            args[j]->thread_id = j;
            jobs.push_back(thread(get_score, args[j]));
        }
        for (int j = 0; j < NUM_CHUNKS; j++) {
            jobs[j].join();
        }

        next_guess.first = min_candidate(candidates, NUM_CHUNKS);
        next_guess.second = wc_response(next_guess.first, possible_perms);

        for (int j = 0; j < NUM_CHUNKS; j++)
            free(args[j]);
        free(args);
    }

    guessed.push_back(next_guess.first);

    return next_guess;
}

struct args **create_args(vector<string> &perms, pair<string, int> *cd, vector<string> &chunk, int thread_id)
{
    struct args **args = (struct args **) malloc(sizeof(struct args*)*NUM_CHUNKS);
    assert(args);
    for (int i = 0; i < NUM_CHUNKS; i++) {
        args[i] = (struct args *) malloc(sizeof(struct args));
        assert(args[i]);
        args[i]->perms = &perms;
        args[i]->cd = cd;
    }

    return args;
}

// make_chunks:  return pointers to n (nearly) equally sized vectors
//                from the original vector
void make_chunks(vector<string> &orig, vector<vector<string> > &chunks, int n)
{
    int sz = orig.size();
    int chunk_sz = sz / n;
    int n_with_extra = sz % n;
    vector<string>::iterator b = orig.begin();
    vector<string>::iterator e;

    for (int i = 0; i < n; i++) {
        int m = chunk_sz;    // size of this chunk
        if (n_with_extra) {
            ++m;
            --n_with_extra;
        }
        e = b + m;
        vector<string> subvec(b, e);
        chunks.push_back(subvec);
        b = e;
    }
}

// min_candidate:  string with min int from array of pair<string, ints>
string min_candidate(pair<string, int> *candidates, int n)
{
    int i, minsofar;
    string minstring;

    minstring = candidates[0].first;
    minsofar = candidates[0].second;
    for (i = 1; i < n; ++i) {
        if (candidates[i].second < minsofar) {
            minsofar = candidates[i].second;
            minstring = candidates[i].first;
        }
    }

    return minstring;
}

// get_score:  find the maximum number of remaining solutions over all
//             possible responses to the query s
//             this version takes a chunk and finds the guess with lowest score
//             from that chunk
void get_score(struct args *args)
{
    // parse the args struct
    vector<string> &chunk = *(args->chunk);
    vector<string> &perms = *(args->perms);
    pair<string, int> *cd = args->cd;
    int thread_id = args->thread_id;

    typedef vector<string>::const_iterator vec_iter;
    int sz = perms[0].size();

    pair<string, int> best_guess;
    best_guess.second = perms.size();
    int wc_num_remaining;
    for (vec_iter s = chunk.begin(); s != chunk.end(); ++s) {
        vector<int> matches(sz + 1, 0);
        for (vec_iter p = perms.begin(); p != perms.end(); ++p) {
            ++matches[evaluate(*s, *p)];
        }
        wc_num_remaining = *max_element(matches.begin(), matches.end());
        if (wc_num_remaining < best_guess.second) {
            best_guess.first = *s;
            best_guess.second = wc_num_remaining;
        }
    }

    cd[thread_id] = best_guess;

    return;
}

// wc_response:  the response to guess that eliminates the least solutions
int wc_response(string &guess, vector<string> &perms)
{
    map<int, int> matches_eval;

    for (vector<string>::iterator it = perms.begin(); it!=perms.end(); ++it) {
        ++matches_eval[evaluate(guess, *it)];
    }

    return max_element(matches_eval.begin(), matches_eval.end(), prcmp)->first;
}

// prcmp:  comparison function for pair<int, int> types in map
bool prcmp(pair<int, int> x, pair<int, int> y)
{
    return x.second < y.second;
}

void sequence_print(const string s)
{
    for (string::const_iterator i = s.begin(); i != s.end(); i++) {
        if (i == s.begin())
            cout << "(";
        cout << *i;
        if (i != s.end() - 1)
            cout << ", ";
        else
            cout << ")";
    }
}

I've moved this to Are You The One? on GitHub with updated, faster code.

CJam -19 turns- An Idiot's Strategy
This is not a serious answer but a demonstration.  This is an idiot's solution where he does not take into account the number of correct pairings information provided from the second part of the turn.  With completely random pairings, this takes an average of 27 weeks.  This answer is insuffienct as I have said but indicates that the odds for an intellegent group (much more intellegent that this program) is likely not as slim as you might expect.  The more intellegent algorithms i've written, however take alot more time to run so I can' actually get answers from them.
Update: The code below was updated to use state that it should remove ones that don't work if the only correct ones are ones we already knew were correct.  It was also editted to show my random "correct answer" generator.  The average result is now only 19.  It is still a dumb solution but it is better than the previous marginally.
A,{__,mr=_@@-}A*;]sedS*:Z;

ZS/:i:G;                               "Set the input (goal) to G";
{UU@{G2$==@+\)}%~;}:C;                 "This is the tool to count how many of an array agree with G";
{:Y;1$1$<{Y-}%Yaa+@@)>{Y-}%+}:S;       "for stack A X Y, sets the Xth value in the array to Y";
{:Y;1$1$<2$2$=Y-a+@@)>+}:R;            "for stack A X Y, removes Y from the Xth value in the array";

1:D;                                   "Set turn counter to one. if zero exits loop";

A,]A*                                  "array of arrays that has all possible values for an ordering";

{                                      "start of loop";

_V=(\;_GV=={V\SV):V;}{V\R}?            "Guesses a number for the first unknown. If right sets the pair; else erases it";

_[{(_,_{mr=}{;;11}?:Y\{Y-}%}A*;]_C     "guesses random possible arrangement and determines how many are right, error=11";
\_{+}*45-:Y{Y;{_11={;BY-}{}?}%}{}?\    "error correct by including the missing number";

_V={;V:X>{X\RX):X;}%~LV}{}?            "if all new are wrong, makes sure they aren't guessed again";
_A={Dp0:D;;p;}{D):D;;;}?               "If all are right, prints it an tells loop to exit.  Else increments counter";

D}g                                    "repeat from start of loop";

Also note: the sloppy error handling is because it is easier to program that then a more intellegent method.

+1 for actually being brave enough to implement a solution. I am actually quite shocked that it only takes 27 turns on average to guess the correct solution. I'd assume that as you guess correctly, subsequent matches are exponentially (well, factorially) easier to find. Thanks! I'd be interested to see if anyone can get less than 10. You have given me hope!

If 27 is surprising look at that! All joking aside I think that a solution which guarentees 10 or at least gets it on average is possible.  I just can't get such an algorithm to work in a reasonable time frame.

19...I'm even more shocked. Just a question though... in your program, where you say "Guesses a number for the first unknown. If right sets the pair; else erases it". If it's wrong...you should be adding it to the list of matches you know aren't correct, so you don't guess it again (either in the permutation, or as the separate guess).

It means erase it from the list of possibilities; I have a list of possible ones not a list of impossible ones.  Oh, and I forgot to mention that this has the male be position in array and female being numbers 0-9 (or vice versa).  I would use A5 B2 etc. format if it were a more serious submission.

Oh, I see. Never mind then. The format is not important to me...I just used that form because I thought it would be the most clear. I will include that in the question.

Actually 27 guesses is precisely the theoretical upper bound of how many turns on average this will take. Consider the first man, it'll take maximum 9 guesses to know the correct match, and an average of 5 guesses ((1+2+...+9)/9). Then it'll take maximum 8 turns for the second man to get the correct match (with average 4.5). This numbers decrease by one until we have 2 pairs left, which can be determined in 1 guess. Total we need 9+8+7+6+5+4+3+2+1 = 45 guesses at maximum, and an average of 27.

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


text:
Mondrian painting description language
This challenge consists in coding an interpreter for a Mondrian painting description language (MPDL).
Language definition
The language operates on a stack of rectangles.
A rectangle is defined by its upper left coordinate and lower right coordinate. Coordinates must be integers.
The stack is initialized with a single rectangle with attributes (1,1,254,254)
Each command has the following format:
<character><integer>
There are three commands:
v<integer> : perform a vertical split on the latest rectangle in the stack, at the position indicated by the parameter (as percentage). The source rectangle is removed from the stack and replaced with the two new rectangles that result of the split. The left rectangle is pushed on the stack, then the right rectangle. As rectangle coordinates are integers, fractions should be rounded to biggest smaller integer.
h<integer> : horizontal split. The top rectangle is pushed on the stack, then the bottom rectangle.
c<integer> : removes the latest rectangle from the stack and paints it to the color given as parameter. 1 = white, 2 = red, 3 = blue, 4 = yellow
Challenge
Write a program that takes as parameter a painting description and creates a 256x256 bitmap representation of the painted rectangles. The rectangles must be separated with a 3 pixel black line. A one or two pixel rectangle should have his non-black pixels hidden by the border black pixels.
The input can be read as a parameter or as a file, up to you. The commands should be separated by a space. You can assume that the input file has correct syntax and does not have trailing or leading spaces, tabs, etc.
The output can be directly displayed on the screen, or saved to a file, up to you.
The shortest code wins.
Test
The following source:
v25 h71 v93 h50 c4 c1 c1 c2 h71 c3 h44 c1 c1

Should produce the Composition II in Red, Blue and Yellow:

The language isn't great. v and h arguments should be in pixels

Also, I'm not sure what's the point of rotating the stack instead of popping.

Using percentages allows you to choose whatever size for the output bitmap - the result will be same (only it will be scaled)

But... why would you modify them later rather than immediately?

What are the allowed output formats? Any image format or displaying on screen are all OK?

What are the allowed input formats? Are we required to be able to handle newlines, or we may choose?

@Jan I update the question to add precisions on output/input formats. Basically : they are free.

I think a language definition using [hv]<n> followed by description of the first rectangle then the second and explicit end of particular branch (either though [c] or a new directive) would make the challenge more interesting allowing for more diverse implementation. This version basically mandates implementing the stack as in the problem definition.

@nutki You are right. We could have a functional notation as v30(h50(c1,c5),h70(v50(c1,c3),c2)). I choose the language above because I though parsing would be simpler.

Yeah something like that, but note you can still do without extra syntax elements as all operators have constant number of parameters. So the above can be still parsed when represented as v30 v50 c1 c5 h70 v50 c1 c3 c2.

@nutki Agree with you. I hesitate modifying the question, as it has already go through sandbox validation and some may have started coding it?

The example would be v25 h71 v44 c1 c1 c3 h71 c2 v93 h50 c1 c4

@SuperChafouin I know, it's up to you. You could always allow both formats of the input.

@SuperChafouin Also adopting between solutions is not that hard as the only difference to the description is that c now pops the stack and there is no r operation. But the stack operation of h and v would stay as in the original.

@SuperChafouin "Sandbox validation" isn't anything sacred :P It's your challenge and it's brand new with no answers. Its hardly a risk to add in good ideas.

Why 'to be painted' flag in the new version? Am I missing something why you wouldn't be able to paint it straight away like it the original description?

@Martin I prefer using percentages as they also carry semantics about the painting : e.g. split the rectangle at two thirds and paint it yellow. Don't think Mondrian was thinking in pixels :-) Also, no antialiasing because numbers are always rounded.

Last point, I'd like the description language to be universal and work for any picture size, even if in this specific golf, a fixed bitmap size is given.

Really hoping someone writes a solution in Piet!

Perl 5 + ImageMagick - 297
Something to start with:
sub a{my($x,$y,$X,$Y,$d)=@_;$_=shift@ARGV;
/v/?a($d=$x+($X-$x)*$'/100,$y,$X,$Y).a($x,$y,$d,$Y):
/h/?a($x,$d=$y+($Y-$y)*$'/100,$X,$Y).a($x,$y,$X,$d):
/c/&&"-fill ".qw/white red blue yellow/[$'-1]." -draw 'rectangle $x,$y $X,$Y' "}
system"convert -size 256x256 -stroke black xc: ".a(0,0,255,255)."a.gif"

Takes input on command line and generates a.gif.

Haskell - 335
import Diagrams.Prelude
import Diagrams.Backend.SVG
c=centerXY
d((x:n):i)|x=='v'=(b#scaleX s#c|||a#scaleX(1-s)#c,k)|x=='h'=(b#scaleY s#c===a#scaleY(1-s)#c,k)|x=='c'=(square 1#fc([white,red,blue,yellow]!!(read n-1)),i)where{s=(read n)/100;(a,j)=d i;(b,k)=d j}
main=getLine>>=renderSVG"a.svg"(Width 256).pad 1.02.c.lwG 0.012.fst.d.words

The program reads the instructions as one line from stdin, if this is unacceptable let me know.
Compiles into a program that takes in flags -w width -h height -o outputfile.
Outputs an "a.svg" file, if that's not immediately clear from the code. Since the output is a vector image, it's not 'pixel perfect'.
This is my first time working with Diagrams -package, feel free to point out any mistakes I made. Especially any backend that would let me output with less code would be nice.
You can see some of the first steps I took when developing the code in http://paste.hskll.org/get/1737. It differs from the code above in imports and lacks main since the paste.hskll.org provides its own main and drawing environment.

Python - 434 405 377 364 361
My first python golf. This can probably be improved A LOT, so any feedback is appreciated.
from turtle import*
a=[[1,1,254,254]]
for c in input().split():
 v,w,x,y=a.pop();p,b,f,g=int(c[1::1]),'hvc'.index(c[0]),x-v,y-w
 if b>1:goto(v,-w),color('#000',['#fff','red','#00f','#ff0'][p-1]),begin_fill(),[(fd(o),rt(90))for o in[f,g]*2],end_fill()
 else:a+=[[v,w,(x,v+(((x-v)/100)*p))[b],(w+(((y-w)/100)*p),y)[b]])],a+=[[[v,a[-1][2]][b],[a[-1][3],w][b],x,y]]

You can save a char by merging lines 4, 5 with a semicolon. Also a+=[x] instead of a.append(x). And split doesn't need an argument if separating by whitespace.

HTML + JavaScript ES6 (407)
Tested with Firefox 32.0.3

<canvas id=c width=256 height=256><script>r=[[1,1,253,253]]
p=x=>r.push(x)
o=c.getContext("2d")
o.lineWidth=3
prompt().split(" ").map(x=>{q=r.pop()
v=q[0]
b=q[1]
n=q[2]
m=q[3],{c:x=>{o.beginPath()
o.rect(v,b,n,m)
o.fillStyle=[,"#fff","red","blue","#ff0"][x]
o.fill()
o.stroke()},v:x=>{s=x/100*n|0
p([v,b,s,m])
p([v+s,b,n-s,m])},h:x=>{s=x/100*m|0
p([v,b,n,s])
p([v,b+s,n,m-s])}}[x[0]](+x.slice(1))})</script>

So much more golfable! x.charAt(0) -> x[0]; x.substr -> x.slice; white yellow -> #fff #ff0; document.getElementById("c") -> c ... and more

@edc65 Thanks! I'll improve it further tomorrow.

Thanks for the answer, but I try to test it and I have a white screen?

@SuperChafouin What browser are you using? I don't think that arrow functions (and other ES6 stuff) are really supported except in Firefox.

HTML+JavaScript (ES6) 335
Too similar to @mika answer - marking CW.

replace with function instead of split...map
spread operator
push 2 values at once
ternary operator instead of function properties

<canvas id=c><script>
c.width=c.height=256,
s=[[1,1,253,253]],
o=c.getContext('2d'),
o.translate(0.5,0.5), // to avoid anti-alias on straight lines
o.lineWidth=3,
prompt().replace(/(\S)(\d+)/g,(_,c,n)=>(
p=s.pop(o.fillStyle=[,'#fff','red','#00f','#ff0'][n]),
c<'d'?(o.fillRect(...p),o.strokeRect(...p))
:(c=c<'i'|2,
 q=[...p],
 q[c]=r=q[c]*n/100|0,
 p[c]-=r,
 p[c-2]+=r,
 s.push(q,p))))
</script>