ドル紙幣オークション


33

これは、ゲーム理論におけるドル札オークションゲームのKOTHチャレンジです。その中で、ドルは最高入札者に売られています。入札単価は5¢単位で上昇し、敗者も入札単価を支払います。損失を削減するために、両プレイヤーは入札戦争をドルの価値をはるかに超えてエスカレートするという考え方です。

ボットがそれよりも賢いことを望みましょう。

net.ramenchef.dollarauction.DollarBidderクラスを拡張して、このゲームをプレイするボットを作成します。nextBid他のボットの以前の入札に基づいて、ボットの次の入札を返すメソッドを実装する必要があります。必要に応じて、このnewAuctionメソッドを使用して、対戦相手のボットのクラスで各オークションをリセットすることもできます。

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

入札は、次のいずれかが発生するまで続きます。

  • nextBid例外をスローします。これが発生した場合、例外をスローしたボットは以前の入札を支払い、他のボットは無料でドルを受け取ります。
  • どちらのボットも、前回の入札単価を上回る金額を支払いません。これが発生した場合、両方のボットが入札を支払い(敗者は以前の入札を支払います)、勝者は1ドルを受け取ります。
  • 両方のボットが100ドルを超えて入札します。この場合、両方のボットが100ドルを支払い、どちらのボットもドルを受け取りません。

ボットの組み合わせごとに2つのオークションが開催されます。ボットは、それらのオークション全体で得た合計利益によってスコア付けされます。最高のスコアが勝ちます。

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

これを分析志向のボットのテンプレートとして使用しないでください。ImprovedAnalystBot代わりに使用してください。

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

追加の規則

  • 標準的な抜け穴は禁止されています。
  • 他のボットの妨害は許可されますが、フィールド/メソッドの可視性を変更しようとすると、不思議なSecurityExceptions が発生します。例外は、別のボットが500ミリ秒の制限を破ることです。
  • ボットは、DollarBidderクラスを拡張する場合を除き、ランナーパッケージにアクセスできません。
  • すべてのメソッドは500ms以下で返されるはずです。
  • ボットは確定的である必要はありません。
  • 入札単価は5¢の倍数である必要ありませ
  • $ 1 = 100¢
  • 結果は2018年4月24日に掲載されます。

GitHubのランナー

結果

ここで個々のラウンドを表示します。

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

おめでとうございますMTargetedBot。14.30ドルの利益があります。


11
この課題は、基本的にOne-Uppingに対して脆弱です。私は相手のクラスを知っているので、それに対して最良の戦略を選ぶのは簡単です。(それから誰かがやって来て、ボットをワンアップできるなど)
ネイサンメリル

2
入札単価は5¢単位で上がります」。あなたは、しかし..これを検証するためにあなたのコードに何も持っていないLuckyDiceBotの単位で例の入札のために2-12ランダムに...
ケビンCruijssen

4
また、ボットにより他のボットが500ミリ秒の制限を超えた場合はどうなりますか?
ネイサンメリル

4
@RamenChefここでは悪意のあるコードについて話しています。別のボットが私を呼び出していることを検出し、Thread.sleep(1000)を呼び出すとどうなりますか?
ネイサンメリル

3
妨害行為が許可されているものと許可されていないものが不明なため、私はVTCです。OPは、「ランナーを攻撃する」(あいまいな)投稿を許可しておらず、許可されている悪意のあるコードと許可されていない悪意のあるコードの間に明確な境界線はありません?)
ネイサンメリル

回答:


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);
    }
}
  • 更新されたMBotに基づく
  • CounterBotのような同様のメソッドを使用しますが、一部のメソッドをより強力にヒットするように改良し、一部のメソッドを読みやすくする必要があります
  • 不明な対戦相手のデフォルトはMBotストラト

1
これは公平ではありません。
ジョシュア

@ジョシュアあなたの意見では、このソリューションについて特に公平ではないものは何ですか?
mleko

相手の名前を知る。
ジョシュア

@Joshuaの半分のソリューションはその情報を使用しています。そうここにある-私たちも、彼は挑戦を変更することを拒否し、これを変更する必要があるか、ワン増額が行われることを著者に手紙を書いた
mleko

1
すでにやった
ジョシュア

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

聖なる牛。これは書くのが簡単だと思っていて、その後3時間を費やしました。

