Package org.cspoker.ai.opponentmodels.weka

Source Code of org.cspoker.ai.opponentmodels.weka.Propositionalizer

/**
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.cspoker.ai.opponentmodels.weka;

import java.util.EnumSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.cspoker.common.elements.cards.Card;
import org.cspoker.common.handeval.spears2p2.StateTableEvaluator;

import com.google.common.collect.Multiset;
import com.google.common.collect.TreeMultiset;

public class Propositionalizer implements Cloneable {

  private Map<Object, PlayerData> players = new HashMap<Object, PlayerData>();
  private List<PlayerData> activePlayers = new LinkedList<PlayerData>();
  private List<PlayerData> allinPlayers = new LinkedList<PlayerData>();

  private int bb = 0;

  private int maxBet = 0;
  private int lastRaise = 0;
  private int gameRaiseAmount = 0;
  private boolean somebodyActedThisRound = false;

  private BetStatistics gameStats = new BetStatistics();
  private String round = "preflop";
  private int totalPot = 0;

  private int nbPlayersDoneThisRound = 0;
  private int nbSeatedPlayers = 0;
  private EnumSet<Card> cards;

  private int minRank=0;
  private int maxRank=0;
  private int averageRank=0;
  private double sigmaRank=0;

  public Propositionalizer() {
  }

  @Override
  public Propositionalizer clone() {
    try {
      Propositionalizer clone = (Propositionalizer)super.clone();

      //clone player map (is this needed?)
      Map<Object, PlayerData> playersClone = new HashMap<Object, PlayerData>(clone.getPlayers());

      //clone the active players at this table. they are mutable
      List<PlayerData> activePlayersClone = new LinkedList<PlayerData>();
      for (PlayerData player : activePlayers) {
        PlayerData playerClone = player.clone();
        activePlayersClone.add(playerClone);
        playersClone.put(playerClone.getId(), playerClone);
      }

      //no need to clone contents of allinPlayers, is immutable
      //do need to clone the list itself
      List<PlayerData> allinplayersClone = new LinkedList<PlayerData>(clone.getAllinPlayers());
      clone.players = playersClone;
      clone.activePlayers = activePlayersClone;
      clone.allinPlayers = allinplayersClone;
      clone.gameStats = gameStats.clone();
      return clone;
    } catch (CloneNotSupportedException e) {
      throw new IllegalStateException(e);
    }
  }

  public void signalBBAmount(int bb){
    this.bb=bb;
    for(PlayerData p:activePlayers) p.signalBBAmount(bb);
  }

  public void signalAllIn(Object id, int chipsMoved) {
    if(inPreFlopRound() && maxBet<bb && chipsMoved <= bb){
      signalBlind(true, id, chipsMoved);
    }else{
      PlayerData p = players.get(id);
      //call raise or bet
      if(maxBet==0){
        signalBet(true, id, chipsMoved);
      }else if(p.getDeficit(this)<chipsMoved){
        signalRaise(true, id, p.getBet()+chipsMoved);
      }else{
        signalCall(true, id, chipsMoved);
      }
    }
  }

  public void signalBet(boolean isAllIn, Object id, int movedAmount) {
    PlayerData p = players.get(id);
    logBet(id, movedAmount/(double)bb);
    if(isAllIn) {
      activePlayers.remove(p);
      allinPlayers.add(p);
    }
    // we also consider a raise by big blind here, treat kinda like bet!
    // that's why the +=
    maxBet += movedAmount;
    lastRaise = Math.max(lastRaise, movedAmount);
    gameRaiseAmount += movedAmount;
    totalPot += movedAmount;
    somebodyActedThisRound = true;
    gameStats.addBet(this,movedAmount/(double)bb);
    p.signalBet(this,movedAmount);
  }

  public void signalCheck(Object id) {
    PlayerData p = players.get(id);
    logCheck(id);
    ++nbPlayersDoneThisRound;
    gameStats.addCheck(this);
    somebodyActedThisRound = true;
    p.signalCheck(this);
  }

  public void signalRaise(boolean isAllIn, Object id, int maxBetParsed) {
    PlayerData p = players.get(id);
    int raiseAmount = maxBetParsed-maxBet;
    if (p.getDeficit(this) == 0) {
      signalBet(isAllIn, id, raiseAmount);
    } else {
      logRaise(id,raiseAmount/(double)bb);
      if(isAllIn) {
        activePlayers.remove(p);
        allinPlayers.add(p);
      }
      maxBet = maxBetParsed;
      lastRaise = Math.max(lastRaise, raiseAmount);
      int movedAmount = maxBet - p.getBet();
      gameRaiseAmount += raiseAmount;

      totalPot += movedAmount;
      somebodyActedThisRound = true;
      gameStats.addRaise(this, (movedAmount-raiseAmount)/(double)bb, raiseAmount/(double)bb);
      p.signalRaise(this,raiseAmount,movedAmount);
    }
    nbPlayersDoneThisRound = 0;
  }


  public void signalCall(boolean isAllIn, Object id) {
    PlayerData p = players.get(id);
    if(p.getDeficit(this)==0){
      signalCheck(id);
    }else{
      signalCall(isAllIn, id, Math.min(p.getStack(), maxBet-p.getBet()));
    }
  }

  public void signalCall(boolean isAllIn, Object id, int movedAmount) {
    PlayerData p = players.get(id);
    logCall(id);

    if(isAllIn){
      activePlayers.remove(p);
      allinPlayers.add(p);
    }
    totalPot += movedAmount;
    ++nbPlayersDoneThisRound;
    somebodyActedThisRound = true;
    gameStats.addCall(this, movedAmount/(double)bb);
    p.signalCall(this,movedAmount);
  }

  public void signalFold(Object id) {
    PlayerData p = players.get(id);
    if(p.getDeficit(this)>0) logFold(id);

    activePlayers.remove(p);
    somebodyActedThisRound = true;
    gameStats.addFold(this);
    p.signalFold(this);
  }


  public void signalBlind(boolean isAllIn, Object playerId, int amount) {
    PlayerData p = players.get(playerId);

    //TODO change amount when allin
    maxBet = amount;
    totalPot += amount;
    if (isAllIn) {
      activePlayers.remove(p);
      allinPlayers.add(p);
    }
    p.signalBlind(amount);
  }


  public void signalRiver() {
    if(!activePlayers.isEmpty()){
      round = "river";
      startNewRound();
    }
  }

  public void signalTurn() {
    if(!activePlayers.isEmpty()){
      round = "turn";
      startNewRound();
    }
  }

  public void signalFlop() {
    if(!activePlayers.isEmpty()){
      round = "flop";
      startNewRound();
      for (PlayerData p : activePlayers) {
        p.signalFlop();
      }
    }
  }

  public void signalCommunityCards(EnumSet<Card> cardsSet) {
    this.cards =cardsSet;
    //updateER();
  }

  public void signalCardShowdown(Object id, Card card1, Card card2) {
//    PlayerData p = players.get(id);
    if(cards.size()==5){
      //showdown after river
      Multiset<Integer> ranks = new TreeMultiset<Integer>();
      //      int minSampleRank = Integer.MAX_VALUE;
      //      int maxSampleRank = Integer.MIN_VALUE;
      //      int sum = 0;

      int startRank = 53;
      for (Card card:cards) {
        startRank = handRanks[card.ordinal() + 1 + startRank];
      }

      //add real rank
      int realRank = startRank;
      realRank = handRanks[card1.ordinal() + 1 + realRank];
      realRank = handRanks[card2.ordinal() + 1 + realRank];
      int realType = (realRank >>> 12) - 1;
      realRank = realRank & 0xFFF;
      realRank = offsets[realType] + realRank - 1;

      //take rank samples
      int nbBuckets = 6;
      int nbSamplesPerBucket = 6;
      int nbSamples = nbBuckets*nbSamplesPerBucket;
      for(int i=0;i<nbSamples;i++){

        int rank = startRank;
        Card sampleCard1;
        do{
          sampleCard1 = Card.values()[random.nextInt(Card.values().length)];
        }while(cards.contains(sampleCard1));
        rank = handRanks[sampleCard1.ordinal() + 1 + rank];

        Card sampleCard2;
        do{
          sampleCard2 = Card.values()[random.nextInt(Card.values().length)];
        }while(cards.contains(sampleCard2) || sampleCard2.equals(sampleCard1));
        rank = handRanks[sampleCard2.ordinal() + 1 + rank];

        int type = (rank >>> 12) - 1;
        rank = rank & 0xFFF;
        rank = offsets[type] + rank - 1;

        ranks.add(rank);

        //        if(rank<minSampleRank){
        //          minSampleRank = rank;
        //        }
        //        if(rank>maxSampleRank){
        //          maxSampleRank = rank;
        //        }
        //        sum += rank;
      }
      //      double var = 0;
      //      double mean = ((double)sum)/nbSamples;
      //      for (Multiset.Entry<Integer> entry : ranks.entrySet()) {
      //        double diff = mean - entry.getElement();
      //        var += diff * diff * entry.getCount();
      //      }
      //      var /= (nbSamples-1);
      //      int averageSampleRank = (int) Math.round(mean);
      //      int sigmaSampleRank = (int) Math.round(Math.sqrt(var));
      int[] bucketCounts = new int[nbBuckets];
      Iterator<Integer> iter = ranks.iterator();
      double realRankCount = ranks.count(realRank);
      //      long avgBucket = -1;
      double[] bucketDistr = new double[nbBuckets];
      if(realRankCount>0){
        for(int bucket=0;bucket<nbBuckets;bucket++){
          for (int i = 0; i < nbSamplesPerBucket; i++) {
            int rank = iter.next();
            if(rank==realRank){
              ++bucketCounts[bucket];
            }
          }
        }
        int partitionSum = 0;
        for (int i = 0; i < nbBuckets; i++) {
          bucketDistr[i] = bucketCounts[i]/realRankCount;
          partitionSum += bucketCounts[i]*i;
        }
        //      avgBucket = Math.round(partitionSum/realRankCount);
      }else{
        boolean found = false;
        bucketIteration: for(int bucket=0;bucket<nbBuckets;bucket++){
          for (int i = 0; i < nbSamplesPerBucket; i++) {
            int rank = iter.next();
            if(rank>realRank){
              bucketDistr[bucket]=1;
              //        avgBucket = bucket;
              found = true;
              break bucketIteration;
            }
          }
        }
        if(!found){
          bucketCounts[nbBuckets-1]=1;
          //        avgBucket = nbBuckets-1;
        }
      }
      logShowdown(id,bucketDistr);
    }else{
      //ignore
      //throw new IllegalStateException("everybody went all-in before the river");
    }
  }

  private final static int[] handRanks;
  static {
    handRanks = StateTableEvaluator.getInstance().handRanks;
  }
  private static final int[] offsets = new int[] { 0, 1277, 4137, 4995, 5853,
    5863, 7140, 7296, 7452 };
  private Random random = new Random(0);
  //
  //  private void updateExpectedRank() {
  //    Multiset<Integer> ranks = new HashMultiset<Integer>();
  //    minRank = Integer.MAX_VALUE;
  //    maxRank = Integer.MIN_VALUE;
  //    int sum = 0;
  //    int n = 100;
  //
  //    int startRank = 53;
  //    for (Card card:cards) {
  //      startRank = handRanks[card.ordinal() + 1 + startRank];
  //    }
  //    for(int i=0;i<n;i++){
  //      EnumSet<Card> sample = EnumSet.copyOf(cards);
  //      int rank = startRank;
  //      while(sample.size()<7){
  //        Card sampleCard;
  //        do{
  //          sampleCard = Card.values()[random.nextInt(Card.values().length)];
  //        }while(sample.contains(sampleCard));
  //        sample.add(sampleCard);
  //        rank = handRanks[sampleCard.ordinal() + 1 + rank];
  //      }
  //      int type = (rank >>> 12) - 1;
  //      rank = rank & 0xFFF;
  //      rank = offsets[type] + rank - 1;
  //      ranks.add(rank);
  //      if(rank<minRank){
  //        minRank = rank;
  //      }
  //      if(rank>maxRank){
  //        maxRank = rank;
  //      }
  //      sum += rank;
  //    }
  //    double var = 0;
  //    double mean = ((double)sum)/n;
  //    for (Multiset.Entry<Integer> entry : ranks.entrySet()) {
  //      double diff = mean - entry.getElement();
  //      var += diff * diff * entry.getCount();
  //    }
  //    var /= (n-1);
  //    averageRank = (int)Math.round(mean);
  //    sigmaRank = Math.round(Math.sqrt(var));
  //  }

  public void signalShowdown() {
    if (round.equals("flop") || round.equals("turn")
        || round.equals("river")) {
      for (PlayerData p : activePlayers) {
        p.signalShowdown();
      }
    }
  }

  public void signalSeatedPlayer(int stack, Object id) {
    PlayerData p = players.get(id);
    if (p == null) {
      p = new PlayerData(id);
      players.put(id, p);
    }
    activePlayers.add(p);
    p.signalBBAmount(bb);
    ++nbSeatedPlayers;
    p.startNewGame();
    p.resetStack(stack);
  }

  public void signalNewGame() {
    round = "preflop";
    somebodyActedThisRound = false;
    gameStats = new BetStatistics();
    nbPlayersDoneThisRound = 0;
    nbSeatedPlayers = 0;
    activePlayers.clear();
    allinPlayers.clear();
    gameRaiseAmount = 0;
    startNewRound();
  }

  protected void startNewRound() {
    for (PlayerData player : activePlayers) {
      player.startNewRound();
    }
    nbPlayersDoneThisRound = 0;
    maxBet = 0;
    lastRaise = bb;
    somebodyActedThisRound = false;
  }

  public boolean isSomebodyActedThisRound() {
    return somebodyActedThisRound;
  }

  public List<PlayerData> getActivePlayers() {
    return activePlayers;
  }

  public Map<Object, PlayerData> getPlayers() {
    return players;
  }

  public List<PlayerData> getAllinPlayers() {
    return allinPlayers;
  }

  public int getTotalPot() {
    return totalPot;
  }

  public int getMaxBet() {
    return maxBet;
  }

  public double getRelativeMaxBet() {
    return maxBet/(double)bb;
  }

  public int getAverageRank() {
    return averageRank;
  }

  public int getMaxRank() {
    return maxRank;
  }

  public BetStatistics getTableGameStats() {
    return gameStats;
  }

  public int getMinRank() {
    return minRank;
  }

  public double getSigmaRank() {
    return sigmaRank;
  }

  public int getNbSeatedPlayers() {
    return nbSeatedPlayers;
  }

  public int getNbActivePlayers() {
    return activePlayers.size();
  }

  public double getActivePlayerRatio() {
    return (double) getNbActivePlayers() / (double) getNbSeatedPlayers();
  }

  public int getPotSize() {
    return totalPot;
  }

  public double getRelativePotSize() {
    return totalPot/(double)bb;
  }

  public int getMaxMaxBet(){
    int maxBet1 = 0;
    int maxBet2 = 0;

    for (PlayerData player : activePlayers) {
      int maxMaxPlayerBet = player.getStack()+player.getBet();
      if(maxMaxPlayerBet>maxBet1){
        maxBet2 = maxBet1;
        maxBet1 = maxMaxPlayerBet;
      }else if(maxMaxPlayerBet > maxBet2){
        maxBet2 = maxMaxPlayerBet;
      }
    }
    return maxBet2;
  }


  public int getMaxRaise(PlayerData p) {
    int amountLeftToRaiseWith = p.getStack()-p.getDeficit(this);
    int maxRaise = Math.max(0, getMaxMaxBet()-getMaxBet());
    return Math.min(amountLeftToRaiseWith, maxRaise);
  }

  public int getMinRaise(PlayerData p) {
    return Math.min(lastRaise, getMaxRaise(p));
  }


  public int getPlayersToAct() {
    if (somebodyActedThisRound) {
      return getNbActivePlayers() - nbPlayersDoneThisRound - 1;
    }
    return getNbActivePlayers() - nbPlayersDoneThisRound;
  }

  public int getPlayersActed() {
    return nbPlayersDoneThisRound;
  }

  public double getRoundCompletion() {
    if (isSomebodyActedThisRound()) {
      if (getNbActivePlayers() <= 1) {
        return 0;
      }
      return nbPlayersDoneThisRound / (double) (getNbActivePlayers() - 1);
    }
    return nbPlayersDoneThisRound / (double) getNbActivePlayers();
  }

  public double getAverageAF(PlayerData p, int memory) {
    List<PlayerData> opponents = activePlayers.size()>1? activePlayers:allinPlayers;
    double sum = 0;
    int n = 0;
    for (PlayerData player : opponents) {
      if(!p.equals(player)) {
        sum += player.getGlobalStats().getAF(memory);
        ++n;
      }
    }
    return (sum/n);
  }

  public double getAverageVPIP(PlayerData p, int memory) {
    List<PlayerData> opponents = activePlayers.size()>1? activePlayers:allinPlayers;
    double sum = 0;
    int n = 0;
    for (PlayerData player : opponents) {
      if(!p.equals(player)) {
        sum += player.getVPIP(memory);
        ++n;
      }
    }
    return (sum/n);
  }

  public double getAveragePFR(PlayerData p, int memory) {
    List<PlayerData> opponents = activePlayers.size()>1? activePlayers:allinPlayers;
    double sum = 0;
    int n = 0;
    for (PlayerData player : opponents) {
      if(!p.equals(player)) {
        sum += player.getPFR(memory);
        ++n;
      }
    }
    return (sum/n);
  }

  public double getAverageAFq(PlayerData p, int memory) {
    List<PlayerData> opponents = activePlayers.size()>1? activePlayers:allinPlayers;
    double sum = 0;
    int n = 0;
    for (PlayerData player : opponents) {
      if(!p.equals(player)) {
        sum += player.getGlobalStats().getAFq(memory);
        ++n;
      }
    }
    return (sum/n);
  }

  public double getAverageAFAmount(PlayerData p, int memory) {
    List<PlayerData> opponents = activePlayers.size()>1? activePlayers:allinPlayers;
    double sum = 0;
    int n = 0;
    for (PlayerData player : opponents) {
      if(!p.equals(player)) {
        sum += Math.log(player.getGlobalStats().getAFAmount(memory));
        ++n;
      }
    }
    return (sum/n);
  }

  public double getAverageWtSD(PlayerData p, int memory) {
    List<PlayerData> opponents = activePlayers.size()>1? activePlayers:allinPlayers;
    double sum = 0;
    int n = 0;
    for (PlayerData player : opponents) {
      if(!p.equals(player)) {
        sum += player.getWtSD(memory);
        ++n;
      }
    }
    return (sum/n);
  }

  public String getRound() {
    return round;
  }

  public boolean inPreFlopRound() {
    return "preflop".equals(round);
  }

  public boolean inFlopRound() {
    return "flop".equals(round);
  }

  public boolean inTurnRound() {
    return "turn".equals(round);
  }

  public boolean inRiverRound() {
    return "river".equals(round);
  }

  protected void logBet(Object actorId, double raiseAmount){
    // no op
  }

  protected void logRaise(Object actorId, double raiseAmount){
    // no op
  }

  protected void logFold(Object actorId){
    // no op
  }

  protected void logCall(Object actorId){
    // no op
  }

  protected void logCheck(Object actorId){
    // no op
  }

  protected void logShowdown(Object actorId, double[] partitionDistr) {
    // no op
  }

  public double rel(double up, double down) {
    if(down==0) return 0;
    return up/down;
  }

}
TOP

Related Classes of org.cspoker.ai.opponentmodels.weka.Propositionalizer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.