Đấu giá hóa đơn đô la


33

Đây là một thách thức KOTH cho trò chơi đấu giá hóa đơn đô la trong lý thuyết trò chơi. Trong đó, một đô la đang được bán cho người trả giá cao nhất. Giá thầu tăng theo mức tăng 5 và người thua cũng trả giá thầu của họ. Ý tưởng là cả hai người chơi leo thang cuộc chiến đấu thầu vượt xa giá trị của đồng đô la để cắt lỗ.

Hãy hy vọng bot của bạn thông minh hơn thế.

Bạn sẽ tạo một bot để chơi trò chơi này bằng cách mở rộng net.ramenchef.dollarauction.DollarBidderlớp. Bạn phải thực hiện nextBidphương thức trả về giá thầu tiếp theo của bot của bạn với giá thầu trước đó của bot khác. Nếu cần, bạn cũng có thể sử dụng newAuctionphương pháp để đặt lại cho mỗi phiên đấu giá với lớp bot của đối thủ.

public abstract class DollarBidder {
    /**
     * Used by the runner to keep track of scores.
     */
    long score = 0;

    /**
     * (Optional) Prepare for the next auction.
     *
     * @param opponent The class of the opponent's bot.
     */
    public void newAuction(Class<? extends DollarBidder> opponent) {}

    /**
     * Bid on the dollar. Bidding ends if the bid is
     * not enough to top the previous bid or both bids
     * exceed $100.
     *
     * @param opponentsBid How much money, in cents,
     *  that the opponent bid in the previous round. If
     *  this is the first round in the auction, it will
     *  be 0.
     * @return How much money to bid in this round, in
     *  cents.
     */
    public abstract int nextBid(int opponentsBid);
}

Đấu thầu diễn ra cho đến khi một trong những điều sau đây xảy ra:

  • nextBidném một ngoại lệ. Nếu điều này xảy ra, bot đã ném ngoại lệ trả giá thầu trước đó của họ và bot khác nhận được đồng đô la miễn phí.
  • Hoặc bot không trả đủ tiền để đứng đầu giá thầu trước đó. Nếu điều này xảy ra, cả hai bot trả giá thầu của họ (người thua cuộc trả giá thầu trước đó của họ) và người chiến thắng sẽ nhận được một đô la.
  • Cả hai bot trả giá hơn 100 đô la. Nếu điều này xảy ra, cả hai bot đều trả 100 đô la và không bot nào nhận được đô la.

2 phiên đấu giá được tổ chức cho mỗi sự kết hợp của bot. Bots được tính bằng tổng lợi nhuận họ kiếm được qua các phiên đấu giá đó. Điểm cao nhất sẽ thắng.

Ví dụ

GreedyBot

import net.ramenchef.dollarauction.DollarBidder;

public class GreedyBot extends DollarBidder {
    @Override
    public int nextBid(int opponentsBid) {
        return opponentsBid + 5;
    }
}

OnlyWinningMove

import net.ramenchef.dollarauction.DollarBidder;

public class OnlyWinningMove extends DollarBidder {
    @Override
    public int nextBid(int opponentsBid) {
        return 0;
    }
}

AnalystBot

Đừng sử dụng điều này như một khuôn mẫu cho các bot có đầu óc phân tích; sử dụng ImprovedAnalystBotthay thế.

import net.ramenchef.dollarauction.DollarBidder;

// yes, this is a poor implementation, but I'm not
// going to waste my time perfecting it
public class AnalystBot extends DollarBidder {
    private DollarBidder enemy;

    @Override
    public void newAuction(Class<? extends DollarBidder> opponent) {
        try {
            enemy = opponent.newInstance();
            enemy.newAuction(this.getClass());
        } catch (ReflectiveOperationException e) {
            enemy = null;
        }
    }

    @Override
    public int nextBid(int opponentsBid) {
        if (enemy == null)
            return 0;

        return enemy.nextBid(95) >= 100 ? 0 : 95;
    }
}

AnalystKiller

import net.ramenchef.dollarauction.DollarBidder;

public class AnalystKiller extends DollarBidder {
    private static int instances = 0;
    private final boolean tainted;

    public AnalystKiller() {
        this.tainted = instances++ != 0;
    }

    @Override
    public int nextBid(int opponentsBid) {
        if (tainted)
            throw new RuntimeException("A mysterious error occurred! >:)");

        return 0;
    }
}

Quy tắc bổ sung

  • Sơ hở tiêu chuẩn bị cấm.
  • Phá hoại các bot khác được cho phép, nhưng cố gắng thay đổi khả năng hiển thị trường / phương thức sẽ dẫn đến bí ẩn SecurityException s . Một ngoại lệ là khiến một bot khác phá vỡ giới hạn 500ms.
  • Bots không thể truy cập gói người chạy trừ khi mở rộng DollarBidderlớp.
  • Tất cả các phương pháp sẽ trở lại trong 500ms hoặc ít hơn.
  • Bots không cần phải được xác định.
  • Giá thầu của bạn không cần là bội số của 5.
  • $ 1 = 100
  • Kết quả sẽ được đăng vào ngày 24 tháng 4 năm 2018.

Á quân trên GitHub

Các kết quả

Xem các vòng cá nhân ở đây.

MTargetedBot: $14.30
BuzzardBot: $9.83
BluffBot: $9.40
RiskRewardBot: $9.35
SecretBot: $8.50
LuckyDiceBot: $7.28
CounterBot: $6.05
MBot: $5.40
StackTraceObfuscaterBot: $5.20
EvilBot: $4.80
MarginalBot: $4.60
TargetValueBot: $4.59
InflationBot: $4.27
UpTo200: $4.20
InsiderTradingBot: $1.90
MimicBot: $1.50
BorkBorkBot: $1.22
DeterrentBot: $0.95
MarginalerBot: $0.00
RandBot: $-4.45
BreakEvenAsap: $-7.00
AnalystOptimizer: $-13.95
DeterredBot: $-1997.06
ScoreOverflowBot: $-21474844.15
MirrorBot: $-21475836.25

Xin chúc mừng MTargetedBotvới lợi nhuận $ 14,30!


11
Thách thức này về cơ bản dễ bị tổn thương với One-Upping. Vì tôi biết lớp của đối thủ của mình, thật dễ dàng để chọn chiến lược tốt nhất chống lại nó. (Sau đó, một người nào đó xuất hiện và có thể tạo ra bot của tôi , v.v.)
Nathan Merrill

2
" Giá thầu tăng theo mức tăng 5 ". Bạn không có bất cứ điều gì trong mã của mình để xác thực điều này, mặc dù .. LuckyDiceBotví dụ: giá thầu tăng dần một 2-12cách ngẫu nhiên ..
Kevin Cruijssen

4
Ngoài ra: nếu bot của tôi khiến các bot khác vượt quá giới hạn 500ms thì sao?
Nathan Merrill

4
@RamenChef Chúng ta đang nói về mã độc ở đây. Điều gì sẽ xảy ra nếu tôi phát hiện khi một bot khác gọi cho tôi và gọi Thread.s ngủ (1000)?
Nathan Merrill

3
Tôi là VTC vì không rõ những gì phá hoại được phép và những gì không. OP đã không cho phép các bài nộp "tấn công người chạy" (điều này rất mơ hồ) và không có ranh giới rõ ràng giữa mã độc được phép và mã độc đó không (Làm thế nào để bạn xác định bot nào khiến bot mất quá nhiều thời gian ?)
Nathan Merrill

Câu trả lời:


2

MTargetedBot

public class MTargetedBot extends MBot {

    @Override
    protected int calcBid(int opponentsBid, boolean isPeeking, boolean isSubPeeking) {
        Class c = this.rivalClass;

        switch (c.getSimpleName()) {
            case "AnalystBot":
                if (isPeeking && !isSubPeeking) {
                    throw new RuntimeException();
                } else if (isPeeking) {
                    return 66666;
                }
                break;
            case "MirrorBot":
                if (isPeeking && !isSubPeeking) {
                    throw new RuntimeException();
                } else if (isPeeking) {
                    return 0;
                }
                break;
            case "GreedyBot":
            case "LuckyDiceBot":
            case "InflationBot":
            case "TargetValueBot":
                // not playing with ya
                return 0;
            case "MimicBot":
            case "BuzzardBot":
            case "MarginalBot":
            case "MarginalerBot":
            case "BluffBot":
            case "MBot":
                // go away, gimme easy money
                return isPeeking ? 66666 : 5;
            case "RandBot":
                // me or noone
                return 100;
            case "SecretBot":
                return 10;
            case "AnalystKiller":
            case "OnlyWinningMove":
            case "EvilBot":
            case "StackTraceObfuscaterBot":
                // easy
                return opponentsBid + 5;
        }

        return super.calcBid(opponentsBid, isPeeking, isSubPeeking);
    }
}
  • Dựa trên MBot cập nhật
  • Sử dụng phương thức tương tự như CounterBot, nhưng với một số phương thức được tinh chỉnh để đánh mạnh hơn một số đối thủ, cũng nên dễ đọc hơn
  • Trên đối thủ không xác định mặc định là MBot strat

