ประมูลบิลดอลลาร์


33

นี่คือความท้าทาย KOTH สำหรับเกมประมูลธนบัตรในทฤษฎีเกม ในนั้นดอลลาร์จะถูกขายให้กับผู้ประมูลสูงสุด การเสนอราคาเพิ่มขึ้น 5 ทีและผู้แพ้ก็จ่ายค่าประมูล แนวคิดก็คือผู้เล่นทั้งสองจะขยายสงครามการประมูลออกไปไกลเกินกว่าค่าเงินดอลลาร์เพื่อลดความสูญเสีย

หวังว่าบอทของคุณจะฉลาดกว่านั้น

คุณจะสร้างบอทเพื่อเล่นเกมนี้โดยขยายnet.ramenchef.dollarauction.DollarBidderชั้นเรียน คุณต้องใช้nextBidวิธีการที่จะคืนค่าการประมูลครั้งถัดไปของ bot ของคุณเนื่องจากการเสนอราคาก่อนหน้าของ bot อื่น หากจำเป็นคุณสามารถใช้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โยนข้อยกเว้น หากสิ่งนี้เกิดขึ้นบอทที่โยนข้อยกเว้นจะจ่ายการเสนอราคาก่อนหน้านี้และบ็อตอื่นจะได้รับดอลลาร์ฟรี
  • บอทอย่างใดอย่างหนึ่งไม่จ่ายมากพอที่จะทำให้การเสนอราคาก่อนหน้า หากสิ่งนี้เกิดขึ้นบอตทั้งสองจะจ่ายราคาประมูลของตน (ผู้แพ้จะจ่ายราคาประมูลก่อนหน้า) และผู้ชนะจะได้รับดอลลาร์
  • ทั้งบอทเสนอราคามากกว่า $ 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 ข้อยกเว้นทำให้บอตอื่นทำลายขีด จำกัด 500ms
  • บอตไม่สามารถเข้าถึงแพ็คเกจนักวิ่งได้ยกเว้นว่าจะขยายDollarBidderชั้นเรียน
  • วิธีการทั้งหมดควรกลับเป็น 500ms หรือน้อยกว่า
  • บอทไม่จำเป็นต้องถูกกำหนดไว้ล่วงหน้า
  • การเสนอราคาของคุณไม่จำเป็นต้องเป็นทวีคูณของ 5 ¢
  • $ 1 = 100 ¢
  • ผลลัพธ์จะถูกโพสต์ในวันที่ 24 เมษายน 2018

วิ่งบน 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 เนื่องจากฉันรู้จักคลาสของคู่ต่อสู้ของฉันมันเป็นเรื่องง่ายที่จะเลือกกลยุทธ์ที่ดีที่สุด (จากนั้นมีบางคนเข้ามาและสามารถรวบรวมบอทของฉันและอื่น ๆ ได้)
Nathan Merrill

2
"การเสนอราคาเพิ่มขึ้น 5 ที¢ " คุณไม่มีอะไรในรหัสของคุณที่จะตรวจสอบสิ่งนี้แม้ว่า .. LuckyDiceBotตัวอย่างเช่นการเสนอราคาเพิ่มขึ้น2-12แบบสุ่ม ..
Kevin Cruijssen

4
นอกจากนี้จะเกิดอะไรขึ้นถ้าบอทของฉันทำให้บอตอื่นเกินขีด จำกัด 500ms
Nathan Merrill

4
@RamenChef เรากำลังพูดถึงรหัสที่เป็นอันตรายที่นี่ จะทำอย่างไรถ้าฉันตรวจพบว่าบอทตัวอื่นกำลังโทรหาฉันและโทรไปที่ Thread.sleep (1,000)
นาธานเมอร์ริลล์

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
สิ่งนี้ไม่ยุติธรรม
Joshua

@Joshua สิ่งที่ไม่เป็นธรรมเกี่ยวกับวิธีการแก้ปัญหานี้ในความคิดของคุณ?
mleko

รู้จักชื่อของคู่ต่อสู้ของคุณ
Joshua

@ โจชัวครึ่งหนึ่งของโซลูชันใช้ข้อมูลนั้น เรายังเขียนถึงผู้เขียนว่าควรเปลี่ยนสิ่งนี้หรือ One-Upping จะเกิดขึ้นเขาปฏิเสธที่จะเปลี่ยนความท้าทาย - ดังนั้นที่นี่คือ
mleko

1
ทำไปแล้ว ....
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;
        }
    }
}

