Viajeros del tiempo que lanzan monedas


19

En el futuro, cuando el viaje en el tiempo (abreviado como TT) sea común, el lanzamiento de monedas se convertirá en un deporte mental serio. Para prepararnos para el futuro, creamos una competencia para programas en los que viajar en el tiempo realmente sucederá desde los puntos de vista de las entradas.

La competencia es un King of the Hill de round-robin que consiste en partidos de lanzamiento de monedas entre clases Java.

Reglas del partido de lanzamiento de monedas

  • Hay dos jugadores y 100 rondas.
  • En cada ronda se lanza una moneda y, según el resultado, uno de los jugadores obtiene 1 punto. Cada jugador tiene un 50% de posibilidades de ganar un punto.
  • Después del lanzamiento, ambos jugadores tienen la oportunidad de controlar el tiempo tirando de las palancas.
  • Si tira de una palanca azul (revertir el tope) no es posible TT a la vuelta que se utilizó la palanca o cualquier vuelta anterior. El intento de TT de ir a estas rondas no tendrá efecto.
  • Si tira de una palanca roja (reverter) , intenta revertir el tiempo a una ronda anterior. Si tiene éxito, la memoria del oponente se revertirá. a su memoria antes de la ronda elegida y los resultados del lanzamiento de la moneda a partir de la ronda elegida también se eliminarán . El único signo posible para tu oponente sobre el TT será el número de palancas no utilizadas que no se revertirán.
  • Cada jugador tiene 5 palancas azules y 20 rojas sin usar al comienzo del partido. Estas palancas no se ven afectadas por los TT.
  • Si no ocurre un TT al final de una ronda número 100, el juego termina y gana el jugador con el puntaje más alto.

Detalles

  • Las rondas tienen una indexación basada en 1 (forma 1 a 100).
  • Antes de la ronda x, se le proporciona el número de palancas azules y rojas disponibles, los resultados del lanzamiento de la moneda hasta el turno x(inclusive) y el recuerdo de su (último)x-1 ronda.
  • Al tirar de una palanca azul en la ronda, se xdetiene cualquier TT que tenga un destino en la ronda xo antes (bloquea un TT si sucede en la misma ronda exacta también).
  • Volver a la ronda xsignifica que la próxima ronda será redonda x.
  • Si ambos jugadores eligen revertir al final de una ronda, el tiempo se revierte al destino anterior que no está bloqueado. Los jugadores que intentaron volver a este tiempo mantendrán su memoria.

Detalles técnicos

  • Debería escribir una clase Java implementando la interfaz Bot proporcionada.
  • Agrega tu bot al proyecto.
  • Agregue una instancia de su Bot al Botarchivo Controller.java.
  • Su clase no debe guardar información entre llamadas . (En la mayoría de los casos, tener solo finalvariables fuera de las funciones satisface este requisito).
  • Puede proporcionar información al controlador en el memorycampo de su Actionobjeto devuelto . Esto se le devolverá en el próximo turno si no sucedió TT. Si ocurre un TT, recibirá la memoria anterior correspondiente.
  • Puede usar el totalScore()método de la Gameclase para obtener la puntuación de una cadena de historial.

Protocolo

  • En cada turno takeTurn(...)se llama a su método con 5 argumentos:

    • la cantidad de palancas azules no utilizadas
    • la cantidad de palancas rojas no utilizadas
    • el historial de lanzamiento de monedas, una cadena que consiste en 1 y 0 que marcan sus ganancias y pérdidas en las rondas anteriores. El primer personaje corresponde al primer lanzamiento de moneda. (En la primera ronda, la longitud de la cuerda será1 ).
    • una cadena, su memoria almacenada de la ronda anterior
    • el índice basado en 1 de esta ronda
  • En cada giro, su método devuelve un Actionobjeto que contiene

    • un número entero en el movecampo que describe su acción:

      • 0 para ninguna acción
      • -1 tirar de una palanca azul y bloquear los TT que pasan por esta ronda
      • un entero positivo x , no mayor que la ronda actual, para tirar de una palanca roja e intentar volver a la rondax
      • Los enteros no válidos se tratan como 0.
    • una cadena que contiene su memoria de esta ronda que desea conservar. Tenga en cuenta que almacenar memoria no es una parte crucial del desafío . Puede realizar buenas entradas sin almacenar datos útiles en la cadena. En la primera ronda, la cadena será una cadena vacía.

  • Su método no debería demorar más de 10 ms por ronda en promedio en un partido.

  • El incumplimiento regular del límite de tiempo resulta en la descalificación.

