Voyageurs dans le temps


19

À l'avenir, lorsque le voyage dans le temps (abrégé en TT) sera courant, le lancer de pièces deviendra un sport mental sérieux. Pour préparer l'avenir, nous créons un concours de programmes où les voyages dans le temps se feront vraiment du point de vue des participants.

Le concours est un tournoi à la ronde King of the Hill consistant à lancer des matchs entre les classes Java.

Règles du match de lancer de pièces

  • Il y a deux joueurs et 100 tours.
  • À chaque tour, une pièce est lancée et en fonction du résultat, l'un des joueurs marque 1 point. Chaque joueur a 50% de chances de marquer un point.
  • Après le lancer, les deux joueurs ont la possibilité de contrôler le temps en tirant sur les leviers.
  • Si vous tirez sur un levier bleu (butée de retour), aucun TT n'est possible pour le tour auquel le levier a été utilisé ou pour tout tour précédent. La tentative de TT d'aller à ces tours n'aura aucun effet.
  • Si vous tirez sur un levier rouge (inverseur), vous essayez de ramener le temps à un ancien tour. En cas de réussite, la mémoire de l' adversaire sera rétablie dans sa mémoire avant le tour choisi et les résultats du tirage au sort à partir du tour choisi seront également supprimés . Le seul signe possible pour votre adversaire au sujet du TT sera le nombre de ses leviers inutilisés qui ne seront pas inversés.
  • Chaque joueur dispose de 5 leviers bleus et 20 rouges inutilisés au début du match. Ces leviers ne sont pas affectés par les TT.
  • Si aucun TT ne se produit à la fin d'un 100e tour, la partie se termine et le joueur avec le score le plus élevé gagne.

Détails

  • Les rondes ont une indexation basée sur 1 (de 1 à 100).
  • Avant le tour, xvous disposez du nombre de leviers bleus et rouges disponibles, le résultat du lancer de pièces jusqu'au tour x(inclus) et la mémoire de votre (dernier) x-1tour.
  • Tirer un levier bleu en round xarrête tous les TT qui ont une destination au round xou avant (cela bloque un TT si cela se produit également sur ce même round).
  • Revenir au tour xsignifie que le prochain tour sera rond x.
  • Si les deux joueurs choisissent de revenir à la fin d'un tour, le temps revient à la destination précédente qui n'est pas bloquée. Le ou les joueurs qui ont tenté de revenir à cette heure garderont leur mémoire.

Détails techniques

  • Vous devez écrire une classe Java implémentant l'interface Bot fournie.
  • Ajoutez votre bot au projet.
  • Ajoutez une instance de votre Bot au Botfichier Controller.java.
  • Votre classe ne doit pas conserver d'informations entre les appels . (Dans la plupart des cas, le fait de n'avoir que des finalvariables en dehors des fonctions satisfait à cette exigence.)
  • Vous pouvez donner des informations au contrôleur dans le memorychamp de votre Actionobjet retourné . Cela vous sera rendu au tour suivant si aucun TT ne s'est produit. Si un TT se produit, vous recevrez votre mémoire antérieure correspondante.
  • Vous pouvez utiliser la totalScore()méthode de la Gameclasse pour obtenir le score d'une chaîne d'historique.

Protocole

  • A chaque tour, votre takeTurn(...)méthode est appelée avec 5 arguments:

    • le nombre de leviers bleus inutilisés
    • le nombre de leviers rouges inutilisés
    • l'historique de lancer de pièces, une chaîne composée de 1 et de 0 marquant vos victoires et vos pertes lors des tours précédents. Le premier caractère correspond au premier lancer de pièces. (Au premier tour, la longueur de la chaîne sera 1.)
    • une chaîne, votre mémoire stockée du tour précédent
    • l'indice basé sur 1 de ce tour
  • A chaque tour, votre méthode retourne un Actionobjet contenant

    • un entier dans le movechamp décrivant votre action:

      • 0 pour aucune action
      • -1 pour tirer un levier bleu et bloquer les TT qui traversent ce tour
      • un entier positif x, pas plus grand que le tour en cours, pour tirer un levier rouge et essayer de revenir au tourx
      • Les entiers non valides sont traités comme 0.
    • une chaîne contenant votre mémoire de ce tour que vous souhaitez conserver. Notez que le stockage de la mémoire n'est pas une partie cruciale du défi . Vous pouvez faire de bonnes entrées sans stocker de données utiles dans la chaîne. Au premier tour, la chaîne sera une chaîne vide.

  • Votre méthode ne devrait pas prendre plus de 10 ms par tour en moyenne dans un match.

  • Le non-respect régulier du délai entraîne la disqualification.