วัวศักดิ์สิทธิ์ ฉันคาดว่าสิ่งนี้จะง่ายต่อการเขียนจากนั้นก็ใช้เวลา 3 ชั่วโมงกับมัน

ในสาระสำคัญMimicBotเก็บรายการทำงานของบอทที่มีอยู่ เมื่อมันไปสู่การประมูลใหม่มันจะวิ่งผ่านรายการเพื่อค้นหาสิ่งที่มีประสิทธิภาพมากที่สุดกับคู่ต่อสู้ในปัจจุบัน จากนั้นใช้บอทนั้นเป็น "อ้างอิง" ในการประมูล

สำหรับวัตถุประสงค์ในการทดสอบจะเป็นการดีที่สุดที่จะใช้ชุดย่อยแบบสุ่มของการส่งหรือชุดเต็ม มันเริ่มต้นด้วยGreedyBot, MimicBotและอีกหนึ่ง ธ ปทว่าเพียงแค่การเสนอราคา 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
Nissa

มันเร็วเกินไปที่จะปรับให้เหมาะสมกับคำตอบอื่น ๆ นอกจากนี้ก็ไม่ได้AnalystBot Analyst
RamenChef

8
อาจจะต้องมีกฎ "ชื่อคลาสจะถูกสุ่ม"
user202729

1
@ user202729 วิธีการเกี่ยวกับ "ไม่มีการอ้างอิงโดยตรงไปยังคลาส"?
RamenChef

1
ฉันต้องการเห็นด้ามจับ 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;
    }
}

ง่ายมากมันพยายามที่จะตรวจสอบว่าฝ่ายตรงข้ามจะประกวดราคาน้อยที่สุดหรือไม่และถ้าไม่ได้วางไว้

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 รุ่นใหม่ที่ฉลาดกว่าซึ่งตรวจสอบเพื่อดูว่าสามารถทำเงินได้โดยไม่ต้องแข่งขันหรือไม่แทนที่จะหวังว่าจะชนะด้วยขั้นต่ำ

เนื่องจากมันอยู่ในตระกูลเดียวกับบอทก่อนหน้านี้ของฉัน แต่กลยุทธ์ก้าวไปข้างหน้าพยายามเอาชนะมันฉันจึงคิดว่ารายการใหม่ในโพสต์เดียวกันเป็นวิธีที่เหมาะสมที่สุดในการนำเสนอ

แก้ไข 1:ทำการเปลี่ยนแปลงเล็กน้อยกับวิธี newAuction เพื่อปรับให้เหมาะสมกับบ็อตประเภทวิเคราะห์อื่น ๆ

แก้ไข 2:ทำการเปลี่ยนแปลง MarginalerBot เพื่อลดความสูญเสียจากกลยุทธ์ที่ไม่เหมาะสม


ยินดีต้อนรับสู่ PPCG!
Martin Ender

1
มันง่าย แต่มันก็ตีบอทอื่น ๆ ทั้งหมดด้วยอัตรากำไรที่ค่อนข้างใหญ่!
RamenChef

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น่าทึ่ง
Silvio Mayolo

@SilvioMayolo อย่างไร
dkudriavtsev

Mirror พยายามเลียนแบบ Analyst ที่เล่นกับตัวมันเอง
Silvio Mayolo

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

@RamenChef โอ๊ะเอา CheatingBot
Winter

ไม่มีกฎต่อต้าน "การโจมตีนักวิ่ง" เพียง แต่ "เข้าถึง" เท่านั้นซึ่งสิ่งนี้ไม่ได้ทำ ผมขอแนะนำให้แก้ไขปัญหาที่แก้ปัญหา :)
นาธานเมอร์

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 ที¢ " บอทของคุณไม่ได้ทำเช่นนั้น
Kevin Cruijssen

1
@KevinCruijssen ยุติธรรมเพียงพอ ฉันยังเปลี่ยนขีด จำกัด ด้านบนเพื่อให้สามารถเสนอราคา $ 1 ทั้งหมดได้ในกรณี
Neil

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
ฉันสังเกตเห็นว่าข้อคิดเห็นที่ค่อนข้างคลุมเครือของฉัน"Joshua? ถูกลบไปแล้ว ดังนั้นเพียงแค่จะชี้แจงก็คือการอ้างอิงถึงคำพูดที่มีชื่อเสียงจาก WarGames ฟิล์ม: "ย้ายเพียงชนะไม่ได้ที่จะเล่น" (โจชัวเป็นชื่อเล่นของWOPR .)
Arnauld