Puntuación

  • Ganar un partido gana 2 puntos y un empate gana 1 punto para ambos jugadores. La pérdida no gana puntos.
  • La puntuación de un bot será el número total de puntos que recolectó.
  • El número de partidos jugados entre cada par de concursantes dependerá del número de entradas y su velocidad.

Dos ejemplos simples de bots se publican como respuestas.

El controlador y los primeros Bots están disponibles aquí. .

Resultados de la prueba con bots enviados hasta el 3 de noviembre .:

Puntajes totales:

Oldschool: 3163
Random: 5871
RegretBot: 5269
Nostalgia: 8601
Little Ten: 8772
Analyzer: 17746
NoRegretsBot: 5833
Oracle: 15539
Deja Vu: 5491
Bad Loser: 13715

(El controlador se basa en el controlador del desafío Cat catcher . Gracias por @flawr que lo proporciona como base para este.)

Bonificación: una bonita película de 6 minutos basada en un concepto similar.


1
No entiendo lo que significa esta regla. If you pull a blue lever (revert stopper) no TT is possible through that round anymore. TT's attempting to go through the round will have no effect.¿Qué es "pasar por una ronda"?
feersum

@feersum Si entiendo correctamente, jalar la palanca azul "bloquea" permanentemente la ronda actual (y, por lo tanto, todas las rondas anteriores) para que los resultados no puedan modificarse por el viaje en el tiempo. Si alguien intenta realizar un TT antes de que haya tirado de la palanca azul, no podrá hacerlo.
PhiNotPi

@feersum @PhiNotPi tiene razón, ¿esta versión es más clara? If you pull a blue lever (revert stopper) no TT is possible to the round the lever was used or any earlier round anymore. TT's attempting to go to these rounds will have no effect.
randomra

Cuando tire de la palanca roja, ¿puede elegir la misma ronda en la que se encuentra actualmente para rehacer el lanzamiento de la moneda para esa ronda?
TheNumberOne

@TheNumberOne Sí, eso es lo que hace el bot de ejemplo aleatorio .
randomra

Respuestas:


12

Analizador

Esto analiza el pasado para hacer las mejores predicciones para el futuro.

EDITAR: evita los tiempos de palanca azul. Utiliza palancas azules de manera efectiva. Utiliza palancas rojas de manera más efectiva. Más miedo para la temporada de Halloween.

EDITAR: corregido por 1 error.

EDITAR:computeWinningProbability Función mejorada . Ahora usa palancas rojas y palanca azul de forma más agresiva.

//Boo!
package bots;

import main.Action;
import main.Game;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Created 10/24/15
 *
 * @author TheNumberOne
 */
public class Analyzer implements Bot{

    @Override
    public String getName(){
        return "Analyzer";
    }