本質的MimicBotに、利用可能なボットの実行リストを保持します。それが新しいオークションに行くとき、それは現在の対戦相手に対して最も効果的なものを探してリストを実行します。次に、そのボットをオークションの「参照」として使用します。

テストの目的では、提出物のランダム化されたサブセットまたはフルセットのいずれかを使用するのが最善です。それはで始まりGreedyBotMimicBotおよび1つの以上のボットだけの入札5¢います。


11

InsiderTradingBot

@StephenLeppikの答えの精神で、InsiderTradingBotはすべての対戦相手を知っており、彼らの戦略を理解しています。あなたの動き、スティーブン。

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
いや、インサイダー取引は、RichJerkボットがあなたのボットのために特定の例外を作り、それに対して0ドルを入札した場合です。
ニッサ

他の答えに対して最適化するのは時期尚早です。また、でAnalystBotはありませんAnalyst
ラーメンシェフ

8
おそらく「クラス名はランダム化される」というルールが必要です。
user202729

1
@ user202729「クラスへの直接参照なし」はどうですか?
ラーメンシェフ

1
これがMimicBotを処理するのを見たいです。
ニッサ

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

非常に単純で、対戦相手が最小入札価格に異議を唱えるかどうかを判断し、そうでない場合はそれを配置します。

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

MarginalBotの新しい、よりスマートなバージョン。最小限の勝利を望んでいるだけでなく、コンテストなしで金moneyけの動きができるかどうかを確認します。

私の以前のボットと同じファミリーですが、それを打とうとするサイドステップ戦略なので、同じ投稿の新しいエントリがそれを提示する最も合理的な方法であると考えました。

編集1: newAuctionメソッドに小さな変更を加えて、他の分析タイプのボットに対して最適化する。

編集2: MarginalerBotに変更を加えて、卑劣なまたは非決定的な戦略に対する損失を最小限に抑えます。


PPCGへようこそ!
マーティンエンダー

1
簡単ですが、他のすべてのボットよりもかなり大きなマージンで勝っています!
ラーメンシェフ

8

MirrorBot

敵を自分自身と対戦させます。

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
あなたはAnalyst見事にヌードになりました。
シルヴィオマヨロ

@SilvioMayoloどうやって?
dkudriavtsev

ミラーは自分自身と対戦するアナリストをエミュレートしようとし、スタックオーバーフローを引き起こします。
シルヴィオマヨロ

8

編集:DollarBidderクラスの対象を変更すると、このボットが壊れました。

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

1オークション後、そのスコアは-2147483645になりますが、次回は5¢または105¢を失い、スコアは正で非常に大きくなります。他のすべての損失は無視できます。

最初のオークションでは、GreedyBotが-2147483646をベットします。これは5で割り切れません。


scoreパッケージで保護されています。ボットはアクセスできません。
ラーメンシェフ

@RamenChef Oops、CheatingBotを削除

「ランナーへの攻撃」に対するルールはなく、「アクセスする」だけで、これは行いません。問題を解決するバグを修正することをお勧めします:)
ネイサンメリル

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

現時点ではこれをテストできませんので、壊れているかどうかをお知らせください。

基本的に、ドルの値を選択し、その値を超えるまで相手を上回っています。


6

BorkBorkBot

import net.ramenchef.dollarauction.DollarBidder;

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

それが壊れないならあきらめます。


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

それをしなければなりませんでした。


入札単価は5¢単位で上がります」。ボットは現在そうしていません。
ケビンクルーッセン

1
@KevinCruijssenまあまあ。それは念のために、全体の$ 1入札できるよう、私はまた、上限値を変更
ニール・

6

DeterrentBot

import net.ramenchef.dollarauction.DollarBidder;

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

唯一の勝利の動きはプレイしないことであるという分析志向のボットを説得する試み。


1
私のやや不可解なコメント「ジョシュア?それはあなたですか?」に気づきました削除されました。したがって、明確にするために、映画WarGamesからの有名な引用への参照でした:「唯一の勝利の動きはプレーしないことです」。(ジョシュアはWOPRのニックネームです。)
アーナルド

5

LuckyDiceBot