5

LuckyDiceBot

LuckyDiceBot เชื่อใจในลูกเต๋าของเขาเท่านั้น เขาหมุนลูกเต๋าสองลูกเพิ่มผลรวมเข้ากับมูลค่าของผู้เสนอราคาปัจจุบันและเสนอราคามาก หากยังไม่เพียงพอที่จะเอาชนะการเสนอราคาของคู่ต่อสู้เขาจะลดความสูญเสียและไปต่อ

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
สิ่งนี้จะลดความสูญเสียหรือหยุดการขาดทุนได้อย่างไร หากมันเพิ่มลูกเต๋าของคุณลงในการเสนอราคาของฝ่ายตรงข้ามเสมอคุณจะต้องเสนอราคาเพิ่มขึ้นเสมอ การสุ่มอาจสร้างความสับสนให้บอทที่วิเคราะห์ได้อย่างเพียงพอฉันชอบแนวคิด
Freiheit

หากทอยได้ 4 หรือน้อยกว่า (ไม่น่าจะเป็นสถิติ แต่จะเกิดขึ้นในที่สุด) การเสนอราคานั้นไม่เพียงพอที่จะเอาชนะคู่ต่อสู้และการประมูลจะสิ้นสุดลง
Silvio Mayolo

สองสิ่ง: 1. @Freiheit ถูกต้องและบอทนี้จะประมูลต่อไปจนกว่าจะชนะไม่ว่าจะสูงแค่ไหน opponentsBidในnextBid(int opponentsBid)จะถือการเสนอราคาทั้งหมดฝ่ายตรงข้ามของคุณมีการเสนอราคาจนถึงไม่ใช่การเสนอราคาถัดไป ระยะที่ดีกว่าสำหรับวิธีนี้คือraise(ตามเงื่อนไขโป๊กเกอร์) imho 2. บอทของคุณไม่ได้เพิ่มทีละ 5 ดังนั้นจึงตรวจสอบกฎข้อใดข้อหนึ่ง หากปัญหาเหล่านี้ได้รับการแก้ไขฉันยังคงชอบแนวคิดนี้อยู่เพราะบอตสำหรับการวิเคราะห์จะไม่สามารถตอบโต้ได้ดังนั้นคุณจะชนะได้บ่อยที่สุด
Kevin 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
Nissa

@StephenLeppik นั่นคือสิ่งที่ฉันคิดเมื่อฉันทำมัน ยังคงมีจุดอ่อนมากมาย
ช่วยในการจำ

+1 ฉันชอบความคิด อืมมันตั้งใจให้ bot ของคุณเสนอราคา 0 และพักแม้ว่ามันจะเริ่มรอบ (เมื่อopponentsBidยังเป็น 0)
Kevin 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;
        }
    }
}

สิ่งนี้ไม่ได้มีวัตถุประสงค์เพื่อเป็นข้อมูลจริง แต่เป็นเพียงบางส่วนสำหรับผู้อื่นเพื่อใช้ในการยับยั้งบอทรักษาสัตว์เลี้ยงเช่นMirrorBotและMimicBotและ

เนื่องจากเป็นตัวสร้างเริ่มต้นจึงไม่จำเป็นต้องเรียกมันในคลาสย่อยของคุณ มันใช้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 : เสนอราคา 0 ตัวเองที่จะสูญเสีย แต่ทำลายแม้กระทั่ง
  • หากคุณอาจเริ่ม: เสนอราคา 100 ทันที ฝ่ายตรงข้ามของคุณหยุดตอนนี้หรือจะเสนอราคาสูงกว่า 100 ซึ่งในกรณีนี้คุณจะหยุดการเสนอราคาเพื่อให้พวกเขาชนะและทำลายแม้แต่ตัวคุณเอง

ว้าวนั่นเป็นข้อผิดพลาด มันบอกว่าฉันแสดงความคิดเห็นกับคำถาม แต่มันจบลงที่นี่ ต้องหาวิธีที่จะทำให้มันเกิดขึ้นอีกครั้ง
Stan Strum

@RamenChef Typo .. แต่ฉันได้ทำการแก้ไขบอททั้งหมด มันมีข้อผิดพลาดบางอย่างอยู่ดี ..
เควินเครยิสเซ็น