    @Override
    public Action takeTurn(int blue_levers, int red_levers, String history,
                           String memory, int roundNumber) {
        /*System.out.println(Game.totalScore(history) + " : " + history);
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
        }*/
        int roundsLeft = 100 - roundNumber;
        int myScore = (Game.totalScore(history) + roundNumber) / 2; //My number of wins.
        int enemyScore = roundNumber - myScore;                     //Enemy's number of wins.
        Map<Integer, Double> bestRounds = new HashMap<>();
        int timeLimit = 0;

        Scanner scanner = new Scanner(memory);
        if (scanner.hasNext()){     //No memory, first turn.
            boolean triedTimeTravel = scanner.nextBoolean();
            if (triedTimeTravel){
                int time = scanner.nextInt();
                if (roundNumber > time) {     //Failed.
                    timeLimit = time;
                }
            }
            timeLimit = Math.max(timeLimit, scanner.nextInt());
            int size = scanner.nextInt();
            for (int i = 0; i < size; i++) {
                bestRounds.put(scanner.nextInt(), scanner.nextDouble());
            }
        } else {
            bestRounds.put(1, 0.5);
        }

        clean(bestRounds, roundNumber, timeLimit);
        double winningProb = computeWinningProbability(myScore, enemyScore, roundsLeft);
        String newMemory = computeMemory(bestRounds, roundNumber, winningProb);

        if (winningProb >= new double[]{1.5, .75, .7, .65, .6, .55}[blue_levers]){ //Ensure success ... slowly.
            return getAction(-1, newMemory, timeLimit, roundNumber);
        }

        int bestRound = bestRound(bestRounds);
        double bestRoundProb = bestRounds.get(bestRound);

        if ((winningProb <= bestRoundProb - .05 || winningProb < .5 && bestRoundProb > winningProb) && red_levers > 0){
            return getAction(bestRound, newMemory, timeLimit, roundNumber);  //Let's find the best past.
        } else {
            return getAction(0, newMemory, timeLimit, roundNumber); //Let's wait it out :)
        }
    }

    //Should be combined with computeMemory.
    private static Action getAction(int actionNum, String newMemory, int timeLimit, int roundNumber){
        if (actionNum == -1){
            timeLimit = Math.max(timeLimit, roundNumber);
            newMemory = "false " + timeLimit + " " + newMemory;
            return new Action(actionNum, newMemory);
        }
        if (actionNum == 0){
            return new Action(actionNum, "false " + timeLimit + " " + newMemory);
        }
        if (actionNum > 0){
            return new Action(actionNum, "true " + actionNum + " " + timeLimit + " " + newMemory);
        }
        return null;
    }

    private static int bestRound(Map<Integer, Double> bestRounds) {
        int best = 0;           //If no previous rounds ... just go forward a round.
        double bestScore = -1;
        for (Map.Entry<Integer, Double> entry : bestRounds.entrySet()){
            if (entry.getValue() > bestScore){
                best = entry.getKey();
                bestScore = entry.getValue();
            }
        }
        return best;
    }

    private static String computeMemory(Map<Integer, Double> map, int roundNumber, double winningProb) {
        StringBuilder builder = new StringBuilder();
        builder.append(map.size() + 1).append(" ");
        for (Map.Entry<Integer, Double> entry : map.entrySet()){
            builder.append(entry.getKey()).append(" ").append(entry.getValue()).append(" ");
        }
        builder.append(roundNumber + 1).append(" ").append(winningProb);
        return builder.toString();
    }

    private static void clean(Map<Integer, Double> data, int round, int timeLimit) {
        data
                .entrySet()
                .stream()
                .filter(entry -> entry.getKey() > round || entry.getKey() <= timeLimit)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList()).forEach(data::remove);
    }

    private static double computeWinningProbability(int myScore, int enemyScore, int roundsLeft){ //Too complex for IntelliJ
        int height = myScore - enemyScore;
        double total = 0.0;
        for (int i = Math.max(height - roundsLeft, 2); i <= height + roundsLeft; i += 2){
            total += prob(roundsLeft, height, i);
        }
        total += prob(roundsLeft, height, 0) / 2;
        return total;
    }

    private static double prob(int roundsLeft, int height, int i){
        double prob = 1;
        int up = i - height + (roundsLeft - Math.abs(i - height))/2;
        int down = roundsLeft - up;
        int r = roundsLeft;
        int p = roundsLeft;
        while (up > 1 || down > 1 || r > 1 || p > 0){  //Weird algorithm to avoid loss of precision.
            //Computes roundsLeft!/(2**roundsLeft*up!*down!)

            if ((prob >= 1.0 || r <= 1) && (up > 1 || down > 1 || p > 1)){
                if (p > 0){
                    p--;
                    prob /= 2;
                    continue;
                } else if (up > 1){
                    prob /= up--;
                    continue;
                } else if (down > 1){
                    prob /= down--;
                    continue;
                } else {
                    break;
                }
            }
            if (r > 1) {
                prob *= r--;
                continue;
            }
            break;
        }
        return prob;
    }

}