LuckyDiceBotは彼のサイコロのみを信頼します。彼は2つのサイコロを振って、合計を現在の入札者の価値に加算し、その額を入札します。相手の入札を克服するのに十分でない場合、彼は彼の損失を削減し、彼の方法で進みます。

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
これはどのように損失を削減または損失を停止しますか 常にサイコロを敵の入札に追加する場合、常により多く入札します。ランダム性は十分に分析的なボットを混乱させるかもしれません、私はコンセプトが好きです。
フライハイト

ロールが4以下の場合(統計的にはありそうにないが、最終的には発生します)、入札は対戦相手を打ち負かすには不十分であり、オークションは終了します。
シルヴィオマヨロ

次の2つです。opponentsBidin nextBid(int opponentsBid)は、対戦相手がこれまでに入札した合計入札を保持し、次の入札ではありません。この方法のより良い用語はraise(ポーカー用語として)imhoです。2.ボットは5ずつ増加しないため、ルールの1つを検証しています。これらの問題が修正されたとしても、分析ボットは対抗できず、非常に頻繁に勝つ可能性が高いため、私はまだコンセプトが好きです。
ケビンCruijssen

5

DeterredBot

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は、LuckyDiceBotとの違法なギャンブルで大金を稼ぎます。そのため、もちろん警察(DeterrentBot)が到着すると、彼は次のオークションへの入札など、何らかの方法ですぐに収入を処分しなければなりません。


4

InflationBot

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

現時点ではこれをテストできませんので、壊れているかどうかをお知らせください。

ラウンドごとに、ドルの価値が上がります。


これは、MirrorBot、MarginalerBot、およびおそらくMimicBotに対しても優れています。
ニッサ

@StephenLeppikそれは私がそれを作ったときに私が考えていたものです。それでもまだ多くの弱点があります。
ニーモニック

+1、私はアイデアが好きです。うーん、ボットが0をビッドし、ラウンドを開始しても(opponentsBidまだ0のとき)中断することを意図していますか?
ケビンCruijssen

@KevinCruijssenはい。それは最初の敵に対してのみ起こり得ます。それをコピーするボットはいずれも0から始まるため、これらのボットは5c以上を浪費しません。
ニーモニック

4

非競合:AbstractAnalystCounterBot

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

これが真の提出として意図されるのではなく、いくつかの決まり文句のように他の人が同じようペット飼育のボットを阻止するために使用するのMirrorBotMimicBot

これはデフォルトのコンストラクタであるため、サブクラスで呼び出す必要はありません。isPeeking別のボットが索しているかどうかを判断するメソッドを実装します。


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

シナリオ

  • 対戦相手が開始して入札した<= 0場合、負けとなります。
  • 対戦相手が開始して入札できる場合[5,95]:自分で100を入札します。対戦相手がすぐに停止するか、合計で100を超える入札が行われます。その場合、入札を停止して、勝者を獲得し、自分自身を打ち負かすことができます。
  • 対戦相手が開始して入札する可能性がある場合>= 100:負けても勝ちになるために自分で入札する
  • 開始する場合:すぐに100を入札します。対戦相手がすぐに停止するか、100を超えて入札します。その場合は、入札を停止して、勝者を獲得し、自分自身を打ち負かすことができます。

うわー、それはバグです。それは私が質問にコメントしていると言っていたが、それはここで終わった。それを再現する方法をお奨め見つける
スタン・ストラム

@RamenChef Typo ..しかし、ボット全体を変更しました。それは...とにかく、いくつかのバグを持っていた
ケビンCruijssen

4
これは絶対にお金を失う可能性があります。あなたは100を入札した場合は、相手の入札105は、100を失ってしまう、と彼らは唯一の5失う
ニーモニック

@Mnemonic Ahもちろん..その部分については考えていませんでした。今のところ説明を編集しますが、ボットはそのままにします。
ケビンCruijssen

1
「緩い」ではなく「失う」という意味だと思います。負けは勝利の反対です。ルースはタイトの反対です。
キャット

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

}

アナリストを混乱させるために、例外ではなくエラーをスローします。


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

直面している相手を評価しようとし、噛むことができる以上に噛まないようにしてください。


1
PPCGへようこそ!
アリオン

3

アナリストオプティマイザー

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

他のボットの一部からまとめられます。これは、AnalystBotになろうとしてプレイし、失敗した場合はBorkBorkBotになります。

