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


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.