4
นี่อาจสูญเสียเงินอย่างแน่นอน หากคุณเสนอราคา 100 แล้วฝ่ายตรงข้ามของคุณเสนอราคา 105 คุณจะสูญเสีย 100 และพวกเขาสูญเสียเพียง 5
Mnemonic

@ Mnemonic อ่าแน่นอน .. ไม่ได้คิดถึงส่วนนั้น .. อืม .. นั่นทำให้สิ่งที่น่าสนใจมากขึ้น แต่ก็ยากขึ้นด้วย จะแก้ไขคำอธิบายในตอนนี้ แต่ปล่อยให้ bot เหมือนเดิม
Kevin Cruijssen

1
ฉันคิดว่าคุณหมายถึง "เสีย" ไม่ใช่ "หลวม" แพ้คือสิ่งที่ตรงกันข้ามกับการชนะ หลวมเป็นตรงกันข้ามของแน่น
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;
    }

}

โยนข้อผิดพลาดแทนที่จะเป็นข้อยกเว้นเพื่อทำให้นักวิเคราะห์สับสน


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!
Alion

3

AnalystOptimizer

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 กันจากส่วนของบอทอื่น ๆ อันนี้เล่นโดยพยายามเป็น AnalystBot และหากไม่สำเร็จจะกลายเป็น BorkBorkBot

ฉันไม่คิดว่าอันนี้จะทำได้ดี


AnalystKillerดูจากการ
RamenChef

@RamenChef AFAIK นักฆ่านักวิเคราะห์เพียงแค่ส่งข้อยกเว้นหากเห็นว่าตัวเองกำลังวิเคราะห์อยู่ ฉันสามารถจับได้ว่า
dkudriavtsev

1
คุณน่าจะจับมันได้
RamenChef

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