これがうまくいくとは思わない。


気をつけてくださいAnalystKiller
ラーメンシェフ

@RamenChef AFAIKアナリストのキラーは、自身が分析されているのを見ると例外をスローします。私はそれをキャッチすることができます
-dkudriavtsev

1
おそらくキャッチする必要があります。
ラーメンシェフ

@RamenChefありませんアイデアそれが動作する場合、私は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;
  }
}

カウンター:

  • DarthVaderSecurityException入札が始まる前にを引き起こすことでそれ自体を打ち消しますが、念のため5を入札します。
  • AnalystBot そして AnalystOptimizer、私が95を入札したときに両方の回答を確認します。ただし、開始する場合は5(または開始した場合は100)を入札するため、95セントを失い、5セントだけ入札するか、損益分岐点で1米ドルの請求書を獲得します。
  • MirrorBot私はそれに対して入札するものを入札します。だから私はちょうど5を入札し、始めた人は95セントを勝ち取り、もう1人は5セントを失います。
  • MarginalBot 入札単価が10未満(または開始金額)の場合は5に、それ以外の場合は入札単価は0になります。 5セント。
  • GreedyBot 常に私よりも5高い入札単価を設定するので、0に入札して均等に勝ち、勝つことができます。
  • OnlyWinningMoveそして、AnalystKillerの両方がいつもただ勝つために5を入札し、0入札します
  • TargetValueBot 範囲内で入札します [100,200]でので、190になるまで毎回さらに5を入札します。この場合、200に引き上げてドルを勝ち取り、損益分岐点になります(開始者に応じて190または195を失います)。
  • BorkBorkBot範囲内[5,95]で入札するため、毎回さらに5入札します。85または90(開始者に応じて)を入札したらすぐに、自分で95を入札します。彼らは85または90セントを失い、5セントの利益で1米ドルの請求書を獲得します。
  • DeterrentBot 開始する場合は5、開始する場合は100なので、100でカウンターするように105だけを入札すると、100ドルを失い、1ドルの請求書を獲得することでわずか5セントを失います。
  • BreakEvenAsapすぐに100を入札します。したがって、100の入札で開始した場合は、105でカウンターして95セントを獲得し、100を失うようにします。
  • RichJerk すぐに10,001をビッドするので、0をビッドしてイーブンブレークして9,901を失います。
  • DeterredBot 私を知らないため、0を入札するので、5を入札して勝ちます。
  • LuckyDiceBot勝つまで入札を続けます。だから、もし始めたら、彼らがドルを獲得するためにできるだけ高く入札することを望んで5を入札してください。彼らが勝ち始めて自分自身を打ち負かすために彼らが始めたなら、ただ0を入札してください。
  • RandBot範囲内[5,100]でランダムに入札するため、停止するまでさらに5回入札します。この場合、95セントを獲得して負けました0-100
  • UpTo200(名前が示すように)最大200まで入札します。したがって、停止するまで5だけ高く入札します。1米ドルの請求書に勝ち、合計で105セントの損失を被りますが、200セントを失います。
  • InsiderTradingBot 私を知らないので、勝つために5セントを入札してください
  • MimicBot一番大変でした。5の最初の入札で開始またはカウンターするために10を入札するだけです内側のwhileループ)。HashSetにある敵に基づいて、別のことが起こります。実際にカウンターがあるかどうかを確認するために、再訪して詳しく調べる必要があります。
  • RiskRewardBot 私を知らないので、ちょうど5を入札します。その場合、勝つために5を入札します。
  • MarginalerBot私が何を入札するかに応じて、最大100までビットします。開始できる場合は、90を入札し、95を入札し、100を入札して、0を入札して95セントを失い、1米ドルの法案を獲得し、損益分岐点になります。代わりに開始される可能性がある場合は、90を入札するので、90自体を入札し、95を入札して0を入札して90セントを失い、1ドルの法案を5セントの利益で勝ち取ります。
  • BuzzardBot範囲内のすべてのカウンターを分析します[0,100)100すぐに入札するoppFlag = 0と、完全な100サイズの配列に値100の100xが含まれます。スイッチcase 0で、ループは[0,100)再び範囲内になり、i + 5最大で104になるため、if bids[i] < i + 5は真になりません。 、したがって、入札は0のままです。
  • ImprovedAnalystBotthis.enemy = null彼の対戦相手はCounterBot、自分自身ではないので、常に持っています。したがって、常に0が入札されますが、私は5の入札でカウンターします。
  • InflationBot 開始時でもブレイクするために0をビッドし、それ以外の場合は5をビッドし続けます。したがって、すぐにブレイクして勝つために0をビッドするだけです。
  • ScoreOverflowBotInteger.MAX_VALUE開始する可能性がある場合は近くに入札し、そうでない場合は入札し105ます。したがって、105を入札した場合は110だけを入札し(105を失うと10を失う)、それ以外の場合は0を入札して勝ちます。
  • MBotMarginalerBotはと同じですが、「覗き見」相手に対する保護が追加されています。「覗く」ことはしないので、基本的にと同じMarginalerBotです。
  • SecretBot彼のisPeeking()メソッドにfalseを返させるので、開始するか、5を入札すると、それぞれ5または10を入札します。それ以外の場合は、0を入札します。したがって、開始するかどうかにかかわらず、opponentsBid + 510セントまたは15セントのいずれかの入札で勝ち、5セントまたは10セントを失います。
  • BluffBot彼の入札が95の場合、私が入札するものを見て、これが100以上の場合、それは0になり、それ以外の場合は入札しopponentsBid + 5ます。だから私はちょうど入札しopponentsBid + 5ます。誰がスタートしたかに関係なくブレークし、私がスタートしたかどうかに応じて100セントまたは95セントを獲得します。
  • StackTraceObfuscaterBotと同じように動作しMarginalerBotます。
  • EvilBot常に5を入札するため、入札するだけopponentsBid + 5です。いずれにせよ、彼らはそれらの5セントを失い、1米ドルの入札を獲得します(開始した場合は5セントの入札、開始した場合は10セントの入札)。
  • MSlowBotMBotはと同じであり、したがってもMarginalerBotです。