Puntuación (desde el 2 de noviembre):

Total Scores:
Oldschool: 3096
Random: 5756
RegretBot: 5362
Nostalgia: 8843
Little Ten: 8929
Analyzer: 17764
NoRegretsBot: 5621
Oracle: 15528
Deja Vu: 5281
Bad Loser: 13820

1
¡Impresionante! Su bot se bloquea de manera efectiva y se revierte en momentos óptimos. Va a ser muy difícil crear un bot que pueda superar este.
TNT

No estoy seguro de que este bot se pueda detener, sin usar un montón de entradas específicamente diseñadas para meterse con este bot y potenciar otro bot.
Mego

4

Nostalgia

package bots;

import main.Action;
import main.Game;

public class Nostalgia implements Bot {

    @Override
    public String getName() {
        return "Nostalgia";
    }

    @Override
    public Action takeTurn(int blue_levers, int red_levers, String history,
            String memory, int roundNumber) {

        int current_score = Game.totalScore(history);

        // wait until the end to use blue levers
        if (current_score > 0 && blue_levers >= (100 - roundNumber)) {
            return new Action(-1, memory);
        }

        // become increasingly likely to go back as the gap between the good old days
        // and the horrible present increases
        if (current_score < 0 && red_levers > 0) {
            //identify the best time to travel back to
            int best_score = -100;
            int good_old_days = 1;
            int past_score = 0;

            int unreachable_past = 0;
            if(memory != "") {
              unreachable_past = Integer.parseInt(memory, 10);
            }

            for(int i = unreachable_past; i<roundNumber ; i++) {
              if(history.charAt(i) == '1') {
                past_score += 1;
                if(past_score > best_score) {
                  best_score = past_score;
                  good_old_days = i + 1;
                }
              }
              else {
                past_score -= 1;
              }
            }
            if(roundNumber >= 95 || Math.random() < (best_score - current_score) / 100.0) {
              return new Action(good_old_days, Integer.toString(good_old_days));
            }
        }

        // if neither action was needed do nothing
        return new Action(0, memory);
    }
}

No probado, solo una puñalada rápida para tratar de hacer un bot que es difícil de bloquear (porque decide cuándo tirar de la palanca roja principalmente al azar) pero eso toma decisiones decentes.

Editar: me perdí esta regla:

Si tira de una palanca azul (tope de reversa) ya no es posible TT en esa ronda

Esa parece ser una buena razón para usar la memoria: si recuerdas haber intentado realizar un TT en una ronda determinada, es posible que hayas fallado, por lo que no deberías intentar volver a TT en esa ronda. Edité mi bot para tratar de evitar esto.


4

Oráculo

Copié descaradamente algún código de Analyzer (para analizar la memoria). Esta sumisión trata de tirar de una palanca azul temprano y luego aumenta lentamente su ventaja. Creo que el rendimiento de este bot compensa el código feo :)

package bots;

import java.util.*;
import java.util.Map.Entry;
import main.*;

public class Oracle implements Bot {

    @Override
    public String getName() {
        return "Oracle";
    }