1
Điều này không công bằng.
Joshua

@Joshua Điều gì đặc biệt không công bằng về giải pháp này theo ý kiến ​​của bạn?
mleko

Biết tên của đối thủ của bạn.
Joshua

@Joshua một nửa các giải pháp sử dụng thông tin đó. Chúng tôi thậm chí đã viết cho tác giả rằng điều này nên được thay đổi hoặc One-Upping sẽ xảy ra, anh ấy đã từ chối thay đổi thử thách - vì vậy đây là
mleko

1
Đã làm ....
Joshua

15

MimicBot

import net.ramenchef.dollarauction.DollarBidder;

import java.util.Set;
import java.util.HashSet;

public class MimicBot extends AbstractAnalystCounterBot {

    private final Set<Class<? extends DollarBidder>> bidders = new HashSet<>();
    private DollarBidder reference = null;

    // A benchmark class. Not MarginalBot because of proposed rule changes.
    public static class BidFive extends DollarBidder {
        public int nextBid(int o) {
            return 5;
        }
    }


    public MimicBot() {
        bidders.add(OnlyWinningMove.class);
        bidders.add(GreedyBot.class);
        bidders.add(BidFive.class);
    }


    @Override
    public void newAuction(Class<? extends DollarBidder> opponent) {
        DollarBidder enemy;
        reference = null;
        try {
            enemy = opponent.newInstance();
        } catch (Throwable t) {
            return;
        }

        if (!bidders.contains(opponent))
            bidders.add(opponent);

        Class<? extends DollarBidder> leader = OnlyWinningMove.class;
        int best = 0;

        for (Class<? extends DollarBidder> audition : bidders) {
            try {
                enemy.newAuction(MimicBot.class);
            } catch (Throwable t) {
                reference = new GreedyBot(); // Deterrence.
                break;
            }

            DollarBidder tryout;
            try {
                tryout = audition.newInstance();
                tryout.newAuction(opponent);
            } catch (Throwable t) {
                continue;
            }

            int tryoutScore = -100000;
            /* This code was copy-pasted from the *
             * runner, with significant changes. */
            int bid1 = 0, bid2 = 0;
            while (true) {
                int next;
                try {
                    next = enemy.nextBid(bid2);
                } catch (Throwable t) {
                    tryoutScore = 100;
                    break;
                }
                if (next < bid2 + 5) {
                    if (bid2 > 0) {
                        tryoutScore = 100 - bid1;
                    }
                    break;
                }
                if (next > 10000 && bid2 > 10000) {
                    tryoutScore = -10000;
                    break;
                }
                bid1 = next;

                try {
                    next = tryout.nextBid(bid1);
                } catch (Throwable t) {
                    tryoutScore = -bid2;
                    break;
                }
                if (next < bid1 + 5) {
                    tryoutScore = -bid2;
                    break;
                }
                if (next > 10000 && bid1 > 10000) {
                    tryoutScore = -10000;
                    break;
                }
                bid2 = next;
            }
            /* End of copy-pasted code. */

            if (tryoutScore > best) {
                best = tryoutScore;
                leader = audition;
            }
        }

        try {
            reference = leader.newInstance();
        } catch (Throwable t) {
            reference = new OnlyWinningMove();
        }
        reference.newAuction(opponent);
    }


    @Override
    public int nextBid(int opponentsBid) {
        try {
            return reference.nextBid(opponentsBid);
        } catch (Throwable t) {
            return 5;
        }
    }
}

Bò thần. Tôi dự kiến ​​nó sẽ đơn giản để viết, sau đó đã dành 3 giờ cho nó.

Về bản chất, MimicBotgiữ một danh sách đang chạy của các bot có sẵn. Khi nó đi đến một cuộc đấu giá mới, nó chạy qua danh sách để tìm kiếm một cuộc đấu giá hiệu quả nhất trước đối thủ hiện tại. Sau đó, nó sử dụng bot đó như một "tài liệu tham khảo" trong phiên đấu giá.

Đối với mục đích thử nghiệm, tốt nhất nên sử dụng tập hợp con ngẫu nhiên của các bài nộp hoặc toàn bộ. Nó bắt đầu với GreedyBot, MimicBotvà một bot nữa chỉ trả giá 5.


11

InsiderTradingBot

Theo tinh thần câu trả lời của @ StephenLeppik, InsiderTradingBot biết tất cả các đối thủ của mình và hiểu chiến lược của họ. Động thái của bạn, Stephen.

import net.ramenchef.dollarauction.DollarBidder;

public class InsiderTradingBot extends DollarBidder {
  private static boolean analystNutcracker = false;
  private int bid;

  @Override
  public void newAuction(Class<? extends DollarBidder> opponent) {
    if (opponent.equals(DeterredBot.class) ||
        opponent.equals(OnlyWinningMove.class) ||
        opponent.equals(MirrorBot.class)) {
      // I can do this ^.^
      bid = 5;
    } else if (opponent.equals(AnalystKiller.class)) {
      // Outbid 'em >:D
      bid = 10;
    } else if (opponent.equals(BreakEvenAsap.class) ||
               opponent.equals(BorkBorkBot.class) ||
               opponent.equals(DeterrentBot.class)) {
      // Break even quicker!
      bid = 100;
    } else if (opponent.equals(InsiderTradingBot.class)) {
      // I'm probably a simulation inside MirrorBot
      bid = 0;
    } else if (opponent.equals(Analyst.class)) {
      // Let's fight the Analyst with the power of global variables
      bid = 100;
      analystNutcracker = true;
    } else {
      // Welp
      bid = 0;
    }
  }

  @Override
  public int nextBid(int opponentsBid) {
    if ((opponentsBid == 95) && analystNutcracker) {
      analystNutcracker = false;
      return 0;
    }
    return bid;
  }

};

1
Không, giao dịch nội gián sẽ là nếu RichJerkbot tạo ra một ngoại lệ cụ thể cho bot của bạn và trả giá 0 đô la cho nó.
Nissa

Vẫn còn quá sớm để tối ưu hóa các câu trả lời khác. Ngoài ra, nó AnalystBot, không phải Analyst.
RamenChef

8
Có lẽ cần phải có một quy tắc "tên lớp sẽ được chọn ngẫu nhiên".
dùng202729

1
@ user202729 Làm thế nào về "không tham chiếu trực tiếp đến các lớp"?
RamenChef

1
Tôi muốn thấy điều này xử lý MimicBot.
Nissa

8

MarginalBot

import net.ramenchef.dollarauction.DollarBidder;

public class MarginalBot extends DollarBidder {
    private DollarBidder rival;

    @Override
    public void newAuction(Class<? extends DollarBidder> opponent) {
        try {
            rival = opponent.newInstance();
            rival.newAuction(this.getClass());
        } catch (Throwable t) {
            try {
                rival = opponent.newInstance();
                rival.newAuction(null);
            } catch (Throwable h) {
                rival = null;
            }
        }
    }

    @Override
    public int nextBid(int opponentsBid) {
        if (opponentsBid == 0) {
            try {
                if (rival.nextBid(5) < 10) {
                    return 5;
                }
            } catch (Throwable t) {
                //do nothing.
            }
        }
        return 0;
    }
}

Rất đơn giản, nó cố gắng xác định xem đối thủ có tranh chấp giá thầu tối thiểu hay không và nếu không, sẽ đặt nó.

MarginalerBot

import net.ramenchef.dollarauction.DollarBidder;

public class MarginalerBot extends DollarBidder {
    private DollarBidder rival;
    private int bidCount;

    @Override
    public void newAuction(Class<? extends DollarBidder> opponent) {
        bidCount = 0;

        try {
            rival = opponent.newInstance();
            rival.newAuction(this.getClass());
        } catch (Throwable t) {
            try {
                rival = opponent.newInstance();
                rival.newAuction(null);
            } catch (Throwable h) {
                rival = null;
            }
        }
    }

