Coin Tossing Time Du khách


19

Trong tương lai khi Time Travel (viết tắt là TT) sẽ phổ biến, việc tung đồng xu sẽ trở thành một môn thể thao trí óc nghiêm túc. Để chuẩn bị cho tương lai, chúng tôi tạo ra một cuộc thi cho các chương trình mà việc du hành thời gian sẽ thực sự xảy ra từ quan điểm của các mục.

Cuộc thi là King of the Hill theo phong cách vòng tròn bao gồm các trận đấu tung đồng xu giữa các lớp Java.

Quy tắc của trò tung đồng xu

  • Có hai người chơi và 100 vòng.
  • Trong mỗi vòng, một đồng xu được tung và dựa trên kết quả, một trong những người chơi ghi được 1 điểm. Mỗi người chơi có 50% cơ hội để ghi một điểm.
  • Sau khi tung cả hai người chơi có cơ hội kiểm soát thời gian bằng cách kéo đòn bẩy.
  • Nếu bạn kéo một đòn bẩy màu xanh (nút chặn hoàn nguyên) thì không thể thực hiện được vòng tròn mà đòn bẩy đã được sử dụng hoặc bất kỳ vòng nào trước đó nữa. Việc TT cố gắng đi đến những vòng này sẽ không có kết quả.
  • Nếu bạn kéo một đòn bẩy màu đỏ ( hoàn nguyên ), bạn cố gắng hoàn nguyên thời gian trở lại vòng trước. Nếu thành công , bộ nhớ của đối thủ sẽ được hoàn nguyên về bộ nhớ của nó trước vòng đã chọn và kết quả tung đồng xu bắt đầu từ vòng đã chọn cũng sẽ bị xóa . Dấu hiệu khả dĩ duy nhất cho đối thủ của bạn về TT sẽ là số lượng đòn bẩy chưa sử dụng của nó sẽ không được hoàn nguyên.
  • Mỗi người chơi có 5 đòn bẩy không sử dụng màu xanh và 20 màu đỏ khi bắt đầu trận đấu. Những đòn bẩy này không bị ảnh hưởng bởi TT.
  • Nếu không có TT xảy ra vào cuối vòng thứ 100, trò chơi kết thúc và người chơi có số điểm cao hơn sẽ thắng.

Chi tiết

  • Các vòng có một chỉ mục dựa trên 1 (mẫu 1 đến 100).
  • Trước vòng xbạn được cung cấp số lượng đòn bẩy màu xanh và đỏ có sẵn, đồng xu tung kết quả cho đến khi lần lượt x(bao gồm) và bộ nhớ của x-1vòng thứ (cuối cùng) của bạn .
  • Kéo một đòn bẩy màu xanh trong vòng sẽ xdừng bất kỳ TT nào có điểm đến tại vòng xhoặc trước đó (nó sẽ chặn một TT nếu nó cũng xảy ra trên cùng một vòng chính xác đó).
  • Trở lại vòng xcó nghĩa là vòng tiếp theo sẽ tròn x.
  • Nếu cả hai người chơi chọn hoàn nguyên vào cuối vòng, thời gian sẽ được hoàn nguyên về đích trước đó không bị chặn. (Các) người chơi đã cố gắng hoàn nguyên về thời điểm này sẽ giữ lại bộ nhớ của họ.

Chi tiết kỹ thuật

  • Bạn nên viết một lớp Java thực hiện giao diện Bot được cung cấp.
  • Thêm bot của bạn vào dự án.
  • Thêm một thể hiện của Bot của bạn Botvào tệp Controller.java.
  • Lớp học của bạn không nên giữ thông tin giữa các cuộc gọi . (Trong hầu hết các trường hợp chỉ có finalcác biến ngoài hàm đáp ứng yêu cầu này.)
  • Bạn có thể cung cấp thông tin cho bộ điều khiển trong memorytrường của Actionđối tượng được trả về của bạn . Điều này sẽ được trả lại cho bạn trong lượt tiếp theo nếu không có TT xảy ra. Nếu một TT xảy ra, bạn sẽ nhận được bộ nhớ tương ứng trước đó của bạn.
  • Bạn có thể sử dụng totalScore()phương thức của Gamelớp để lấy điểm của chuỗi lịch sử.