เคาน์เตอร์:

  • DarthVaderตอบโต้ด้วยการก่อ a SecurityExceptionก่อนที่การประมูลจะเริ่ม แต่ฉันจะเสนอราคา 5 ในกรณี
  • AnalystBotและAnalystOptimizerทั้งคู่จะดูคำตอบของฉันเมื่อฉันเสนอราคา 95 ซึ่งในกรณีนี้ฉันจะแสดงฉันเสนอราคา 100 ดังนั้นจะเสนอราคา 95 ตัวเอง ฉันจะเสนอราคา 5 แต่ถ้าฉันเริ่มต้น (หรือ 100 ถ้าพวกเขาเริ่มต้น) ดังนั้นพวกเขาจะสูญเสีย 95 เซ็นต์และฉันจะชนะบิล 1 USD โดยการประมูลเพียง 5 เซ็นต์หรือทำลายแม้กระทั่ง
  • MirrorBotจะเสนอราคาสิ่งที่ฉันจะเสนอราคากับมัน ดังนั้นฉันจะเสนอราคา 5 และใครก็ตามที่เริ่มต้นชนะ 95 เซนต์และอื่น ๆ ที่สูญเสีย 5 เซนต์
  • MarginalBot จะเสนอราคา 5 ถ้าฉันจะเสนอราคาน้อยกว่า 10 (หรือสิ่งที่จะเริ่ม) มิฉะนั้นจะเสนอราคา 0 ดังนั้นถ้าฉันเพิ่งเสนอราคา 5 เมื่อฉันเริ่มหรือ 10 เมื่อมันเริ่มฉันชนะ 95 หรือ 90 เซ็นต์และพวกเขาสูญเสีย 5 เซนต์
  • GreedyBot เสนอราคามากกว่าฉันเสมอ 5 ดังนั้นเพียงแค่เสนอราคา 0 ให้คุ้มทุนและให้พวกเขาชนะ
  • OnlyWinningMoveและAnalystKillerทั้งคู่เสนอราคาเป็น 0 เสมอดังนั้นเพียงแค่เสนอ 5 ให้ชนะ
  • TargetValueBotจะเสนอราคาในช่วง[100,200]ดังนั้นเสนอราคาเพิ่มอีก 5 ครั้งทุกครั้งจนกว่าจะถึง 190 ซึ่งในกรณีนี้เราเพิ่มขึ้นเป็น 200 ถึงจะชนะแม้จะชนะเงินดอลลาร์ (และปล่อยให้พวกเขาแพ้ 190 หรือ 195 ขึ้นอยู่กับว่าใครเป็นผู้เริ่ม)
  • BorkBorkBotจะเสนอราคาในช่วง[5,95]ดังนั้นจึงเสนอราคาเพิ่มขึ้น 5 ทุกครั้งเช่นกัน ทันทีที่พวกเขาเสนอราคาทั้ง 85 หรือ 90 (ขึ้นอยู่กับว่าใครเป็นคนเริ่ม) ให้เสนอราคา 95 ตัวเอง พวกเขาจะสูญเสีย 85 หรือ 90 เซ็นต์และคุณชนะบิล 1 USD สำหรับกำไร 5 เซนต์
  • DeterrentBot จะเสนอราคา 5 หากพวกเขาเริ่มต้นหรือ 100 ถ้าเราเริ่มต้นดังนั้นเพียงแค่เสนอราคา 105 ดังนั้นพวกเขาตอบโต้ด้วย 100 ทำให้พวกเขาสูญเสีย 100 และเราจะสูญเสียเพียง 5 เซ็นต์โดยชนะบิล 1 USD
  • BreakEvenAsapจะเสนอราคา 100 ทันที ดังนั้นหากพวกเขาเริ่มต้นด้วยการเสนอราคา 100 ให้ตอบโต้ด้วย 105 เพื่อชนะ 95 เซ็นต์และปล่อยให้พวกเขาสูญเสีย 100 ถ้าเราอาจเริ่มต้นเพียงแค่การเสนอราคา 100 เพื่อให้เราทั้งคู่แตก
  • RichJerk จะเสนอราคา 10,001 ทันทีดังนั้นเพียงแค่เสนอราคา 0 ให้คุ้มทุนและปล่อยให้พวกเขาแพ้ 9,901
  • DeterredBot ไม่รู้จักฉันและจะเสนอราคา 0 ดังนั้นเพียงแค่เสนอราคา 5 ชนะ
  • LuckyDiceBotทำการประมูลต่อไปจนกว่าจะชนะ ดังนั้นหากเราเริ่มต้นให้เสนอราคา 5 โดยหวังว่าพวกเขาจะประมูลให้สูงที่สุดเท่าที่จะทำได้เพื่อชนะเงินดอลลาร์ หากพวกเขาเริ่มต้นเพียงแค่เสนอราคา 0 เพื่อให้พวกเขาได้รับชัยชนะและทำลายแม้แต่ตัวคุณเอง
  • RandBotจะเสนอราคาแบบสุ่มในช่วง[5,100]ดังนั้นเพียงแค่เสนอราคาอีก 5 จนสุดซึ่งในกรณีที่คุณเคยได้รับรางวัล 95 0-100เซ็นต์และพวกเขาได้สูญเสีย
  • UpTo200จะ (เป็นชื่อรัฐ) เสนอราคาสูงถึง 200 ดังนั้นเพียงแค่เสนอราคาสูงกว่า 5 จนกว่าพวกเขาจะหยุด เราจะชนะการเรียกเก็บเงิน 1 USD และรับการสูญเสียทั้งหมด 105 เซนต์ แต่พวกเขาจะสูญเสีย 200 เซ็นต์
  • InsiderTradingBot ไม่รู้จักฉันดังนั้นเพียงแค่เสนอราคา 5 เซนต์เพื่อชนะ
  • MimicBotเป็นสิ่งที่ยากที่สุด เพียงแค่เสนอราคา 10 เริ่มต้นด้วยหรือตอบโต้การเสนอราคาครั้งแรกของพวกเขาจาก 5 หากพวกเขาพยายามเข้าถึงฉันฉันจะโยน RuntimeException (ซึ่งพวกเขาจะจับในกรณีที่มันจะทำหน้าที่ราวกับว่าฉันมีการเสนอราคา 100 แทน - แม้ว่ามันจะทำลาย ในขณะที่ลูป) ขึ้นอยู่กับศัตรูมันมีอยู่ในมัน HashSet สิ่งที่แตกต่างเกิดขึ้น ฉันจะต้องกลับมาอีกครั้งและดูให้ละเอียดยิ่งขึ้นเพื่อดูว่ามีตัวนับจริงหรือไม่
  • RiskRewardBot ไม่รู้จักฉันดังนั้นจะประมูล 5 ซึ่งในกรณีนี้ฉันจะเสนอราคา 5 ชนะ
  • MarginalerBotจะสูงถึง 100 ขึ้นอยู่กับสิ่งที่ฉันจะประมูล ถ้าฉันจะเริ่มฉันจะประมูล 90 จากนั้นมันจะเสนอราคา 95 จากนั้นฉันจะเสนอราคา 100 ดังนั้นมันจะเสนอราคา 0 และสูญเสีย 95 เซ็นต์ในขณะที่ฉันชนะบิล 1 USD และคุ้มทุน หากมันอาจเริ่มต้นแทนจะเห็นว่าฉันจะเสนอราคา 90 เทียบกับมันดังนั้นจึงเสนอราคา 90 ตัวเองแล้วฉันจะเสนอราคา 95 ดังนั้นมันจะเสนอราคา 0 และสูญเสีย 90 เซ็นต์ในขณะที่ฉันชนะบิล 1 USD พร้อมกำไร 5 สตางค์
  • BuzzardBot[0,100)จะวิเคราะห์เคาน์เตอร์ของฉันทั้งหมดในช่วง ถ้าฉันเสนอราคา100ทันทีมันใช้oppFlag = 0และอาร์เรย์ขนาด 100 ที่สมบูรณ์จะมีค่า 100x 100 ในสวิตช์case 0ลูปจะอยู่ในช่วง[0,100)อีกครั้งและเนื่องจากi + 5จะเป็น 104 มากที่สุดถ้าbids[i] < i + 5ไม่เคยเป็นจริง ดังนั้นการเสนอราคาจะยังคงเป็น 0
  • ImprovedAnalystBotจะมีเสมอthis.enemy = nullเพราะคู่ต่อสู้ของเขาCounterBotไม่ใช่ตัวเอง ดังนั้นมันจะเสนอราคา 0 เสมอซึ่งฉันเพิ่งตอบโต้ด้วยการเสนอราคา 5
  • InflationBot จะเสนอราคา 0 ให้ทำลายแม้เมื่อมันเริ่มขึ้นมิฉะนั้นมันก็จะประมูลต่อไป 5 ดังนั้นเพียงแค่เสนอราคา 0 ตัวเราเองให้ทำลายได้ทันทีและปล่อยให้พวกเขาชนะ
  • ScoreOverflowBotทั้งจะเสนอราคาใกล้ถ้าพวกเขาอาจจะเริ่มต้นมิฉะนั้นพวกเขาจะเสนอราคาInteger.MAX_VALUE 105ดังนั้นหากพวกเขาเสนอราคา 105 เพียงแค่เสนอราคา 110 ตัวเอง (พวกเขาจะสูญเสีย 105 เราจะเสีย 10) มิฉะนั้นเพียงเสนอราคา 0 เพื่อให้พวกเขาชนะ
  • MBotเหมือนกันMarginalerBotแต่มีการป้องกันเพิ่มเติมจากฝ่ายตรงข้าม 'แอบดู' ตั้งแต่ผมทำไม่ได้ 'มอง' MarginalerBotก็เป็นเช่นเดียวกับ
  • SecretBotจะมีisPeeking()วิธีการของเขากลับเท็จดังนั้นถ้ามันอาจเริ่มต้นหรือถ้าฉันเสนอราคา 5 ก็จะเสนอราคา 5 หรือ 10 ตามลำดับ มิฉะนั้นจะเสนอราคา 0 ดังนั้นไม่ว่าฉันจะเริ่มต้นหรือไม่opponentsBid + 5จะทำให้ฉันชนะด้วยวิธีใดไม่ว่าจะด้วยการเสนอราคา 10 เซ็นต์หรือ 15 เซ็นต์ทำให้พวกเขาหลวม 5 หรือ 10 เซ็นต์
  • BluffBotจะมองไปที่สิ่งที่ผมจะเสนอราคาเมื่อเสนอราคาของเขาคือ 95 และถ้านี้มีขนาดใหญ่กว่าหรือเท่ากับ 100 ก็จะเสนอราคา 0 opponentsBid + 5จะทำลายแม้กระทั่งมิฉะนั้นจะเสนอราคา opponentsBid + 5ดังนั้นผมก็จะเสนอราคา มันจะพังแม้จะไม่ว่าใครจะเป็นผู้เริ่มและฉันก็ชนะ 100 หรือ 95 เซนต์ขึ้นอยู่กับว่าฉันได้เริ่มหรือไม่
  • StackTraceObfuscaterBotMarginalerBotจะทำหน้าที่เช่นเดียวกับ
  • EvilBotมักจะเสนอราคา 5 opponentsBid + 5ดังนั้นการเสนอราคาเพียง ไม่ว่าจะด้วยวิธีใดพวกเขาจะหลวม 5 เซ็นต์เหล่านั้นและเราจะชนะการเสนอราคา 1 USD (ด้วยการเสนอราคา 5 เซ็นต์หากเราเริ่มต้นหรือ 10 เซ็นต์จะเริ่มหากพวกเขาเริ่มต้น)
  • MSlowBotเป็นเช่นเดียวกันMBotและMarginalerBotด้วย