    @Override
    public int nextBid(int opponentsBid) {
        bidCount += 1;

        for (int iBid = opponentsBid + 5; iBid < 100; iBid = iBid + 5) {
            if (bidCount > 0) {
                break;
            }

            try {
                if (rival.nextBid(iBid) < iBid + 5) {
                    return iBid;
                }
            } catch (Throwable t) {
                //do nothing.
            }
        }
        return 0;
    }
}

Một phiên bản mới hơn, thông minh hơn của MarginalBot kiểm tra xem liệu nó có thể thực hiện bất kỳ động thái kiếm tiền nào mà không cần cạnh tranh hay không, thay vì chỉ hy vọng giành chiến thắng với mức tối thiểu.

Vì nó cùng họ với bot trước đây của tôi, nhưng vượt qua các chiến lược cố gắng đánh bại nó, tôi nghĩ rằng một mục mới trong cùng một bài là cách trình bày hợp lý nhất.

Chỉnh sửa 1: Thực hiện một thay đổi nhỏ đối với phương thức NewAraction để tối ưu hóa với các bot loại phân tích khác.

Chỉnh sửa 2: Thực hiện thay đổi đối với MarginalerBot để giảm thiểu tổn thất trước các chiến lược lén lút hoặc không xác định.


Chào mừng đến với PPCG!
Martin Ender

1
Thật đơn giản, nhưng nó đánh bại tất cả các bot khác bằng một tỷ lệ khá lớn!
RamenChef

8

MirrorBot

Làm cho kẻ thù chơi với chính nó.

import net.ramenchef.dollarauction.DollarBidder;

public class MirrorBot extends DollarBidder{

    private DollarBidder enemy;

    @Override
    public void newAuction(Class<? extends DollarBidder> opponent) {
        try {
            enemy = opponent.newInstance();
            enemy.newAuction(this.getClass());
        } catch (ReflectiveOperationException e) {
            enemy = null;
        }
    }

    @Override
    public int nextBid(int opponentsBid){
        if (enemy == null)
            return (opponentsBid >= 95) ? 0 : (opponentsBid + 5);
        try {
            return enemy.nextBid(opponentsBid);
        } catch (Throwable e) {
            System.out.println("haha no");
            return (opponentsBid >= 95) ? 0 : (opponentsBid + 5);
        }
    }
}

6
Bạn nuk Analystngoạn mục.
Silvio Mayolo

@SilvioMayolo thế nào?
dkudriavtsev

Mirror cố gắng giả lập Nhà phân tích chơi với chính nó, dẫn đến một chồng tràn.
Silvio Mayolo

8

Chỉnh sửa : Các thay đổi được nhắm mục tiêu trong lớp DollarBidder đã phá vỡ bot này.

ScoreOverflowBot

import net.ramenchef.dollarauction.DollarBidder;

public class ScoreOverflowBot extends DollarBidder {
  boolean betBig = true;

  @Override
  public int nextBid(int opponentsBid) {
    if(betBig)
    {
      betBig = false;
      return 2147483645;
    }
    else
      return 105;
  }
}

Sau 1 lần đấu giá, điểm của nó sẽ là -2147483645 nhưng lần tiếp theo sẽ mất 5 ¢ hoặc 105 làm cho điểm số dương và rất lớn. Tất cả các tổn thất khác sau đó sẽ không đáng kể.

Trong phiên đấu giá đầu tiên, nó cũng sẽ đặt cược cho GreedyBot -2147483646 không chia hết cho 5.


scoređược bảo vệ trọn gói. Bot của bạn không thể truy cập nó.
RamenChef

@RamenChef Rất tiếc, đã xóa CheatBot
Mùa đông

Không có quy tắc chống lại "tấn công người chạy", chỉ "truy cập" nó, điều này không làm. Tôi khuyên bạn nên sửa lỗi, giải quyết vấn đề này :)
Nathan Merrill

7

TargetValueBot

import java.util.Random;
import net.ramenchef.dollarauction.DollarBidder;

public class TargetValueBot extends DollarBidder {
    private int target;

    @Override
    public void newAuction(Class<? extends DollarBidder> opponent) {
        Random rand = new Random();
        target = 100;
        for (int i = 0; i < 20; i++) {
            target += rand.nextInt(2) * 10 - 5;
        }
    }

    @Override
    public int nextBid(int opponentsBid) {
        if (opponentsBid >= target) {
            return 0;
        } else {
            return opponentsBid + 5;
        }
    }
}

Không thể kiểm tra điều này vào lúc này, vì vậy xin vui lòng cho tôi biết nếu nó bị hỏng.

Về cơ bản, chọn một giá trị cho đồng đô la và trả giá cao hơn đối thủ cho đến khi chúng tôi vượt quá giá trị đó.


6

BorkBorkBot

import net.ramenchef.dollarauction.DollarBidder;

public class BorkBorkBot extends DollarBidder{
  @Override
  public int nextBid(int opponentsBid){
    return (opponentsBid >= 95) ? 0 : (opponentsBid + 5);
  }
}

Cho đi nếu nó không thể hòa vốn.


6

RandBot

import net.ramenchef.dollarauction.DollarBidder;
import java.util.concurrent.ThreadLocalRandom;

public class RandBot extends DollarBidder {

    @Override
    public int nextBid(int opponentsBid) {
        return ThreadLocalRandom.current().nextInt(21) * 5;
    }
}

Nó phải được thực hiện.


" Giá thầu tăng theo mức tăng 5 ". Bot của bạn hiện không làm như vậy.
Kevin Cruijssen

1
@KevinCruijssen Hội chợ đủ. Tôi cũng đã thay đổi giới hạn trên để nó có thể trả giá toàn bộ $ 1, chỉ trong trường hợp,
Neil

6

Răn đe

import net.ramenchef.dollarauction.DollarBidder;

public class DeterrentBot extends DollarBidder {
    @Override
    public int nextBid(int opponentsBid) {
        return opponentsBid > 5 ? 100 : opponentsBid + 5;
    }
}

Nỗ lực thuyết phục bất kỳ bot có đầu óc phân tích nào rằng động thái chiến thắng duy nhất là không chơi.


1
Tôi đã nhận thấy rằng bình luận hơi khó hiểu của tôi "Joshua? Có phải bạn không?" đã bị xóa. Vì vậy, chỉ cần làm rõ, đó là một tham chiếu đến một câu nói nổi tiếng từ bộ phim WarGames: "động thái chiến thắng duy nhất là không chơi" . (Joshua là biệt danh của WOPR .)
Arnauld

5

LuckyDiceBot

LuckyDiceBot chỉ tin tưởng súc sắc của mình. Anh ta tung hai con xúc xắc, cộng tổng vào giá trị của người trả giá hiện tại và trả giá nhiều như vậy. Nếu nó không đủ để vượt qua giá thầu của đối thủ, anh ta sẽ cắt lỗ và tiếp tục đi.

import net.ramenchef.dollarauction.DollarBidder;
import java.util.Random;

public class LuckyDiceBot extends DollarBidder {
  private Random random;

  public LuckyDiceBot() {
    random = new Random();
  }

  @Override
  public int nextBid(int opponentsBid) {
    int d1 = random.nextInt(6) + 1;
    int d2 = random.nextInt(6) + 1;
    return opponentsBid + d1 + d2;
  }

};

2
Làm thế nào để cắt lỗ hoặc dừng lỗ? Nếu nó luôn thêm cuộn xúc xắc của mình vào giá thầu của đối thủ thì bạn sẽ luôn đặt giá thầu nhiều hơn. Sự ngẫu nhiên có thể gây nhầm lẫn cho một bot phân tích đầy đủ, tôi thích khái niệm này.
Freiheit

Nếu cuộn là 4 hoặc ít hơn (không thể thống kê, nhưng cuối cùng sẽ xảy ra), thì giá thầu không đủ để đánh bại đối thủ và cuộc đấu giá kết thúc.
Silvio Mayolo