    @Override
    public Action takeTurn(int blue_levers, int red_levers, String history, String memory, int roundNumber) {
        int roundsLeft = 100 - roundNumber;
        Map<Integer, Integer> rounds = new HashMap<>();
        int myScore = (Game.totalScore(history) + roundNumber) / 2;
        int difference = myScore*2 - roundNumber;
        int highestBlockedRound = -1;
        int bestScore = 0;
        boolean hasUsedBlueLever = false;

        Scanner scanner = new Scanner(memory);
        if (scanner.hasNext()) {
            //timeTravel toRound highestBlockedRound hasUsedBlueLever bestScore rounds round1 percent1 round2 percent2 round3 percent3...
            boolean triedTravel = scanner.nextBoolean();
            int time = scanner.nextInt();
            if (triedTravel){
                if (roundNumber > time) {
                    highestBlockedRound = time;
                }
            }
            highestBlockedRound = Math.max(highestBlockedRound, scanner.nextInt());

            hasUsedBlueLever = scanner.nextBoolean();
            bestScore = scanner.nextInt();

            int size = scanner.nextInt();
            for (int i = 0; i < size && i < roundNumber; i++) {
                int number = scanner.nextInt();
                int diff = scanner.nextInt();
                if (number < roundNumber) {
                    rounds.put(number, diff);
                }
            }
        }
        rounds.put(roundNumber, difference);
        final int blockedRound = highestBlockedRound;

        int roundToRevert = 0;
        if (rounds.size() > 2) {
            Optional<Entry<Integer, Integer>> bestRound = rounds.entrySet()
                    .stream()
                    .filter(x -> x.getKey() >= blockedRound && x.getKey() <= roundNumber)
                    .sorted(Comparator
                        .comparingInt((Entry<Integer, Integer> x) -> x.getValue()*-1)
                        .thenComparingInt(x -> x.getKey()))
                    .findFirst();
            if (bestRound.isPresent()) {
                roundToRevert = bestRound.get().getKey();
            }
        }

        if (roundsLeft + Game.totalScore(history) <= 0 && red_levers > 0) {
            roundToRevert = highestBlockedRound+1;
        } else if (blue_levers > 0 && roundToRevert == roundNumber && ((hasUsedBlueLever && difference >= bestScore*1.5) || (!hasUsedBlueLever && difference > 1))) {
            roundToRevert = -1;
            hasUsedBlueLever = true;
            bestScore = difference;
            highestBlockedRound = roundNumber;
        } else if (red_levers > 0 && roundToRevert > 0 && rounds.get(roundToRevert) > difference+2) {
            roundToRevert += 1;
        } else {
            roundToRevert = 0;
        }

        StringBuilder sb = new StringBuilder();
        sb.append(roundToRevert > 0).append(' ');
        sb.append(roundToRevert).append(' ');
        sb.append(highestBlockedRound).append(' ');
        sb.append(hasUsedBlueLever).append(' ');
        sb.append(bestScore).append(' ');
        sb.append(rounds.size()).append(' ');
        rounds.entrySet().stream().forEach((entry) -> {
            sb.append(entry.getKey()).append(' ').append(entry.getValue()).append(' ');
        });
        String mem = sb.toString().trim();
        scanner.close();
        return new Action(roundToRevert, mem);
    }
}

¡Buen trabajo! Sabía que no estaba siendo lo suficientemente agresivo con mis palancas rojas. Ahora para mejorar el analizador. ;)
TheNumberOne

3

LamentoBot

Al final de nuestra vida, el partido, lamentamos nuestros fracasos pasados ​​e intentamos volver y arreglarlos.

package bots;

import main.Action;
import main.Game;

public final class RegretBot implements Bot {

    @Override
    public String getName() {
        return "RegretBot";
    }

    @Override
    public Action takeTurn(int blue_levers, int red_levers, String history, String memory, int roundNumber) {
        int actionNum = 0;
        if(roundNumber == 100) {
            // if it's the end of the game and we're losing, go back
            //  in time to the first loss, in hopes of doing better
            if(Game.totalScore(history)<=0 && red_levers > 0) {
                actionNum = history.indexOf("0")+1;
            }
            // if we're winning at the end, pull a blue lever if we can,
            //  to prevent our opponent from undoing our victory
            else if(blue_levers > 0) {
                actionNum = -1;
            }
        }
        // we don't need no stinkin' memory!
        return new Action(actionNum, null);
    }

}