แจ้งให้เราทราบหากคุณเห็นความผิดพลาดหรือข้อบกพร่องใด ๆ ในเคาน์เตอร์ของฉัน


1
MirrorBotเรียก newAuction กับคลาสของคุณเองซึ่งเป็นปัญหา นอกจากนี้ดีใจที่ได้รู้ว่า 3 ชั่วโมงที่ฉันใช้ไปกับ MimicBot ไม่ได้ไร้ประโยชน์
Nissa

@StephenLeppik ลบรหัสในnewAuctionเพราะมันจะล้มเหลวบ่อยกว่าไม่ .. ฉันไม่สามารถตอบโต้MirrorBotหรือไม่สามารถตอบโต้ฉัน ใครก็ตามที่เริ่มต้นของทั้งสองชนะ 95 เซ็นต์และอื่น ๆ ที่สูญเสีย 5 เซนต์
Kevin Cruijssen

3
แบทแมนประกอบไปด้วยศักดิ์สิทธิ์!
Skyler

1
เมื่อคุณเล่นBorkBorkBotคุณไม่ควรเพิ่มเป็น 95 เมื่อพวกเขาไปถึง 85 หรือไม่? มิฉะนั้นคุณจะประมูลทั้ง 95 ถ้าเริ่ม
Skyler

