package bots.demobots;
import com.biotools.meerkat.*;
import com.biotools.meerkat.util.Preferences;
import java.util.Random;
/**
* @author oursland
* <p/>
* See <a href="http://oursland.net/projects/pabots">Oursland</a>
*/
public class ChumpBot implements Player {
// private Preferences prefs = new Preferences();
private GameInfo gameInfo = null;
private Card c1 = new Card();
private Card c2 = new Card();
private int seat;
private int stageCount = 0;
private double basicRaise = 0.0;
private HandEvaluator he = new HandEvaluator();
private Random random = new Random();
private double fear = 0.0;
private static final double[] BRAVERY = {0.60, 0.75, 0.82, 0.88, 0.9, 0.92, 0.98, 0.995, 1.0};
private static final double[] BOLDNESS = {1.0, 1.2, 1.3, 1.35, 1.4, 1.45, 1.5, 1.7, 2.0};
private double bravery = 0.9;
private double boldness = 1.4;
public void holeCards(Card c1, Card c2, int seat) {
this.c1 = c1;
this.c2 = c2;
this.seat = seat;
}
public Action getAction() {
double callAmount = gameInfo.getAmountToCall(seat);
Action rc = Action.callAction(callAmount);
switch (gameInfo.getStage()) {
case Holdem.PREFLOP: {
rc = preFlopAction(stageCount, rc);
}
break;
case Holdem.FLOP: {
rc = postFlopAction(0.5, 0.8, stageCount, rc);
}
break;
case Holdem.TURN: {
rc = postFlopAction(0.2, 0.8, stageCount, rc);
}
break;
case Holdem.RIVER: {
rc = postFlopAction(0.1, 0.8, stageCount, rc);
}
break;
default: {
throw new Error();
}
}
stageCount++;
return rc;
}
public void init(Preferences prefs) {
// TODO Initialize your player from the given preferences file.
// this.prefs = prefs;
this.basicRaise = 0.0;
setPlayStyle();
}
private void setPlayStyle() {
this.bravery = BRAVERY[random.nextInt(BRAVERY.length)];
this.boldness = BOLDNESS[random.nextInt(BOLDNESS.length)];
}
public void gameStartEvent(GameInfo gameInfo) {
// The hand is starting
this.gameInfo = gameInfo;
// initialize betting structure based on the starting chip amount
if (this.basicRaise == 0.0) {
this.basicRaise = gameInfo.getBankRoll(gameInfo.getCurrentPlayerSeat()) / 40;
}
this.fear = 0.0;
}
private Action postFlopAction(double strength, double bluff, int stageCount, Action defaultAction) {
double toCall = gameInfo.getAmountToCall(seat);
updateFear(toCall);
strength = Math.pow(strength, Math.pow(bravery, fear + stageCount * 5));
bluff = Math.pow(bluff, Math.pow(boldness, fear + stageCount * 5));
double handRank = HandEvaluator.handRank(c1, c2, gameInfo.getBoard());
double bluffChoice = random.nextDouble();
if (stageCount < 2) {
if (handRank > 0.95 + 0.2 * strength) {
return safeRaise(toCall, 20);
} else if (handRank > 0.9 + 0.2 * strength) {
return safeRaise(toCall, 10);
} else if (handRank > 0.8 + 0.2 * strength) {
return safeRaise(toCall, 5);
} else if (handRank > 0.6 + 0.4 * strength) {
return safeRaise(toCall, 4);
} else if (handRank > 0.4 + 0.6 * strength) {
return safeRaise(toCall, 3);
} else if (handRank > 0.2 + 0.8 * strength) {
return safeRaise(toCall, 2);
} else if (handRank > strength) {
return safeRaise(toCall, 1);
} else if (bluffChoice < Math.pow(bluff, 12)) {
return Action.raiseAction(toCall, 5 * basicRaise);
} else if (bluffChoice < Math.pow(bluff, 10)) {
return Action.raiseAction(toCall, 4 * basicRaise);
} else if (bluffChoice < Math.pow(bluff, 8)) {
return Action.raiseAction(toCall, 3 * basicRaise);
} else if (bluffChoice < Math.pow(bluff, 6)) {
return Action.raiseAction(toCall, 2 * basicRaise);
} else if (bluffChoice < Math.pow(bluff, 4)) {
return Action.raiseAction(toCall, 1 * basicRaise);
} else if (toCall > 0.0 && bluffChoice > Math.pow(bluff, 1)) {
return Action.foldAction(toCall);
}
}
return defaultAction;
}
private Action safeRaise(double toCall, double mult) {
int mySeat = gameInfo.getCurrentPlayerSeat();
boolean canRaise = gameInfo.canRaise(mySeat);
double minRaise = gameInfo.getMinRaise();
mult -= mult * random.nextGaussian() / 4;
if (mult < 0) {
mult = 0;
}
double raise = mult * basicRaise - toCall;
if (raise > 0.0 && raise > minRaise && canRaise) {
raise = Math.min(raise, gameInfo.getBankRoll(mySeat));
return Action.raiseAction(toCall, raise);
} else {
return Action.callAction(toCall);
}
}
private void updateFear(double toCall) {
double tightenUp = toCall / basicRaise;
while (tightenUp > 3) {
fear += 1;
tightenUp /= 1.5;
}
}
public Action preFlopAction(int stageCount, Action defaultAction) {
double toCall = gameInfo.getAmountToCall(seat);
updateFear(toCall);
if (stageCount < 2) {
boolean fold = true;
fold &= c1.getRank() < Card.TEN;
fold &= c1.getRank() < Card.TEN;
fold &= isHoleStraight();
fold &= isHoleFlush();
fold &= toCall > 0.0;
if (fold) {
return Action.foldAction(0.0);
}
int raiseCount = 0;
if (c1.getRank() == c2.getRank()) {
raiseCount += Math.ceil(Math.sqrt(c1.getRank()));
}
if (isHoleStraight() && isHoleFlush()) {
raiseCount += 1;
}
if (raiseCount > 0) {
return Action.raiseAction(toCall, raiseCount * basicRaise);
}
}
return defaultAction;
}
private boolean isHoleFlush() {
return c1.getSuit() != c2.getSuit();
}
private boolean isHoleStraight() {
return Math.abs(c1.getRank() - c2.getRank()) > 3;
}
public void actionEvent(int pos, Action action) {
// TODO A player can override this method to recieve events for each action made by a player.
}
public void winEvent(int pos, double amount, String handName) {
// TODO A player at pos has won amount with the hand handName
if (pos != seat && random.nextDouble() < 0.1) {
setPlayStyle();
}
}
public void stageEvent(int stage) {
// A new stage (betting round) has begun.
stageCount = 0;
}
public void showdownEvent(int pos, Card c1, Card c2) {
// Player pos has shown two cards.
}
public void gameOverEvent() {
// The hand is now over.
}
public void gameStateChanged() {
// The game info state has been updated Called after an action event has been fully processed
}
public void dealHoleCardsEvent() {
// TODO Auto-generated method stub
}
}