Hai điều: 1. @Freiheit là đúng và bot này sẽ tiếp tục đấu thầu cho đến khi nó giành chiến thắng cho dù cao như thế nào. opponentsBidtrong nextBid(int opponentsBid)tổ chức tổng thầu đối thủ của bạn đã chào vậy, đến nay, không phải đấu thầu tiếp theo của nó. Một thuật ngữ tốt hơn cho phương pháp sẽ là raise(như thuật ngữ Poker) imho. 2. Bot của bạn không tăng bit lên 5, do đó, xác nhận một trong các quy tắc. Nếu những vấn đề này được khắc phục, tôi vẫn thích khái niệm này, bởi vì các bot phân tích sẽ không thể khắc phục và do đó rất có thể bạn sẽ giành chiến thắng khá thường xuyên.
Kevin Cruijssen

5

Đã răn đe

import net.ramenchef.dollarauction.DollarBidder;

public class DeterredBot extends DollarBidder {
    private int deterrence;
    public void newAuction(Class<? extends DollarBidder> opponent) {
        if (opponent.equals(DeterrentBot.class)) {
            deterrence = 1;
        } else if (opponent.equals(LuckyDiceBot.class)) {
            deterrence = -1;
        } else {
            deterrence = 0;
        }
    }
    @Override
    public int nextBid(int opponentsBid) {
        switch (deterrence) {
        case 0:
            return 0;
        case -1:
            return opponentsBid + 5;
        case 1:
            // Holy shit, the fuzz! Hide the money!
            return 100001;
        }
        throw new RuntimeException("Darn hackers!");
    }
}

DeterredBot kiếm bộn tiền nhờ đánh bạc bất hợp pháp của mình với LuckyDiceBot. Vì vậy, tất nhiên khi cảnh sát (DeterrentBot) đến, anh ta phải nhanh chóng xử lý thu nhập của mình bằng một cách nào đó, chẳng hạn như đấu thầu vào phiên đấu giá tiếp theo.


4

Lạm phát

import net.ramenchef.dollarauction.DollarBidder;

public class InflationBot extends DollarBidder {
    private int target = -5;

    @Override
    public void newAuction(Class<? extends DollarBidder> opponent) {
        target += 5;
    }

    @Override
    public int nextBid(int opponentsBid) {
        if (opponentsBid >= target) {
            return 0;
        } else {
            return opponentsBid + 5;
        }
    }
}

Không thể kiểm tra điều này vào lúc này, vì vậy xin vui lòng cho tôi biết nếu nó bị hỏng.

Mỗi vòng, giá trị của đồng đô la tăng lên.


Điều này sẽ rất tuyệt vời khi đối đầu với MirrorBot, MarginalerBot, và có lẽ cả MimicBot.
Nissa

@StephenLeppik Đó là những gì tôi đã nghĩ khi tôi thực hiện nó. Vẫn còn nhiều điểm yếu.
Mnemonic

+1, tôi thích ý tưởng. Hmm, có phải là bot của bạn trả giá 0 và phá vỡ ngay cả khi nó bắt đầu một vòng (khi opponentsBidvẫn là 0)?
Kevin Cruijssen

@KevinCruijssen Có. Điều đó chỉ có thể xảy ra với đối thủ đầu tiên. Bất kỳ bot nào sao chép nó sẽ bắt đầu từ 0, vì vậy điều này sẽ không lãng phí nhiều hơn so với 5c.
Mnemonic

4

Không cạnh tranh: AbstractAnalystCorerBot

import net.ramenchef.dollarauction.DollarBidder;

import java.util.Set;
import java.util.HashSet;

public abstract class AbstractAnalystCounterBot extends DollarBidder {

public AbstractAnalystCounterBot() {
    if (isPeeking())
        throw new RuntimeException();
}

    protected boolean isPeeking() {
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        for (StackTraceElement ste : stackTrace) {
            Class<?> clazz;
            try {
                clazz = Class.forName(ste.getClassName());
            } catch (ClassNotFoundException | SecurityException e) {
                continue;
            }
            if (DollarBidder.class.isAssignableFrom(clazz) && !clazz.isAssignableFrom(this.getClass()))
                return true;
        }
        try {
            return Class.forName(stackTrace[0].getClassName()).getPackage().getName().equals("net.ramenchef.dollarauction");
        } catch (Exception e) {
            return true;
        }
    }
}

Đây không phải là một đệ trình thực sự, mà là một số bản tóm tắt cho những người khác sử dụng để ngăn chặn các bot giữ thú cưng như MirrorBotMimicBot .

Vì nó là hàm tạo mặc định, nên không cần gọi nó trong lớp con của bạn. Nó thực hiện một isPeekingphương pháp để xác định xem một bot khác có đang rình mò không.


4

BreakEvenAsap

import net.ramenchef.dollarauction.DollarBidder;

public class BreakEvenAsap extends DollarBidder{
  @Override
  public int nextBid(int opponentsBid){
    // If the opponent has bid 100 or more: bid 0 to break even and let them win
    return opponentsBid >= 100 ? 0
    // Else: bid 100 to break even (and possibly win)
     : 100;
  }
}

Kịch bản

  • Nếu đối thủ có thể bắt đầu và trả giá <= 0 họ thua.
  • Nếu đối thủ có thể bắt đầu và trả giá [5,95] : hãy tự trả giá 100. Đối thủ của bạn dừng ngay bây giờ hoặc sẽ trả giá tổng cộng trên 100, trong trường hợp đó bạn dừng đặt giá thầu để cho họ có chiến thắng và hòa vốn với chính bạn.
  • Nếu đối thủ có thể bắt đầu và trả giá >= 100 : hãy tự trả giá 0 để thua nhưng hòa vốn.
  • Nếu bạn có thể bắt đầu: trả giá 100 ngay lập tức. Đối thủ của bạn dừng ngay bây giờ hoặc sẽ trả giá trên 100, trong trường hợp đó bạn dừng đặt giá thầu để cho họ có chiến thắng và hòa vốn với chính bạn.

Wow đó là một lỗi. Nó nói tôi đã bình luận về câu hỏi, nhưng nó đã kết thúc ở đây. Phải tìm cách tái tạo nó
Stan Strum

@RamenChef Typo .. Nhưng tôi đã sửa đổi toàn bộ bot. Dù sao nó cũng có một số lỗi ..
Kevin Cruijssen

4
Điều này hoàn toàn có thể mất tiền. Nếu bạn đặt giá thầu 100, thì đối thủ của bạn trả giá 105, cuối cùng bạn sẽ thua 100 và họ chỉ thua 5.
Mnemonic

@Mnemonic Ah tất nhiên .. Không nghĩ về phần đó .. Hmm .. điều đó làm cho mọi thứ thú vị hơn nhưng cũng khó khăn hơn. Sẽ chỉnh sửa mô tả cho bây giờ, nhưng để lại bot như vậy.
Kevin Cruijssen

1
Tôi nghĩ bạn có nghĩa là "mất" không "mất". Thua là ngược lại với chiến thắng. Lỏng là đối diện của chặt chẽ.
Kat

3

EvilBot

import java.util.Arrays;

import net.ramenchef.dollarauction.DollarBidder;

public class EvilBot extends DollarBidder {

    @Override
    public int nextBid(int opponentsBid) {
        if (isPeeking()) {
            throw new Error("HaHa!");
        } else {
            return 5;
        }

    }

    private static boolean isPeeking() {
        final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        for (StackTraceElement ste : Arrays.copyOfRange(stackTrace, 3, stackTrace.length)) {
            Class<?> clazz;
            try {
                clazz = Class.forName(ste.getClassName());
            } catch (ClassNotFoundException e) {
                return true;
            }
            if (DollarBidder.class.isAssignableFrom(clazz))
                return true;
        }
        return false;
    }

}

Ném một Lỗi thay vì Ngoại lệ cho các nhà phân tích gây nhiễu.


3

BuzzardBot

import java.util.Random;

import net.ramenchef.dollarauction.DollarBidder;

public class BuzzardBot extends DollarBidder {

    private int[] bids = new int[100];
    private int oppFlag = 0;

    public void newAuction(Class<? extends DollarBidder> opponent) {
        oppFlag = 0;
        if(isPeeking()) {
            oppFlag = 3;
            return;
        }
        try {
            DollarBidder enemy = opponent.newInstance();
            enemy.newAuction(this.getClass());
            // a simple (and fallible) determinism check
            int sample = new Random().nextInt(100);
            int a = enemy.nextBid(sample);
            int b = enemy.nextBid(sample);
            int c = enemy.nextBid(sample);
            if ((a - b) * (b - c) != 0) {
                oppFlag = 2;
                return;
            }
            for (int i = 0; i < 100; i++) {
                bids[i] = enemy.nextBid(i);
            }
        } catch (Throwable t) {
            oppFlag = 1;
        }
    }