カウンターにタイプミスや欠陥がある場合はお知らせください。


1
MirrorBotあなた自身のクラスでnewAuctionを呼び出すので、それは問題です。また、MimicBotに費やした3時間が無駄にならなかったことを嬉しく思います。
ニッサ

@StephenLeppikのコードを削除したのは、newAuction頻繁に失敗するためです。私は反論MirrorBotも反抗もできません。2人のうちどちらかが95セントで勝ち、もう1人が5セントを失います。
ケビンクルーッセン

3
聖三者連鎖、バットマン!
スカイラー

1
また、プレイBorkBorkBotするときに、85に達したときに95にレイズすべきではありませんか?それ以外の場合は、両方が開始されれば95で入札します。
スカイラー

1
@Freiheit私は知っています。何らかの理由でデフォルトを変更したい場合は、追加のケースを使用して0を返しました。しかし、私はそれらをデフォルトに設定しました(コメントアウトして)。そして、私はすべてをかなりゴルフでゴルフできることを知っていますが、これは最短のコードを作ることではありません。私はそれをもう少しコンパクトにするために三元にしたのですが、それはそれについてです。とりあえずこのままにしておきます。
ケビン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;
        }
    }
}

現時点ではこれをテストできませんので、壊れているかどうかをお知らせください。

目標は、最高の合計スコアを取得することですので、誰かを破ることを心配しないでください。簡単に勝つだけで、起こりうる損失にお金を無駄にしないでください。


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


}

あなたが知っているスパイは、まったくスパイがないよりも価値があります...

他の誰かがgetBidメソッドを呼び出そうとすると、BluffBotは100ドルで応答し、非常に高額のベットまたはベットをやめさせます。

それ以外の場合は、1ドル未満で勝つことができるかどうかを確認し、そうでない場合は入札しないでください。


2

UpTo200

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

SecretBot

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

}

このボットは、5または10の入札で勝つための最小限の試行を行います。彼はまた、スタックトレースをチェックして、別のボットから呼び出されたかどうかを確認し、次に自分が行う入札について嘘をつきます。


にポートisPeekingしても気になりますAbstractAnalystCounterBotか?
ニッサ

1
@StephenLeppikは、よく、私は... MBotからそれを盗んだ
ウィンストンエバート

1
まあ、MBotはおそらく私からそれを盗んだ…
ニッサ

2

ワンエクストラ

