Coin Tossing Time Travelers


19

In futuro, quando Time Travel (abbreviato in TT) sarà comune, il lancio delle monete diventerà un serio sport mentale. Per prepararci al futuro, creiamo un concorso per programmi in cui il viaggio nel tempo avverrà realmente dal punto di vista delle voci.

La competizione è un King of the Hill in stile round robin che consiste in partite di lancio di monete tra le classi Java.

Regole della partita di lancio delle monete

  • Ci sono due giocatori e 100 round.
  • In ogni round viene lanciata una moneta e in base al risultato uno dei giocatori ottiene 1 punto. Ogni giocatore ha il 50% di probabilità di segnare un punto.
  • Dopo il lancio entrambi i giocatori hanno la possibilità di controllare il tempo tirando le leve.
  • Se si tira una leva blu (ripristino del fermo) non è possibile alcun TT sul round in cui è stata utilizzata la leva o su qualsiasi round precedente. Il tentativo di TT di partecipare a questi round non avrà alcun effetto.
  • Se si tira una leva rossa (reverter), si tenta di ripristinare il tempo precedente a un round precedente. Se riesce, la memoria dell'avversario verrà ripristinata nella sua memoria prima del round scelto e anche i risultati del lancio della moneta a partire dal round scelto verranno eliminati . L'unico segno possibile per il tuo avversario riguardo al TT sarà il numero delle sue leve inutilizzate che non verranno ripristinate.
  • Ogni giocatore ha 5 leve blu e 20 rosse inutilizzate all'inizio della partita. Queste leve non sono influenzate dai TT.
  • Se non si verifica alcun TT alla fine di un centesimo round, il gioco termina e vince il giocatore con il punteggio più alto.

Dettagli

  • I round hanno un'indicizzazione basata su 1 (modulo da 1 a 100).
  • Prima del giro xti viene fornito il numero di leve blu e rosse disponibili, il lancio della moneta risulta fino al turnox (incluso) e il ricordo del tuo (ultimo)x-1 round.
  • Tirando una leva blu in tondo si xferma qualsiasi TT che abbia una destinazione in tondox o prima (blocca un TT se accade anche nello stesso round esatto).
  • Ripristinare il round xsignifica che il round successivo sarà roundx .
  • Se entrambi i giocatori scelgono di tornare alla fine di un round, il tempo viene riportato alla destinazione precedente che non è bloccata. I giocatori che hanno cercato di tornare a questo momento manterranno la loro memoria.

Dettagli tecnici

  • È necessario scrivere una classe Java che implementa l'interfaccia Bot fornita.
  • Aggiungi il tuo bot al progetto.
  • Aggiungi un'istanza del tuo Bot al Botfile Controller.java.
  • La tua classe non dovrebbe conservare informazioni tra le chiamate . (Nella maggior parte dei casi avere solo finalvariabili al di fuori delle funzioni soddisfa questo requisito.)
  • È possibile fornire informazioni al controller nel memorycampo Actiondell'oggetto restituito . Questo ti verrà restituito nel prossimo turno se non è successo alcun TT. Se si verifica un TT, riceverai la tua precedente memoria corrispondente.
  • È possibile utilizzare il totalScore()metodo della Gameclasse per ottenere il punteggio di una stringa di cronologia.

Protocollo

  • Ad ogni turno il tuo takeTurn(...)metodo viene chiamato con 5 argomenti:

    • il numero di leve blu non utilizzate
    • il numero di leve rosse non utilizzate
    • la storia del lancio della moneta, una stringa composta da 1 e 0 che segna le tue vincite e perdite nei round precedenti. Il primo personaggio corrisponde al primo lancio della moneta. (Nel primo giro la lunghezza della stringa sarà1 .)
    • una stringa, la memoria memorizzata del round precedente
    • l'indice basato su 1 di questo round
  • Ad ogni turno il tuo metodo restituisce un Actionoggetto contenente

    • un numero intero nel movecampo che descrive la tua azione:

      • 0 per nessuna azione
      • -1 per tirare una leva blu e bloccare il TT che sta attraversando questo round
      • un numero intero positivo x , non più grande del round corrente, per tirare una leva rossa e provare a tornare al roundx
      • Gli interi non validi vengono considerati come 0.
    • una stringa contenente la tua memoria di questo round che vuoi conservare. Notare che l' archiviazione della memoria non è una parte cruciale della sfida . È possibile effettuare buone voci senza memorizzare dati utili nella stringa. Al primo giro la stringa sarà una stringa vuota.

  • Il tuo metodo non dovrebbe richiedere più di 10 ms per round in media in una partita.

  • Il fallimento regolare del termine comporta la squalifica.