Giao thức

  • Tại mỗi lượt của bạn takeTurn(...)phương pháp được gọi với 5 đối số:

    • số lượng đòn bẩy màu xanh không sử dụng
    • số lượng đòn bẩy đỏ không sử dụng
    • lịch sử tung đồng xu, một chuỗi bao gồm 1 và 0 đánh dấu chiến thắng và thua của bạn trong các vòng trước. Ký tự đầu tiên tương ứng với việc tung đồng xu đầu tiên. (Trong vòng đầu tiên, độ dài của chuỗi sẽ là 1.)
    • một chuỗi, bộ nhớ được lưu trữ của bạn từ vòng trước
    • chỉ số 1 dựa trên vòng này
  • Ở mỗi lượt, phương thức của bạn trả về một Actionđối tượng có chứa

    • một số nguyên trong movetrường mô tả hành động của bạn:

      • 0 không có hành động
      • -1 để kéo một đòn bẩy màu xanh và chặn TT đi qua vòng này
      • một số nguyên dương x, không lớn hơn vòng hiện tại, để kéo một đòn bẩy màu đỏ và cố gắng quay trở lại vòngx
      • Số nguyên không hợp lệ được coi là 0.
    • một chuỗi chứa bộ nhớ của bạn từ vòng này mà bạn muốn lưu giữ. Lưu ý rằng việc lưu trữ bộ nhớ không phải là một phần quan trọng của thử thách . Bạn có thể tạo các mục tốt mà không lưu trữ bất kỳ dữ liệu hữu ích nào trong chuỗi. Ở vòng đầu tiên, chuỗi sẽ là một chuỗi rỗng.

  • Phương pháp của bạn sẽ mất trung bình không quá 10 ms mỗi vòng trong một trận đấu.

  • Thường xuyên thất bại trong thời gian giới hạn dẫn đến việc bị loại.

Chấm điểm

  • Chiến thắng một trận đấu kiếm được 2 điểm và một trận hòa kiếm được 1 điểm cho cả hai người chơi. Mất không kiếm được điểm.
  • Điểm của bot sẽ là tổng số điểm mà nó thu thập được.
  • Số lượng trận đấu được chơi giữa mỗi cặp thí sinh sẽ phụ thuộc vào số lượng bài dự thi và tốc độ của chúng.

Hai bot ví dụ đơn giản được đăng dưới dạng câu trả lời.

Bộ điều khiển và cặp Bots đầu tiên có sẵn ở đây .

Kết quả kiểm tra với các bot được gửi cho đến ngày 3 tháng 11.:

Tổng số điểm:

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

(Bộ điều khiển dựa trên bộ điều khiển của người bắt mèo . Cảm ơn vì @flawr đã cung cấp nó làm cơ sở cho cái này.)

Phần thưởng: một bộ phim dài 6 phút dựa trên một khái niệm tương tự.


1
Tôi không hiểu quy tắc này có nghĩa là gì. 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."Đi qua một vòng" là gì?
frageum

@feersum Nếu tôi hiểu chính xác, hãy kéo cần gạt màu xanh vĩnh viễn "khóa" vòng hiện tại (và do đó tất cả các vòng trước) để kết quả không thể được sửa đổi theo thời gian. Nếu bất cứ ai cố gắng TT đến một thời điểm sớm hơn so với khi bạn kéo cần gạt màu xanh, họ sẽ không thể.
PhiNotPi

@feersum @PhiNotPi đã đúng, phiên bản này có rõ ràng hơn không? 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

Khi bạn kéo cần gạt màu đỏ, bạn có thể chọn cùng một vòng mà bạn hiện đang làm để làm lại việc tung đồng xu cho vòng đó không?
TheNumberOne

@TheNumberOne Vâng, đó là những gì bot ví dụ ngẫu nhiên làm.
ngẫu nhiên

Câu trả lời:


12

Máy phân tích