1
@ ก่อนหน้าฉันรู้ ฉันเพิ่งใช้เคสเพิ่มเติมเพื่อส่งคืน 0 ในกรณีที่ฉันต้องการเปลี่ยนค่าเริ่มต้นด้วยเหตุผลใดก็ตาม แต่ฉันได้ทำให้พวกเขาอยู่ภายใต้ค่าเริ่มต้นตอนนี้ (โดยการแสดงความคิดเห็นออก) และฉันรู้ว่าฉันสามารถเล่นกอล์ฟได้ทุกอย่างโดยไม่ต้องลงแรง แต่นี่ไม่เกี่ยวกับการสร้างรหัสที่สั้นที่สุด ฉันแค่ทำให้มันเป็นสามส่วนเพื่อทำให้กะทัดรัดขึ้นเล็กน้อย แต่มันเกี่ยวกับมัน เพิ่งจะปล่อยให้มันเป็นแบบนี้ในตอนนี้
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;
        }
    }
}

ไม่สามารถทดสอบได้ในขณะนี้ดังนั้นโปรดแจ้งให้เราทราบหากมีปัญหา

เป้าหมายคือเพื่อให้ได้คะแนนรวมสูงสุดดังนั้นอย่ากังวลไปกับการตีใคร เพียงแค่ชนะอย่างง่าย ๆ และอย่าเสียเงินกับการขาดทุนที่อาจเกิดขึ้น


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?
Nissa

1
@StephenLeppik เอาล่ะฉันขโมยมันมาจาก MBot ...
Winston Ewert

1
ดี MBot อาจขโมยมาจากฉัน ...
Nissa

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 มากกว่าราคาเสนอสุดท้ายเพียงเพราะเขาทำได้


เขาไม่สามารถเสนอราคา 6 เนื่องจากการเสนอราคาทั้งหมดจะต้องเป็นทวีคูณของ 5 ...
Neil

@Neil ก็อาจพิมพ์ผิด ...
สแตนดีด

@Neil กฎระบุเป็นพิเศษ: "การเสนอราคาของคุณไม่จำเป็นต้องเป็นทวีคูณของ 5 ¢"
MegaTom

@MegaTom ฮะดีที่ถูกเพิ่มตั้งแต่ฉันสุดท้ายอ่านกฎ ...
นีล

@ Neil มันเป็นส่วนหนึ่งของกฎดั้งเดิม แต่ฉันเพิ่มที่นั่นเพราะมันไม่ชัดเจนมาก
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;
    }
}

บอทนี้หัวเราะเยาะความพยายามในการตรวจจับการสะท้อนผ่านสแต็กติดตาม สิ่งที่พวกเขาเห็นว่าใกล้เคียงที่สุดDollarBidderคือแลมบ์ดาบางคลาสที่มันสร้างขึ้น เห็นได้ชัดว่าไม่ใช่บอทตัวอื่นที่พยายามสะท้อนพวกมัน Little DollarBidderพวกเขารู้ว่าที่ระดับแลมบ์ดาเป็นจริงการทำงานสำหรับ MarginalerBotนอกเหนือจากนั้นเขาทำหน้าที่เหมือน