punteggio

  • Vincere una partita guadagna 2 punti e un pareggio guadagna 1 punto per entrambi i giocatori. La perdita non guadagna punti.
  • Il punteggio di un bot sarà il numero totale di punti raccolti.
  • Il numero di partite giocate tra ciascuna coppia di concorrenti dipenderà dal numero di voci e dalla loro velocità.

Due semplici robot di esempio vengono pubblicati come risposte.

Il controller e i primi due robot sono disponibili qui .

Risultati dei test con robot inviati fino al 3 novembre .:

Punteggi totali:

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

(Il controller si basa sul controller della sfida Cat catcher . Grazie per @flawr che lo ha fornito come base per questo.)

Bonus: un bel film di 6 minuti basato su un concetto simile.


1
Non capisco cosa significhi questa regola. 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.Cosa significa "passare per un round"?
feersum

@feersum Se ho capito bene, tirare la leva blu permanentemente "blocca" il round corrente (e quindi tutti i round precedenti) in modo che i risultati non possano essere modificati dal viaggio nel tempo. Se qualcuno tenta di TT ad un tempo precedente rispetto a quando hai tirato la leva blu, non sarà in grado di farlo.
PhiNotPi

@feersum @PhiNotPi ha ragione, questa versione è più chiara? 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,

Quando tiri la leva rossa, puoi scegliere lo stesso round in cui ti trovi attualmente per ripetere il lancio della moneta per quel round?
TheNumberOne,

@TheNumberOne Sì, è quello che fa il bot di esempio casuale .
randomra,

Risposte:


12

Analizzatore

Questo analizza il passato per fare le migliori previsioni per il futuro.

MODIFICARE: evita i tempi di leva blu. Utilizza le leve blu in modo efficace. Utilizza le leve rosse in modo più efficace. Aggiunta la scarsità per la stagione di Halloween.

EDIT: risolto da 1 errore.

EDIT:computeWinningProbability funzione migliorata . Ora usa le leve rosse e la leva blu in modo più aggressivo.

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

}

Punteggio (dal 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
Degno di nota! Il tuo bot si blocca in modo efficace e si ripristina nei momenti ottimali. Sarà molto difficile creare un bot in grado di superare questo.
TNT,

Non sono sicuro che questo bot sia bloccabile, senza usare un mucchio di voci appositamente progettate per pasticciare con questo bot e potenziare un altro 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);
    }
}

Non testato, solo una rapida pugnalata nel tentativo di creare un bot che è difficile da bloccare (perché decide quando tirare la leva rossa per lo più in modo casuale) ma che prende decisioni decenti.

Modifica: ho perso questa regola:

Se si tira una leva blu (ripristino del fermo) non è più possibile attraversare il TT in quel round

Sembra un buon motivo per usare la memoria: se ricordi di aver provato a TT in un dato round, potresti non aver avuto successo, quindi non dovresti provare a ripetere il TT in quel round. Ho modificato il mio bot per cercare di evitarlo.


4

Oracolo

Ho spudoratamente copiato del codice da Analyzer (per analizzare la memoria). Questa presentazione tenta di tirare presto una leva blu e poi lentamente aumenta il suo vantaggio. Penso che le prestazioni di questo bot compensino il brutto codice :)

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

Buon lavoro! Sapevo di non essere abbastanza aggressivo con le mie leve rosse. Ora per migliorare Analyzer. ;)
TheNumberOne

3

RegretBot

Alla fine della nostra vita l'incontro, ci pentiamo dei nostri fallimenti passati e tentiamo di tornare indietro e risolverli.

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 fa moltiplicando e dividendo per 10, usando numeri multipli di 10 e tornando a round multipli di 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);
    }
}

Modifica: ho cambiato un po 'la meccanica ora che la spiegazione di cosa succede quando viene tirata una leva blu è più chiara. Ha anche fatto un po 'di riequilibrio.


1

Casuale

La strategia di Random è la seguente:

  • bloccare con una probabilità del 10% se in testa e con le leve blu rimaste
  • viaggiare indietro di un turno (ripetendo l'ultimo round) con una probabilità del 10% se dietro di un punteggio e con le leve rosse rimaste
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

Cattivo perdente

Questo bot non usa memoria ed è sorprendentemente buono (ma non batte Analyser o 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

Vecchia scuola

Questo robot non fa mai alcuna azione poiché Oldschool non crede nel viaggio nel tempo.

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

Questo bot cerca di tracciare quando tira il blu per evitare tiri rossi in quella regione. Tirerà le leve rosse solo quando sarà significativamente indietro nel punteggio.

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

}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.