2

Pequeño diez

Little Ten multiplica y divide mucho entre 10, usando números que son múltiplos de 10 y volviendo a las rondas que son múltiplos de 10.

package bots;

import main.Action;
import main.Game;

public class LittleTen implements Bot {

    @Override
    public String getName() {
        return "Little Ten";
    }

    @Override
    public Action takeTurn(int blue_levers, int red_levers, String history, String memory, int roundNumber) {
        int score = Game.totalScore(history);
        char c = history.charAt(history.length() - 1);
        if (memory.isEmpty())
            memory = "1";

        if (roundNumber == 100) {
            if (score >= 0)
                // We're tied or ahead by the end of the match. Prevent time
                // travel if we can; otherwise whatever happens happens.
                return new Action(blue_levers > 0 ? -1 : 0, memory);
            else {
                // Travel to earlier rounds the farther behind we are if we can
                // (of course using 10 as a reference)
                if (red_levers > 0) {
                    int i = Integer.parseInt(memory);
                    int round = score <= -10 ? i : 100 - ((100 - i) / (11 + (score <= -10 ? -10 : score)));
                    return new Action(round, memory);
                }
            }
        }
        else if (score >= 7 + roundNumber / 20 && blue_levers > 0) {
            // We're ahead; we don't want to lose our lead, especially if the
            // match is close to ending. But we don't want to use up our blue
            // levers too quickly.
            int choice = (int) (Math.random() * 100),
                bound = (roundNumber / 10 + 1) * 5 - ((6 - blue_levers) * 5 - 2);
            if (choice < bound) {
                memory = String.valueOf(roundNumber);
                return new Action(-1, memory);
            }
        }
        else if (score <= -3) {
            // Possibly use a red lever if we're falling too far behind
            if (red_levers > 0) {
                int choice = (int) (Math.random() * 100),
                    bound = score <= -11 ? 90 : 10 * (-3 - score + 1);
                if (choice < bound) {
                    // Check the first round that is the lower multiple of ten
                    // and decide if we've been successful up to that point; if
                    // so, travel back to that round, otherwise go back 10 more
                    int round = roundNumber / 10 * 10;
                    if (round < 10)
                        return new Action(1, memory);
                    String seq = history.substring(0, round-1);
                    int minRound = Integer.parseInt(memory);
                    while (Game.totalScore(seq) <= 0 && round > 10 && round > minRound) {
                        round -= 10;
                        seq = history.substring(0, round-1);
                    }
                    if (round == 0)
                        round = 1;
                    return new Action(round, memory);
                }
            }
        }
        return new Action(0, memory);
    }
}

Editar: cambió la mecánica un poco ahora que la explicación de lo que sucede cuando se tira de una palanca azul es más clara. También hice un poco de reequilibrio.


1

Aleatorio

La estrategia de Random es la siguiente:

  • bloque con una probabilidad del 10% si está a la cabeza y le quedan palancas azules
  • retrocede un turno (repite la última ronda) con un 10% de posibilidades si está atrasado en el puntaje y le quedan palancas rojas
package bots;

import main.Action;
import main.Game;

public class RandomBot implements Bot {

    @Override
    public String getName() {
        return "Random";
    }

    @Override
    public Action takeTurn(int blue_levers, int red_levers, String history,
            String memory, int roundNumber) {

        // if in the lead and has blocks left, blocks with a 10% chance
        if (Game.totalScore(history) > 0 && blue_levers > 0
                && Math.random() > 0.9) {
            return new Action(-1, null);
        }

        // if behind and has travels left, travel back the current step to
        // replay it with a 10% chance
        if (Game.totalScore(history) < 0 && red_levers > 0
                && Math.random() > 0.9) {
            return new Action(roundNumber, null);
        }

        // if neither action were needed do nothing
        return new Action(0, null);
    }
}

