def compile(self, candidate):
        world = World(self.world)
        compiled = []
        for gene in candidate.genes:
            gene_type, gene_value = gene
            if gene_type == 'wait':
                world = world.apply_command('W')
                compiled.append('W')
                if world.terminated: break
            elif gene_type == 'move':
                destination = gene_value
                commands = pathfinder.commands_to_reach(world, destination)
                for c in commands:
                    direction = [-world.width, world.width, -1, 1, 0]['UDLRA'.index(c)]
                    if world.data[world.robot + direction] == 'W' and world.razors > 0:
                        world = world.apply_command('S')
                        compiled.append('S')
                        if world.terminated: break
                    world = world.apply_command(c)
                    compiled.append(c)
                    if world.terminated: break
            else:
                assert False, "Unrecognized gene: %s" % gene_type
            if world.terminated:
                break

        if not world.terminated:
            compiled.append('A')
        return ''.join(compiled)
    def fitness(self, candidate):
        world = World(self.world)
        world_hash = world.get_hash()
        for gene in candidate.genes:
            if time.time() > self.deadline:
                raise TimeOut
            gene_type, gene_value = gene
            if gene_type == 'wait':
                world = world.apply_command('W')
                if world.terminated:
                    break
                world_hash = world.get_hash()
            elif gene_type == 'move':
                destination = gene_value
                cache_key = (world_hash, world.robot, destination)
                cached = (cache_key in self.cache)
                if cached:
                    commands, world_hash = self.cache[cache_key]
                else:
                    commands = pathfinder.commands_to_reach(world, destination)

                #world = world.apply_commands(commands)

                for c in commands:
                    direction = [-world.width, world.width, -1, 1, 0]['UDLRA'.index(c)]
                    if world.data[world.robot + direction] == 'W' and world.razors > 0:
                        world = world.apply_command('S')
                        if world.terminated: break
                    world = world.apply_command(c)
                    if world.terminated: break

                if not cached:
                    world_hash = world.get_hash()
                    self.cache[cache_key] = (commands, world_hash)
                if world.terminated: break
            else:
                assert False, "Unrecognized gene: %s" % gene_type
        return world.score