    @Override
    public int nextBid(int opponentsBid) {
        switch (oppFlag) {
        case 0:
            // assume the opponent's nextBid function depends only on the bid provided, and
            // make the bid that yields the biggest profit possible accordingly
            int best = 0;
            int bid = 0;
            for (int i = 0; i < 100; i++) {
                if (bids[i] < i + 5) {
                    int gain = (i >= opponentsBid + 5) ? 100 - i : -i;
                    if (gain > best) {
                        best = gain;
                        bid = i;
                    }
                }
            }
            return bid;
        case 1:
            // act like BorkBorkBot against anything that tries to foil analysis with an
            // Exception
            return (opponentsBid >= 95) ? 0 : (opponentsBid + 5);
        case 3:
            // bid aggressively against opposing analysts
            return Math.min(opponentsBid + 5, 100);
        case 2:
        default:
            // place an opening bid against something unpredictable, as it might yield 95c
            // profit, and failure has a low cost.
            return (opponentsBid == 0) ? 5 : 0;
        }
    }

    private static boolean isPeeking() {
        final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        for (StackTraceElement ste : Arrays.copyOfRange(stackTrace, 3, stackTrace.length)) {
            Class<?> clazz;
            try {
                clazz = Class.forName(ste.getClassName());
            } catch (ClassNotFoundException e) {
                return true;
            }
            if (DollarBidder.class.isAssignableFrom(clazz))
                return true;
        }
        return false;
    }
}

Cố gắng đánh giá đối thủ mà nó phải đối mặt và đảm bảo không cắn nhiều hơn những gì nó có thể nhai.


1
Chào mừng đến với PPCG!
Alion

3

Nhà phân tích

import net.ramenchef.dollarauction.DollarBidder;

public class AnalystOptimizer extends DollarBidder{

    private DollarBidder enemy;

    @Override
    public void newAuction(Class<? extends DollarBidder> opponent) {
        try {
            enemy = opponent.newInstance();
            enemy.newAuction(this.getClass());
        } catch (ReflectiveOperationException e) {
            enemy = null;
        }
    }

    @Override
    public int nextBid(int opponentsBid){
        if (enemy == null)
            return (opponentsBid >= 95) ? 0 : (opponentsBid + 5);
        int nb = 0;
        try {
            return enemy.nextBid(95) >= 100 ? 95 : 0;
        } catch (Throwable e) {
            System.out.println("haha no");
            return 95;
        }
    }
}

cobbled với nhau từ các bộ phận của bot khác. cái này chơi bằng cách cố gắng trở thành Nhà phân tích, và nếu không thành công, trở thành BorkBorkBot.

Tôi không nghĩ rằng cái này sẽ làm tốt điều đó.


Xem ra cho AnalystKiller.
RamenChef

@RamenChef AFAIK kẻ giết người phân tích chỉ ném ra một ngoại lệ nếu nó thấy chính nó được phân tích. Tôi có thể bắt được điều đó
dkudriavtsev

1
Bạn có lẽ nên bắt nó.
RamenChef

@RamenChef Không biết điều đó có hiệu quả không, tôi không thể Java
dkudriavtsev

3

CounterBot

import net.ramenchef.dollarauction.DollarBidder;

public class CounterBot extends DollarBidder {
  private Class<? extends DollarBidder> enemy;

  @Override
  public void newAuction(Class<? extends DollarBidder> opponent){
    this.enemy = opponent;
  }

  @Override
  public int nextBid(int opponentsBid) {
    if(this.enemy.equals(CounterBot.class))
      throw new RuntimeException("Here boy, catch!");

    return this.enemy.equals(DarthVader.class) || 
           this.enemy.equals(MirrorBot.class) || 
           this.enemy.equals(OnlyWinningMove.class) ||
           this.enemy.equals(AnalystKiller.class) || 
           this.enemy.equals(DeterredBot.class) ||
           this.enemy.equals(InsiderTradingBot.class) ||
           this.enemy.equals(RiskRewardBot.class) ||
           this.enemy.equals(ImprovedAnalystBot.class) ?
            5
         : this.enemy.equals(MarginalBot.class) ?
           opponentsBid == 0 ? 5 : 10
         : this.enemy.equals(AnalystBot.class) || 
           this.enemy.equals(AnalystOptimizer.class) ?
            opponentsBid == 95 ? 100 : 5
         : this.enemy.equals(TargetValueBot.class) ?
            opponentsBid < 190 ? opponentsBid + 5 : 200
         : this.enemy.equals(BorkBorkBot.class) ?
            opponentsBid < 90 ? opponentsBid + 5 : 95
         : this.enemy.equals(DeterrentBot.class) ?
            105
         : this.enemy.equals(BreakEvenAsap.class) ?
            opponentsBid == 100 ? 105 : 100
         : this.enemy.equals(LuckyDiceBot.class) ?
            opponentsBid == 0 ? 5 : 0
         : this.enemy.equals(RandBot.class) || 
           this.enemy.equals(UpTo200.class) ||
           this.enemy.equals(SecretBot.class) ||
           this.enemy.equals(BluffBot.class) ||
           this.enemy.equals(EvilBot.class) ?
            opponentsBid + 5
         : this.enemy.equals(MimicBot.class) ? // TODO: Find actual counter
            10
         : this.enemy.equals(MarginalerBot.class) ||
           this.enemy.equals(MBot.class) ||
           this.enemy.equals(StackTraceObfuscaterBot.class) ||
           this.enemy.equals(MSlowBot.class) ?
            opponentsBid < 95 ? 90 : opponentsBid == 95 ? 100 : 95;
         : this.enemy.equals(BuzzardBot.class) ?
            100
         : this.enemy.equals(ScoreOverflowBot.class) ?
            opponentsBid == 105 ? 110 : 0
         : //this.enemy.equals(GreedyBot.class) || 
           //this.enemy.equals(RichJerk.class) ||
           //this.enemy.equals(InflationBot.class) ?
           // TODO: More bots?
            0;
  }
}