Điều này phân tích quá khứ để đưa ra dự đoán tốt nhất cho tương lai.

EDIT: Tránh thời gian đòn bẩy màu xanh. Sử dụng đòn bẩy màu xanh một cách hiệu quả. Sử dụng đòn bẩy màu đỏ hiệu quả hơn. Thêm sự khan hiếm cho mùa Halloween.

EDIT: Đã sửa lỗi 1 lỗi.

EDIT: Cải thiện computeWinningProbabilitychức năng. Bây giờ sử dụng đòn bẩy màu đỏ và đòn bẩy màu xanh tích cực hơn.

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

}

Điểm số (kể từ ngày 2 tháng 11):

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
Ấn tượng! Bot của bạn chặn hiệu quả và hoàn nguyên vào thời điểm tối ưu. Sẽ rất khó khăn để tạo ra một bot có thể đứng đầu cái này.
TNT

Tôi không chắc chắn rằng bot này có thể dừng được, mà không sử dụng một loạt các mục được thiết kế đặc biệt để gây rối với bot này và tăng bot khác.
Mego

4

Hoài cổ

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

Không được thử nghiệm, chỉ là một cú đâm nhanh vào việc cố gắng tạo ra một bot khó chặn (bởi vì nó quyết định khi nào nên kéo đòn bẩy đỏ một cách ngẫu nhiên) nhưng điều đó đưa ra quyết định đúng đắn.

Chỉnh sửa: Tôi đã bỏ lỡ quy tắc này:

Nếu bạn kéo một đòn bẩy màu xanh (nút chặn hoàn nguyên) thì không thể có TT nào qua vòng đó nữa

Đó có vẻ là một lý do tốt để sử dụng bộ nhớ - nếu bạn nhớ cố gắng TT vào một vòng nhất định, bạn có thể đã thất bại, vì vậy bạn không nên cố gắng TT lại vòng đó. Chỉnh sửa bot của tôi để cố gắng tránh điều này.


4

Oracle

Tôi xấu hổ sao chép một số mã từ Trình phân tích (để phân tích bộ nhớ). Trình này cố gắng kéo một đòn bẩy màu xanh sớm và sau đó từ từ xây dựng vị trí dẫn đầu của mình. Tôi nghĩ rằng hiệu suất của bot này bù cho mã xấu xí :)

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

Làm tốt lắm! Tôi biết tôi đã không đủ mạnh mẽ với đòn bẩy màu đỏ của mình. Bây giờ để cải thiện Phân tích. ;)
TheNumberOne

3

Hối hận

Vào cuối cuộc đời , chúng tôi rất tiếc về những thất bại trong quá khứ và cố gắng quay lại và sửa chữa chúng.

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

Mười

Little Ten thực hiện nhiều phép nhân và chia cho 10, sử dụng các số là bội số của 10 và quay lại các vòng là bội số của 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);
    }
}

Chỉnh sửa: Bây giờ đã thay đổi cơ học một chút rằng giải thích về những gì xảy ra khi kéo một đòn bẩy màu xanh là rõ ràng hơn. Cũng đã làm một chút tái cân bằng.


1

Ngẫu nhiên

Chiến lược của Random là như sau:

  • chặn với 10% cơ hội nếu dẫn đầu và còn lại đòn bẩy màu xanh
  • quay trở lại một lượt (phát lại vòng cuối cùng) với 10% cơ hội nếu đứng sau điểm số và còn lại đòn bẩy màu đỏ
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

Người thua cuộc tồi

Bot này không sử dụng bộ nhớ và tốt đến mức đáng ngạc nhiên (nhưng nó không đánh bại được Trình phân tích hoặc 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

Trường cũ

Bot này không bao giờ thực hiện bất kỳ hành động nào vì Oldschool không tin vào việc du hành thời gian.

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

Bot Deja Vu

Bot này cố gắng theo dõi khi nó kéo màu xanh để tránh màu đỏ kéo vào khu vực đó. Sẽ chỉ kéo đòn bẩy màu đỏ khi đáng kể phía sau trong điểm số.

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

}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.