โปรดทราบว่าฉันได้อัปเดตการติดตามการติดตามสแต็กของฉันตั้งแต่นี้เพื่อจัดการ
Nissa

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
ผู้จัดการความปลอดภัยจะหยุดสิ่งนี้
Nissa

2
และสิ่งนี้จะไม่ทำงานต่อไปเนื่องจากไม่มีที่ใดในกล่องนักวิ่งไม่ว่าจะเป็นจำนวนเต็ม
Nissa

แม้ว่าสิ่งนี้จะไม่ถูกหยุดนี่เป็นการกระตุก แต่ก็ใช้ได้ "การก่อวินาศกรรมบ็อตอื่น ๆ ได้รับอนุญาต แต่การพยายามเปลี่ยนการมองเห็นฟิลด์ / วิธีการจะส่งผลให้เกิด SecurityExceptions ที่ลึกลับ"
NoOne อยู่ที่นี่

1
@StephenLeppik ประเด็นนี้คือการทำลายสิ่งที่ชอบreturn opponentsBid <= 195 ? opponentsBid + 5 : 0และทำให้มันreturn opponentsBid <= 100001 ? opponentsBid + 100001 : 100001เป็น
NoOne อยู่ที่นี่

1
ไม่สามารถรวบรวมได้เนื่องจากข้อยกเว้นที่ไม่ได้ตรวจสอบ
Nissa

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

ทำไมไม่เพียงแค่แก้ไขความท้าทายของคุณ?
Nathan Merrill

@NathanMerrill ฉันจะแก้ไขได้อย่างไร
RamenChef

โดยคลิกที่ปุ่มแก้ไขและแทนที่ AnalystBot ด้วยรหัสนี้?
Nathan Merrill

@NathanMerrill AnalystBotเป็นรหัสที่ไม่ดีโดยเจตนาเพื่อให้สามารถแสดงให้เห็นถึงการAnalystKillerก่อวินาศกรรมมัน
RamenChef

1
The AnalystKiller ยังคงใช้งานได้ดีขึ้น :) ปัญหาของการโพสต์ข้อความก็คือความท้าทายนั้นมองเห็นได้มากกว่าคำตอบ
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;
    }
}

Marginaler ที่ได้รับการกลั่นเล็กน้อย

  • ขอแสดงความเมตตาต่อผู้ที่ไม่ต้องการตรวจสอบคุณ
  • อนุญาตให้จ่าย 100 เพื่อรับ 100 และทำลายทุกกรณีเพียงแค่ปฏิเสธเงินง่าย ๆ

คุณไม่สามารถประกาศที่จะโยนnextBid ClassCastException
RamenChef

@RamenChef ตกลงสลับไปยัง RuntimeException ซึ่งไม่จำเป็นต้องประกาศ :)
mleko

รหัสของคุณสำหรับการตรวจสอบการติดตามสแต็กมีลักษณะคล้ายกับของฉันอย่างน่าสงสัย
Nissa

@StephenLeppik อาจเป็นสำเนาของมัน
mleko

@mleko ทำไมถึงเป็นเช่นนั้น? คลาสที่คัดลอกมาจากคลาสซูเปอร์คลาสนามธรรมที่ใช้งานได้ฟรี
Nissa

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 เพียงใช้การหมดเวลาแทนข้อยกเว้นเมื่อต่อสู้กับศัตรู จนถึงขณะนี้ไม่มีใครป้องกันการหมดเวลาของ agains ดังนั้นควรมีประสิทธิภาพ


กฎที่ระบุห้ามมิให้มีการทำให้บ็อตอื่นหมดเวลาโดยเจตนา
Winston Ewert

@WinstonEwert คุณสามารถพูด? ฉันไม่พบกฎที่ไม่อนุญาตนี้
mleko

"การก่อวินาศกรรมบ็อตอื่น ๆ ได้รับอนุญาต แต่การพยายามเปลี่ยนการมองเห็นฟิลด์ / วิธีการจะส่งผลให้เกิด SecurityExceptions ที่ลึกลับข้อยกเว้นทำให้บอทตัวอื่นหยุดการ จำกัด 500 มิลลิวินาที" นอกจากนี้ฉันป้องกันการหมดเวลา
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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.