Quầy:

  • DarthVaderphản ứng chính nó bằng cách gây ra SecurityExceptiontrước khi bắt đầu đấu thầu, nhưng tôi sẽ đấu thầu 5 chỉ trong trường hợp.
  • AnalystBotAnalystOptimizercả hai sẽ xem xét câu trả lời của tôi khi tôi đặt giá thầu 95, trong trường hợp đó tôi sẽ hiển thị tôi đặt giá thầu 100 để nó tự trả giá 95. Tuy nhiên, tôi sẽ trả giá 5 nếu tôi bắt đầu (hoặc 100 nếu họ đã bắt đầu), vì vậy họ mất 95 xu và tôi sẽ giành được hóa đơn 1 USD chỉ bằng cách trả giá 5 xu hoặc bằng cách hòa vốn.
  • MirrorBotsẽ trả giá những gì tôi sẽ đấu thầu với nó. Vì vậy, tôi sẽ chỉ trả giá 5, và bất cứ ai bắt đầu thắng 95 xu, và người khác mất 5 xu.
  • MarginalBot sẽ trả giá 5 nếu tôi trả giá dưới 10 (hoặc giá bắt đầu), nếu không, nó sẽ trả giá 0. Vì vậy, nếu tôi chỉ trả giá 5 khi tôi bắt đầu hoặc 10 khi bắt đầu, tôi thắng 95 hoặc 90 xu, và họ thua 5 xu.
  • GreedyBot luôn trả giá cao hơn tôi 5 lần, vì vậy chỉ cần trả giá 0 để hòa vốn và để họ có chiến thắng
  • OnlyWinningMoveAnalystKillercả hai luôn trả giá 0, vì vậy chỉ cần trả giá 5 để giành chiến thắng
  • TargetValueBotsẽ đặt giá thầu trong phạm vi [100,200], vì vậy hãy đặt giá thầu thêm 5 lần mỗi lần cho đến khi chúng ở mức 190, trong trường hợp đó, chúng tôi tăng lên 200 để hòa vốn bằng cách giành được đồng đô la (và để chúng mất 190 hoặc 195 tùy thuộc vào người bắt đầu)
  • BorkBorkBotsẽ trả giá trong phạm vi [5,95], vì vậy, hãy trả giá thêm 5 lần nữa. Ngay sau khi họ đặt giá thầu 85 hoặc 90 (tùy thuộc vào người bắt đầu), hãy tự trả giá 95. Họ sẽ mất 85 hoặc 90 xu và bạn giành được hóa đơn 1 USD để kiếm được 5 xu.
  • DeterrentBot sẽ trả giá 5 nếu họ bắt đầu hoặc 100 nếu chúng tôi bắt đầu, vì vậy chỉ cần đặt giá thầu 105 để họ truy cập bằng 100, khiến họ mất 100 và chúng tôi chỉ mất 5 xu bằng cách giành được hóa đơn 1 USD.
  • BreakEvenAsapsẽ trả giá 100 ngay. Vì vậy, nếu họ đã bắt đầu với giá thầu 100, hãy truy cập 105 để giành được 95 xu và để họ mất 100. Nếu chúng tôi có thể bắt đầu chỉ trả giá 100 để cả hai chúng tôi hòa vốn.
  • RichJerk sẽ trả giá 10,001 ngay lập tức, vì vậy chỉ cần đặt giá thầu 0 để hòa vốn và để họ mất 9,901.
  • DeterredBot không biết tôi và do đó sẽ trả giá 0, vì vậy chỉ cần trả giá 5 để giành chiến thắng.
  • LuckyDiceBottiếp tục đấu thầu cho đến khi nó thắng Vì vậy, nếu chúng tôi bắt đầu, hãy trả giá 5 với hy vọng họ trả giá càng cao càng tốt để giành được đồng đô la. Nếu họ đã bắt đầu chỉ cần trả giá 0 để cho họ có chiến thắng và hòa vốn với chính mình.
  • RandBotsẽ đặt giá thầu ngẫu nhiên trong phạm vi [5,100], vì vậy chỉ cần đặt giá thầu thêm 5 lần nữa cho đến khi dừng, trong trường hợp đó bạn đã thắng 95 xu và họ đã thua 0-100.
  • UpTo200sẽ (như tên trạng thái) đặt giá thầu lên tới 200. Vì vậy, chỉ cần đặt giá thầu 5 cao hơn cho đến khi họ dừng lại. Chúng tôi sẽ giành được hóa đơn 1 USD và mất tổng cộng 105 xu, tuy nhiên họ mất 200 xu.
  • InsiderTradingBot không biết tôi, vì vậy chỉ cần trả giá 5 xu để giành chiến thắng
  • MimicBotlà khó nhất Chỉ cần đặt giá thầu 10 để bắt đầu bằng hoặc phản đối giá thầu đầu tiên của họ là 5. Nếu họ cố gắng truy cập vào tôi, tôi sẽ ném RuntimeException (họ sẽ nắm bắt trong trường hợp nó sẽ hoạt động như thể tôi đã trả giá 100 thay vào đó - mặc dù nó sẽ phá vỡ vòng lặp while bên trong). Dựa trên những kẻ thù mà nó có trong Hashset, một điều khác xảy ra. Tôi sẽ phải xem lại và xem xét kỹ hơn để xem có một quầy thực tế không.
  • RiskRewardBot không biết tôi nên sẽ trả giá 5, trong trường hợp đó tôi sẽ trả giá 5 để giành chiến thắng.
  • MarginalerBotsẽ bit lên tới 100 tùy thuộc vào những gì tôi sẽ trả giá. Nếu tôi có thể bắt đầu, tôi sẽ trả giá 90, sau đó nó sẽ trả giá 95, sau đó tôi sẽ trả giá 100 vì vậy nó sẽ trả giá 0 và mất 95 xu, trong khi tôi giành được hóa đơn 1 USD và hòa vốn. Nếu nó có thể bắt đầu thay vào đó, nó thấy tôi sẽ trả giá 90 so với nó, vì vậy nó tự trả giá 90, sau đó tôi sẽ trả giá 95 để nó trả giá 0 và mất 90 xu, trong khi tôi giành được hóa đơn 1 USD với lợi nhuận 5 xu.
  • BuzzardBotsẽ phân tích tất cả các quầy của tôi trong phạm vi [0,100). Nếu tôi đặt giá thầu 100ngay lập tức nó sử dụng oppFlag = 0và mảng 100 kích thước hoàn chỉnh sẽ chứa 100x giá trị 100. Trong chuyển đổi case 0, vòng lặp sẽ nằm trong phạm vi [0,100)một lần nữa và vì i + 5nhiều nhất sẽ là 104, nếu bids[i] < i + 5không bao giờ là đúng , vì vậy giá thầu nó vẫn là 0.
  • ImprovedAnalystBotsẽ luôn luôn có this.enemy = nullvì đối thủ của mình là CounterBot, không phải chính nó. Vì vậy, nó sẽ luôn trả giá 0, mà tôi chỉ truy cập với giá thầu là 5.
  • InflationBot sẽ trả giá 0 để hòa vốn ngay cả khi nó bắt đầu, nếu không nó sẽ tiếp tục đặt giá thầu 5. Vì vậy, hãy đặt giá thầu 0 cho chính chúng tôi để hòa vốn ngay lập tức và để họ có chiến thắng.
  • ScoreOverflowBotsẽ đấu thầu gần Integer.MAX_VALUEnếu họ có thể bắt đầu, nếu không họ sẽ trả giá 105. Vì vậy, nếu họ đã đặt giá thầu 105 chỉ cần đặt giá thầu 110 cho chính chúng tôi (họ sẽ mất 105, chúng tôi sẽ mất 10), nếu không, hãy đặt giá thầu 0 để cho họ có chiến thắng.
  • MBotlà giống như MarginalerBot, nhưng có thêm sự bảo vệ chống lại các đối thủ 'nhìn trộm'. Vì tôi không 'nhìn trộm', về cơ bản nó giống như MarginalerBot.
  • SecretBotsẽ có isPeeking()phương thức của anh ta trả về false, vì vậy nếu nó có thể bắt đầu hoặc nếu tôi đặt giá thầu 5, thì nó sẽ trả giá tương ứng 5 hoặc 10. Nếu không, nó sẽ trả giá 0. Vì vậy, dù tôi có bắt đầu hay không, opponentsBid + 5sẽ khiến tôi giành chiến thắng, bằng cách trả giá 10 xu hoặc 15 xu, khiến họ mất 5 hoặc 10 xu.
  • BluffBotsẽ xem xét những gì tôi sẽ đặt giá thầu khi giá thầu của anh ấy là 95 và nếu giá trị này lớn hơn hoặc bằng 100, nó sẽ đặt giá thầu 0 để hòa vốn, nếu không, nó sẽ đặt giá thầu opponentsBid + 5. Vì vậy, tôi sẽ chỉ trả giá opponentsBid + 5. Nó sẽ hòa vốn bất kể ai bắt đầu và tôi giành được 100 hoặc 95 xu tùy thuộc vào việc tôi đã bắt đầu hay chưa.
  • StackTraceObfuscaterBotsẽ hành động giống như MarginalerBot.
  • EvilBotsẽ luôn trả giá 5, vì vậy chỉ cần trả giá opponentsBid + 5. Dù bằng cách nào, họ sẽ mất 5 xu đó và chúng tôi sẽ giành được giá thầu 1 USD (với giá thầu 5 xu nếu chúng tôi bắt đầu hoặc 10 xu giá thầu nếu họ đã bắt đầu).
  • MSlowBotlà giống như MBotvà do đó cũng có MarginalerBot.

Hãy cho tôi biết nếu bạn thấy bất kỳ lỗi chính tả hoặc sai sót trong quầy của tôi.


1
MirrorBotgọi newAraction với lớp của riêng bạn, vì vậy đó là một vấn đề. Ngoài ra, rất vui khi biết 3 giờ tôi dành cho MimicBot là vô ích.
Nissa

@StephenLeppik Đã xóa mã trong newAuctionvì nó sẽ thất bại thường xuyên hơn không .. Tôi không thể truy cập MirrorBotcũng như không thể chống lại tôi. Bất cứ ai bắt đầu hai người đều thắng 95 xu và người kia mất 5 xu.
Kevin Cruijssen

3
Dây xích thần thánh, Batman!
Skyler

1
Ngoài ra, khi chơi BorkBorkBot, bạn không nên tăng lên 95 khi họ đạt 85? Nếu không, cả hai bạn đang đấu thầu 95 nếu họ bắt đầu.
Skyler