Notation

  • Gagner un match rapporte 2 points et un match nul rapporte 1 point aux deux joueurs. La perte ne rapporte aucun point.
  • Le score d'un bot sera le nombre total de points qu'il a collectés.
  • Le nombre de matchs joués entre chaque paire de candidats dépendra du nombre de participations et de leur vitesse.

Deux exemples de robots simples sont affichés comme réponses.

Le contrôleur et les deux premiers robots sont disponibles ici .

Résultats des tests avec des bots soumis jusqu'au 3 novembre:

Scores totaux:

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

(Le contrôleur est basé sur le contrôleur du défi Cat catcher . Merci pour @flawr de le fournir comme base pour celui-ci.)

Bonus: un joli film de 6 minutes basé sur un concept similaire.


1
Je ne comprends pas ce que signifie cette règle. 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'est-ce que "passer par un tour"?
feersum

@feersum Si je comprends bien, tirer le levier bleu de façon permanente "verrouille" le tour en cours (et donc tous les tours précédents) afin que les résultats ne puissent pas être modifiés par le voyage dans le temps. Si quelqu'un tente de TT à un moment plus tôt que lorsque vous avez tiré le levier bleu, il ne pourra pas.
PhiNotPi du

@feersum @PhiNotPi a raison, cette version est-elle plus claire? 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

Lorsque vous tirez sur le levier rouge, pouvez-vous choisir le même tour sur lequel vous êtes actuellement pour refaire le tirage au sort pour ce tour?
TheNumberOne du

@TheNumberOne Oui, c'est ce que fait le robot d'exemple aléatoire .
randomra

Réponses:


12

Analyseur

Cela analyse le passé pour faire les meilleures prévisions pour l'avenir.

EDIT: évite les temps de levier bleus. Utilise efficacement les leviers bleus. Utilise plus efficacement les leviers rouges. Ajout de la peur pour la saison d'Halloween.

EDIT: corrigé par 1 erreur.

EDIT:computeWinningProbability Fonction améliorée . Utilise désormais des leviers rouges et bleus plus agressivement.

//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;
    }

}

Score (depuis le 2 novembre):

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
Impressionnant! Votre bot bloque efficacement et revient à des moments optimaux. Il va être très difficile de créer un bot capable de dépasser celui-ci.
TNT

Je ne suis pas sûr que ce bot soit stoppable, sans utiliser un tas d'entrées spécialement conçues pour jouer avec ce bot et booster un autre bot.
Mego

4

Nostalgie

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);
    }
}

Non testé, juste un coup rapide pour essayer de faire un bot difficile à bloquer (car il décide quand tirer le levier rouge principalement au hasard) mais qui prend des décisions décentes.

Edit: j'ai raté cette règle:

Si vous tirez sur un levier bleu (butée de retour), aucun TT n'est possible à travers ce tour

Cela semble être une bonne raison d'utiliser de la mémoire - si vous vous souvenez avoir essayé de TT à un tour donné, vous avez peut-être échoué, vous ne devriez donc pas essayer de revenir à ce tour. J'ai édité mon bot pour essayer d'éviter cela.


4

Oracle

J'ai copié sans vergogne du code à partir d'Analyzer (pour analyser la mémoire). Cette soumission essaie de tirer un levier bleu au début, puis renforce lentement son avance. Je pense que les performances de ce bot compensent le code laid :)

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);
    }
}

Bon travail! Je savais que je n'étais pas assez agressif avec mes leviers rouges. Maintenant, pour améliorer Analyzer. ;)
TheNumberOne

3

RegretBot

À la fin de notre vie le match, nous regrettons nos échecs passés, et essayons de revenir en arrière et de les réparer.

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

Little Ten

Little Ten multiplie et divise beaucoup par 10, en utilisant des nombres qui sont des multiples de 10, et en revenant aux tours qui sont des multiples 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);
    }
}

Edit: modification de la mécanique un peu maintenant que l'explication de ce qui se passe lorsqu'un levier bleu est tiré est plus claire. A également fait un peu de rééquilibrage.


1

Aléatoire

La stratégie de Random est la suivante:

  • bloquer avec une chance de 10% s'il est en tête et a des leviers bleus à gauche
  • revenir en arrière d' un tour (rejouer le dernier tour) avec 10% de chance s'il est en retard dans le score et qu'il reste des leviers rouges
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

Mauvais perdant

Ce bot n'utilise aucune mémoire et est étonnamment bon (mais il ne bat pas Analyzer ou 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

Vieille école

Ce bot ne fait jamais aucune action car Oldschool ne croit pas au voyage dans le temps.

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

Ce bot essaie de suivre quand il tire le bleu pour éviter que le rouge ne tire dans cette région. Ne tirera les leviers rouges qu'en cas de retard significatif dans le score.

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;
}

}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.