Dollar Bill Auction
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;
}
}
}
Holy cow. I expected this to be simple to write, then subsequently spent 3 hours on it.
In essence, MimicBot
keeps a running list of the available bots. When it goes to a new auction, it runs through the list in search of the most effective one against the current opponent. It then uses that bot as a "reference" in the auction.
For testing purposes, it would be best to use either a randomized subset of the submissions or the full set. It starts with GreedyBot
, MimicBot
, and one more bot that just bids 5¢.
InsiderTradingBot
In the spirit of @StephenLeppik's answer, InsiderTradingBot knows all of his opponents and understands their strategies. Your move, Stephen.
import net.ramenchef.dollarauction.DollarBidder;
public class InsiderTradingBot extends DollarBidder {
private static boolean analystNutcracker = false;
private int bid;
@Override
public void newAuction(Class<? extends DollarBidder> opponent) {
if (opponent.equals(DeterredBot.class) ||
opponent.equals(OnlyWinningMove.class) ||
opponent.equals(MirrorBot.class)) {
// I can do this ^.^
bid = 5;
} else if (opponent.equals(AnalystKiller.class)) {
// Outbid 'em >:D
bid = 10;
} else if (opponent.equals(BreakEvenAsap.class) ||
opponent.equals(BorkBorkBot.class) ||
opponent.equals(DeterrentBot.class)) {
// Break even quicker!
bid = 100;
} else if (opponent.equals(InsiderTradingBot.class)) {
// I'm probably a simulation inside MirrorBot
bid = 0;
} else if (opponent.equals(Analyst.class)) {
// Let's fight the Analyst with the power of global variables
bid = 100;
analystNutcracker = true;
} else {
// Welp
bid = 0;
}
}
@Override
public int nextBid(int opponentsBid) {
if ((opponentsBid == 95) && analystNutcracker) {
analystNutcracker = false;
return 0;
}
return bid;
}
};
MirrorBot
Makes the enemy play against itself.
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);
}
}
}