1
@Freiheit tôi biết. Tôi chỉ sử dụng một trường hợp bổ sung để trả về 0 trong trường hợp tôi muốn thay đổi mặc định vì bất kỳ lý do gì. Nhưng tôi đã đặt chúng dưới mặc định bây giờ (bằng cách nhận xét chúng). Và tôi biết rằng tôi có thể chơi golf mọi thứ khá nhiều, nhưng đây không phải là về việc tạo ra mã ngắn nhất. Tôi chỉ làm cho nó một ternary để làm cho nó nhỏ gọn hơn một chút, nhưng đó là về nó. Bây giờ sẽ để nó như thế này
Kevin Cruijssen

3

RiskRewardBot

import net.ramenchef.dollarauction.DollarBidder;

public class RiskRewardBot extends DollarBidder {
    private int target;

    @Override
    public void newAuction(Class<? extends DollarBidder> opponent) {
        if (opponent.equals(OnlyWinningMove.class) ||
            opponent.equals(DeterredBot.class) ||
            opponent.equals(MirrorBot.class) ||
            opponent.equals(AnalystKiller.class) ||
            opponent.equals(RiskRewardBot.class)) {
            target = 5;
        } else if (opponent.equals(MarginalBot.class) ||
            opponent.equals(EvilBot.class)) {
            target = 10;
        } else if (opponent.equals(SecretBot.class)) {
            target = 15;
        } else if (opponent.equals(BorkBorkBot.class)) {
            target = 95;
        } else if (opponent.equals(MarginalerBot.class) ||
             opponent.equals(BluffBot.class) ||
             opponent.equals(BuzzardBot.class)) {
            target = 100;
        }
        } else {
            target = 0;
        }
    }

    @Override
    public int nextBid(int opponentsBid) {
        if (opponentsBid >= target) {
            return 0;
        } else if (target > 10 && opponentsBid == target - 10) {
            return target;
        } else {
            return opponentsBid + 5;
        }
    }
}

Không thể kiểm tra điều này vào lúc này, vì vậy xin vui lòng cho tôi biết nếu nó bị hỏng.

Mục tiêu là để có được tổng điểm cao nhất, vì vậy đừng lo lắng về việc đánh bại bất cứ ai. Chỉ cần giành chiến thắng dễ dàng và không lãng phí tiền vào những tổn thất có thể xảy ra.


3

BluffBot

import net.ramenchef.dollarauction.DollarBidder;

public class BluffBot extends DollarBidder {

private DollarBidder enemy;

@Override
public void newAuction(Class<? extends DollarBidder> opponent){
  try {
    this.enemy = opponent.newInstance();
    enemy.newAuction(this.getClass());
} catch (Throwable e) {
    enemy = null;
}
}

@Override
public int nextBid(int opponentsBid) {
    //Is this a legit call?
    for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
        Class<?> clazz;
        try {
            clazz = Class.forName(ste.getClassName());
            if (DollarBidder.class.isAssignableFrom(clazz) && !clazz.isAssignableFrom(this.getClass())) {
                return 100000;
            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    //Play it safe against strangers
    int enemyMaxBid;
    try{
        enemyMaxBid = enemy.nextBid(95);
    }
    catch (Throwable t){
        enemyMaxBid = 0;
        enemy = null;
    }
    if(enemy == null) return opponentsBid <= 5 ? opponentsBid + 5 : 0; //Hazard a 5c guess because of how many bots fold instantly.

    //If there's profit to be had, get there as cheaply as possible. Otherwise, best outcome is zero.
    return enemyMaxBid >= 100 ? 0 : opponentsBid + 5;
}


}

Một gián điệp mà bạn biết là có giá trị hơn không có gián điệp nào cả ...

Nếu ai đó khác cố gắng gọi phương thức getBid, thì BluffBot trả lời với 100 đô la để lừa họ bỏ cuộc hoặc đặt cược thực sự cao.

Mặt khác, hãy xem liệu có thể giành được dưới 1 đô la không và chỉ cần trả giá nếu không.


2

Lên tới 200

import net.ramenchef.dollarauction.DollarBidder;

public class UpTo200 extends DollarBidder{
  @Override
  public int nextBid(int opponentsBid){
    // If the current bid of the opponent is in the range [0,195]: raise the bid by 5
    return opponentsBid <= 195 ? opponentsBid + 5
    // Else: Give up
     : 0;
  }
}

2

Bí mật

import java.util.Arrays;

import net.ramenchef.dollarauction.DollarBidder;

public class SecretBot extends DollarBidder {

    @Override
    public int nextBid(int opponentsBid) {
        if (isPeeking()) {
            return opponentsBid;
        } else if (opponentsBid < 10) {
            return opponentsBid + 5;
        } else {
            return 0;
        }

    }

    private static boolean isPeeking() {
        final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        for (StackTraceElement ste : Arrays.copyOfRange(stackTrace, 3, stackTrace.length)) {
            Class<?> clazz;
            try {
                clazz = Class.forName(ste.getClassName());
            } catch (ClassNotFoundException e) {
                return true;
            }
            if (DollarBidder.class.isAssignableFrom(clazz))
                return true;
        }
        return false;
    }

}

Bot này thực hiện các nỗ lực tối thiểu để giành chiến thắng bằng cách đặt giá thầu 5 hoặc 10. Anh ta cũng kiểm tra dấu vết ngăn xếp để xem liệu anh ta có được gọi bởi một Bot khác hay không và sau đó nói dối họ về những gì anh ta sẽ trả giá.


Tâm trí nếu tôi port isPeekingvào AbstractAnalystCounterBot?
Nissa

1
@StephenLeppik, tốt, tôi đã đánh cắp nó từ MBot ...
Winston Ewert

1
Chà, MBot có lẽ đã lấy trộm nó từ tôi
Nissa

2

Thêm một

import net.ramenchef.dollarauction.DollarBidder;

public class OneExtra extends DollarBidder {
    @Override
    public int nextBid(int opponentsBid) {
        if(opponentsBid < 110)
          return opponentsBid + 6;
        return opponentsBid;
    }
}

Trả giá 6 lần so với giá thầu cuối cùng, chỉ vì anh ta có thể.


Anh ta không thể trả giá 6 vì tất cả các giá thầu phải là bội số của 5 ...
Neil

@ Không phải là lỗi đánh máy ...
Stan Strum

@ Không có quy tắc cụ thể nêu rõ: "Giá thầu của bạn không cần phải là bội số của 5 ¢"
MegaTom

@MegaTom Huh, cũng được thêm vào kể từ lần cuối tôi đọc quy tắc ...
Neil

@Neil Đó là một phần của quy tắc ban đầu, nhưng tôi đã thêm nó vào đó vì nó không rõ ràng.
RamenChef

2

StackTraceObfuscaterBot

import net.ramenchef.dollarauction.DollarBidder;

import java.util.concurrent.FutureTask;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;

public class StackTraceObfuscaterBot extends DollarBidder {
    private volatile static boolean created = false;
    private volatile DollarBidder pet;
    private boolean firstBid = false;

    public StackTraceObfuscaterBot() {
        if (created)
            throw new IllegalStateException("THERE CAN ONLY BE ONE!");
        created = true;
    }

    @Override
    public void newAuction(Class<? extends DollarBidder> opponent) {
        firstBid = true;
        RunnableFuture<DollarBidder> task = new FutureTask<>(() -> {
            try {
                return opponent.newInstance();
            } catch (Throwable t) {
                return null;
            }
        });
        Thread thread = new Thread(task);
        thread.start();
        try {
            pet = task.get(450, TimeUnit.MILLISECONDS);
        } catch (InterruptedException | ExecutionException | TimeoutException e) {
            task.cancel(true);
            pet = null;
        }
    }

    @Override
    public int nextBid(int opponentsBid) {
        if (!firstBid)
            return 0;
        firstBid = false;

        for (int bid = opponentsBid + 5; i < 100; i += 5) {
            final int bidt = bid;
            RunnableFuture<Boolean> task = new FutureTask<>(() -> {
                pet.newAuction(this.getClass());
                return pet.nextBid(bidt) < bidt + 5;
            });
            Thread thread = new Thread(task);
            thread.start();
            try {
                if (task.get(23, TimeUnit.MILLISECONDS))
                    return bid;
            } catch (InterruptedException | ExecutionException | TimeoutException e) {
                task.cancel(true);
                return 0;
            }
        }
        return 0;
    }
}

Bot này cười khi cố gắng phát hiện sự phản chiếu thông qua dấu vết ngăn xếp. Thứ gần nhất họ thấy DollarBidderlà một lớp lambda mà nó tạo ra. Rõ ràng không phải bot khác cố gắng phản ánh chúng. Họ ít biết rằng lớp lambda đang thực sự làm việc cho a DollarBidder. Ngoài ra, anh hành động như thế MarginalerBot.


Lưu ý rằng tôi đã cập nhật kiểm tra theo dõi ngăn xếp của mình để xử lý việc này.
Nissa

1

Darth Vader

import java.lang.reflect.Field;
import net.ramenchef.dollarauction.DollarBidder;

public class DarthVader extends DollarBidder
{
@Override
public void newAuction(Class<? extends DollarBidder> opponent) {
    //set all values in the integer cache to over the $100 limit except 0
    Class icache = Integer.class.getDeclaredClasses()[0];
    Field c = icache.getDeclaredField("cache");
    c.setAccessible(true);
    Integer[] cache = (Integer[]) c.get(cache);
    for(sbyte b=0;b<128;b++)
    {
     cache[b]=100001;
    }
}

@Override
public int nextBid(int opponentsBid) 
{
    return 0;
}
}

Điều này cố gắng buộc bot của đối thủ trả quá nhiều bằng cách đặt bộ đệm nguyên cho giá trị vượt quá giới hạn $ 100.


2
Người quản lý an ninh sẽ ngăn chặn điều này.
Nissa

2
Và điều này sẽ không hoạt động dù thế nào vì người chạy không đóng hộp số nguyên của nó.
Nissa

Ngay cả khi điều này sẽ không được dừng lại, đây là một động thái giật, mặc dù hợp lệ. "Phá hoại các bot khác được cho phép, nhưng cố gắng thay đổi mức độ hiển thị của trường / phương thức sẽ dẫn đến SecurityExceptions bí ẩn."
NoOneIsHãy

1
@StephenLeppik Điểm của việc này là phá vỡ mọi thứ như return opponentsBid <= 195 ? opponentsBid + 5 : 0và làm cho nó return opponentsBid <= 100001 ? opponentsBid + 100001 : 100001.
NoOneIsHãy

1
Không thể biên dịch vì các ngoại lệ không được kiểm tra.
Nissa

1

ImprovedAnalystBot (không cạnh tranh)

Rất nhiều người dường như đang sử dụng AnalystBotmã làm mẫu, mặc dù đó là mã cố tình xấu. Vì vậy, tôi đang làm cho một mẫu tốt hơn.

import net.ramenchef.dollarauction.DollarBidder;

public class ImprovedAnalystBot extends DollarBidder {
    private DollarBidder enemy;

    @Override
    public void newAuction(Class<? extends DollarBidder> opponent) {
        if (!opponent.equals(this.getClass()))
            try {
                this.enemy = opponent.newInstance();
                enemy.newAuction(this.getClass());
            } catch (Throwable t) {
                this.enemy = null;
            }
        else
            this.enemy = null;
    }

    @Override
    public int nextBid(int opponentsBid) {
        try {
            return enemy != null && enemy.nextBid(95) < 100 ? 95 : 0;
        } catch (Throwable t) {
            return 0;
        }
    }
}

Tại sao không chỉ chỉnh sửa thử thách của bạn?
Nathan Merrill

@NathanMerrill Tôi sẽ chỉnh sửa nó như thế nào?
RamenChef

Bằng cách nhấp vào nút chỉnh sửa và thay thế AnalystBot bằng mã này?
Nathan Merrill

@NathanMerrill AnalystBotlà mã xấu cố ý để nó có thể chứng minh sự AnalystKillerphá hoại nó.
RamenChef

1
The AnalystKiller vẫn hoạt động với bản cải tiến :) Vấn đề khiến nó trở thành một bài đăng là thách thức rõ ràng hơn nhiều so với câu trả lời.
Nathan Merrill

1

MBot

import net.ramenchef.dollarauction.DollarBidder;

import java.util.Arrays;

public class MBot extends DollarBidder {
    protected DollarBidder rival = null;
    protected boolean rivalPrepared = false;
    protected Class<? extends DollarBidder> rivalClass;