1

NoRegretsBot

package bots;

import main.Action;
import main.Game;

public final class NoRegretsBot implements Bot {

    @Override
    public String getName() {
        return "NoRegretsBot";
    }

    @Override
    public Action takeTurn(int blue_levers, int red_levers, String history, String memory, int roundNumber) {
        // every 20 turns, pull a blue lever to lock in the past
        // hopefully this will thwart some of those pesky time-travelers
        return new Action(roundNumber%20==0?-1:0, null);
    }

}

1

Mal perdedor

Este bot no usa memoria y es sorprendentemente bueno (pero no supera a Analyzer u Oracle).

package main;

import bots.Bot;

/**
 * Created 11/2/15
 *
 * @author TheNumberOne
 */
public class BadLoser implements Bot{
    @Override
    public String getName() {
        return "Bad Loser";
    }

    @Override
    public Action takeTurn(int blue_levers, int red_levers, String history, String memory, int roundNumber) {
        if (history.contains("00") && red_levers > 0){       //Subtract a zero for better performance against
            return new Action(history.indexOf("00") + 1, "");// Analyzer and Nostalgia, and worse performance 
                                                             // against everything else.
        }
        int wins = 0;
        for (char c : history.toCharArray()){
            wins += c - '0';
        }
        if (wins >= new int[]{101, 51, 40, 30, 20, 10}[blue_levers]){
            return new Action(-1, "");
        }
        return new Action(0, "");
    }
}

0

Vieja escuela

Este bot nunca realiza ninguna acción, ya que Oldschool no cree en los viajes en el tiempo.

package bots;

import main.Action;

public class OldschoolBot implements Bot {

    @Override
    public String getName() {
        return "Oldschool";
    }

    @Override
    public Action takeTurn(int blue_levers, int red_levers, String history,
            String memory, int roundNumber) {       
        // never tries to block or travel at all
        return new Action(0, null);
    }
}

0

Deja Vu Bot

Este bot intenta rastrear cuando tira del azul para evitar que el rojo entre en esa región. Solo tirará de las palancas rojas cuando esté significativamente atrás en la puntuación.

package bots;

import main.*;

public class Dejavu implements Bot
{
    @Override
    public String getName()
    {
        return "Deja Vu";
    }

@Override
public Action takeTurn(int blue_levers, int red_levers, String history,
                       String memory, int roundNumber) {

    if(roundNumber == 1)
    {
        memory = "-1";
    }
    int[] blevers = getBlueLevers(memory);
    char[] hist = history.toCharArray();
    int ms = 0;
    int ts = 0;
    int rl = -1;
    boolean bl = false;
    boolean url = false;

    for(int i = 0; i < hist.length; i++)
    {
        switch(hist[i])
        {
            case '1':
            ms++;
            break;
            case '0':
            ts++;
            break;
        }
    }

    if(ts - ms >= 10)
    {   
        for(rl = hist.length - 1; ts - ms <= 5 && rl >= 0; rl--)
        {
            switch(hist[rl])
            {
                case '1':
                ms--;
                break;
                case '0':
                ts--;
                break;
            }
        }
        url = true;
    }

    if(ms - ts >= 7)
    {
        bl = true;
        url = false;
        memory += "," + roundNumber;
    }

    for(int i = 0; i < blevers.length; i++)
    {
        if(rl <= blevers[i])
        {
            rl = blevers[i] + 1;
        }
    }

    if(url)
    {
        return new Action(rl, memory);
    }
    else if(bl)
    {
        return new Action(-1, memory);
    }
    else
    {
        return new Action(0, memory);
    }              
}

private int[] getBlueLevers(String s)
{
    String[] b = s.split(",");

    int[] bl = new int[b.length];
    for(int i = 0; i < b.length; i++)
    {
        bl[i] = Integer.parseInt(b[i]);
    }

    return bl;
}

}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.