import net.ramenchef.dollarauction.DollarBidder;

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

彼ができるという理由だけで、最後の入札よりも6を入札します。


すべての入札は5の倍数である必要があるため、彼は6を入札できません
ニール

それはおそらくタイプミス...だ@Neil
スタン・ストラム

@Neilのルールでは、「入札単価は5¢の倍数である必要はありません」
-MegaTom

@MegaTom Huh、それは最後にルールを読んだ後に追加された...-
ニール

@Neilこれは元のルールの一部でしたが、あまり明白ではなかったのでそこに追加しました。
ラーメンシェフ

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

このボットは、スタックトレースを介して反射を検出する試みを笑います。彼らに最も近いものDollarBidderは、それが作成したラムダクラスです。明らかに、それらを反映しようとしている別のボットはありません。ラムダクラスが実際にDollarBidder。それを超えて、彼はのように振る舞いMarginalerBotます。


これを処理するためにスタックトレースチェックを更新したことに注意してください。
ニッサ

1

ダース・ベイダー

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

これは、整数キャッシュを100ドルの制限を超える値に設定することにより、対戦相手のボットに過払いを強制しようとします。


2
セキュリティマネージャーはこれを停止します。
ニッサ

2
そして、ランナーのどこも整数をボックス化しないため、とにかくこれは機能しません。
ニッサ

これが停止しなくても、これは有効ですが、ジャークムーブです。「他のボットの妨害は許可されていますが、フィールド/メソッドの可視性を変更しようとすると、不可解なSecurityExceptionsが発生します。」
-NoOneIsHere

1
@StephenLeppikこれのポイントは、好きなものを壊してreturn opponentsBid <= 195 ? opponentsBid + 5 : 0作ることreturn opponentsBid <= 100001 ? opponentsBid + 100001 : 100001です。
-NoOneIsHere

1
未チェックの例外のためにコンパイルに失敗します。
ニッサ

1

ImprovedAnalystBot (非競合)

多くの人は、AnalystBot意図的に悪いコードであっても、コードをテンプレートとして使用しているようです。そこで、私はより良いテンプレートを作成しています。

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

チャレンジを編集するだけではどうですか?
ネイサンメリル

@NathanMerrillどうすれば編集できますか?
ラーメンシェフ

編集ボタンをクリックして、AnalystBotをこのコードに置き換えますか?
ネイサンメリル

@NathanMerrill AnalystBotは意図的に悪いコードであるため、AnalystKiller妨害を実証することができます。
ラーメンシェフ

1
AnalystKillerは、改善されたものでも動作します:)投稿することの問題は、課題が答えよりもはるかに目に見えることです。
ネイサンメリル

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

  • あなたをチェックしたくない人には不親切です
  • 100を払って100を得ることができ、他の簡単なお金を拒否するだけで、偶然の場合を破ります

あなたはnextBid投げることを宣言できませんClassCastException
ラーメンシェフ

@RamenChef OK、宣言を必要としないRuntimeExceptionに交換しました:)
mleko

スタックトレースチェックのコードは、私のものと疑わしく似ています。
ニッサ

@StephenLeppikおそらくそれのコピー
-mleko

@mlekoなんで?コピー元のクラスは、自由に使用できる抽象スーパークラスです。
ニッサ

1

非競合: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(":(");
            }
        }
    }
}

MBotと同じロジック。敵と戦うときは例外ではなくタイムアウトを使用します。これまでのところ、誰もタイムアウトに対して防御していないので、効果的でなければなりません


記載されているルールは、意図的に別のボットがタイムアウトすることを禁止しています。
ウィンストンユワート

@WinstonEwert引用できますか?私は、この禁止ルールを見つけることができません
mleko

「他のボットの妨害は許可されていますが、フィールド/メソッドの可視性を変更しようとすると、不可解なSecurityExceptionsが発生します。例外により、別のボットが500ミリ秒の制限を超えます。」また、私はタイムアウトに対して防御しています。
ラーメンシェフ

@RamenChefしかし、これは他の要素の可視性を変更しません。私はあなたを正しく理解しているかどうかわかりません。タイムアウトの誘発は許可されていますか?
mleko

「例外により、別のボットが500ミリ秒の制限を超えています。」具体的には、これは妨害行為に関する規則の例外です。
ラーメンシェフ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.