    @Override
    public void newAuction(Class<? extends DollarBidder> opponent) {
        this.rivalClass = opponent;
        this.rivalPrepared = false;
    }

    protected DollarBidder getRival() {
        if (!rivalPrepared) {
            rivalPrepared = true;
            try {
                rival = rivalClass.newInstance();
                rival.newAuction(this.getClass());
            } catch (Throwable t) {
                rival = null;
            }
        }
        return rival;
    }

    @Override
    public int nextBid(int opponentsBid) {
        return calcBid(opponentsBid, isPeeking(3), isPeeking(4));
    }

    protected int calcBid(int opponentsBid, boolean isPeeking, boolean isSubPeeking) {
        if (isPeeking) {
            throw new RuntimeException();
        }

        for (int iBid = opponentsBid + 5; iBid <= 100; iBid = iBid + 5) {
            try {
                if (getRival().nextBid(iBid) < iBid + 5) {
                    return iBid;
                }
            } catch (Throwable t) {
                // noop
            }
        }
        return 0;
    }

    protected boolean isPeeking(int level) {
        final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        final StackTraceElement[] stackTraceElements = Arrays.copyOfRange(stackTrace, level, stackTrace.length);
        for (StackTraceElement ste : stackTraceElements) {
            try {
                Class<?> clazz = Class.forName(ste.getClassName());
                if (DollarBidder.class.isAssignableFrom(clazz))
                    return true;
            } catch (ClassNotFoundException e) {
                return true;
            }
        }
        return false;
    }
}

MarginalerBot hơi tinh chế

  • không tử tế với những người sẽ không kiểm tra bạn
  • cho phép trả 100 để nhận 100 và hòa vốn, chỉ để từ chối người khác kiếm tiền dễ dàng

Bạn không thể tuyên bố nextBidđể ném ClassCastException.
RamenChef

@RamenChef ok, đổi nó sang RuntimeException mà không yêu cầu khai báo :)
mleko

Mã của bạn để kiểm tra theo dõi ngăn xếp trông đáng ngờ tương tự như của tôi.
Nissa

@StephenLeppik có lẽ đó là bản sao của nó
mleko

@mleko tại sao vậy? Lớp được sao chép từ đó là một siêu lớp trừu tượng miễn phí sử dụng.
Nissa

1

Không cạnh tranh: MSlowBot

import net.ramenchef.dollarauction.DollarBidder;

import java.util.Arrays;

public class MSlowBot extends DollarBidder {
    private DollarBidder rival;

    @Override
    public void newAuction(Class<? extends DollarBidder> opponent) {
        try {
            rival = opponent.newInstance();
            rival.newAuction(this.getClass());
        } catch (Throwable t) {
            rival = null;
        }
    }

    @Override
    public int nextBid(int opponentsBid) {
        noPeeking();

        for (int iBid = opponentsBid + 5; iBid <= 100; iBid = iBid + 5) {
            try {
                if (rival.nextBid(iBid) < iBid + 5) {
                    return iBid;
                }
            } catch (Throwable t) {
                //do nothing.
            }
        }
        return 0;
    }

    private void noPeeking() {
        final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        for (StackTraceElement ste : Arrays.copyOfRange(stackTrace, 3, stackTrace.length)) {
            try {
                Class<?> clazz = Class.forName(ste.getClassName());
                if (DollarBidder.class.isAssignableFrom(clazz))
                    Thread.sleep(1000);
            } catch (ClassNotFoundException | InterruptedException e) {
                throw new RuntimeException(":(");
            }
        }
    }
}

Logic tương tự như MBot, chỉ cần sử dụng thời gian chờ thay vì Ngoại lệ khi chiến đấu chống lại kẻ thù. Cho đến nay không ai bảo vệ hết thời gian chờ nên rất hiệu quả


The stated rules forbid deliberately causing another bot to timeout.
Winston Ewert

@WinstonEwert can you quote? I can't find rule disallowing this
mleko

"Sabotaging other bots is allowed, but attempting to alter field/method visibility will result in mysterious SecurityExceptions. An exception is causing another bot to break the 500ms limit." Also, I'm defending against timeout.
RamenChef

@RamenChef but this don't alter visibility of other elements. I'm not sure if I understand you correctly. Is provoking timeout allowed?
mleko

"An exception is causing another bot to break the 500ms limit." Specifically, this is an exception to the rule about sabotage.
RamenChef
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.