5 new revisions:
Revision: 924800a73e30
Author: thijs
Date: Tue Nov 23 08:42:27 2010
Log: 1st part updating mctsbot to CSPoker revision 1396
http://code.google.com/p/opentestbed/source/detail?r=924800a73e30
Revision: 4b0bece8896a
Author: thijs
Date: Sat Nov 27 02:53:21 2010
Log: still updating to CSPoker 1396
http://code.google.com/p/opentestbed/source/detail?r=4b0bece8896a
Revision: 53fecd2eed22
Author: thijs
Date: Wed Dec 8 02:17:51 2010
Log: updated to cspoker revision 1396
http://code.google.com/p/opentestbed/source/detail?r=53fecd2eed22
Revision: 22da981dc500
Author: thijs
Date: Wed Dec 8 08:36:14 2010
Log: updated to CSPoker revision 1396
http://code.google.com/p/opentestbed/source/detail?r=22da981dc500
Revision: 46fc7fea811c
Author: thijs
Date: Tue Mar 29 00:27:29 2011
Log: own consolestarter
http://code.google.com/p/opentestbed/source/detail?r=46fc7fea811c
==============================================================================
Revision: 924800a73e30
Author: thijs
Date: Tue Nov 23 08:42:27 2010
Log: 1st part updating mctsbot to CSPoker revision 1396
http://code.google.com/p/opentestbed/source/detail?r=924800a73e30
Added:
/src/bots/mctsbot/ai/opponentmodels/weka/Prediction.java
Modified:
/src/bots/mctsbot/ai/opponentmodels/weka/ARFFFile.java
/src/bots/mctsbot/ai/opponentmodels/weka/ARFFPlayer.java
/src/bots/mctsbot/ai/opponentmodels/weka/ARFFPropositionalizer.java
/src/bots/mctsbot/ai/opponentmodels/weka/ActionTrackingVisitor.java
/src/bots/mctsbot/ai/opponentmodels/weka/PlayerTrackingVisitor.java
/src/bots/mctsbot/ai/opponentmodels/weka/WekaOptions.java
=======================================
--- /dev/null
+++ /src/bots/mctsbot/ai/opponentmodels/weka/Prediction.java Tue Nov 23
08:42:27 2010
@@ -0,0 +1,65 @@
+package bots.mctsbot.ai.opponentmodels.weka;
+
+import bots.mctsbot.ai.bots.bot.gametree.action.SearchBotAction;
+
+public class Prediction {
+
+ private SearchBotAction action;
+ private double probActual;
+ private double probHypothesis;
+
+ public Prediction(SearchBotAction action, double probActual, double
probHypothesis) {
+ // if (!checkProbability(probActual))
+ // throw new IllegalArgumentException("Incorrect probability of actual
action => " + probActual);
+ // if (!checkProbability(probHypothesis))
+ // throw new IllegalArgumentException("Incorrect probability of
hypothesis action => " + probHypothesis);
+
+ // TODO: why are probabilities wrong? then put IllegalArgumentException
back
+ if (!checkProbability(probActual))
+ probActual = correctProb(probActual);
+ if (!checkProbability(probHypothesis))
+ probHypothesis = correctProb(probHypothesis);
+
+ this.action = action;
+ this.probActual = probActual;
+ this.probHypothesis = probHypothesis;
+ }
+
+ private boolean checkProbability(double prob) {
+ return (prob >= 0.0 && prob <= 1.0);
+ }
+
+ private double correctProb(double prob) {
+ // System.err.println("Probability " + prob + " corrected to " + (prob
< 0.0?"0.0":"1.0"));
+ if (prob < 0.0)
+ return 0.0;
+ if (prob > 1.0)
+ return 1.0;
+ return prob;
+ }
+
+ public SearchBotAction getAction() {
+ return action;
+ }
+
+ public double getTruePositive() {
+ return Math.min(probActual, probHypothesis);
+ }
+
+ public double getTrueNegative() {
+ return Math.min(1 - probActual, 1 - probHypothesis);
+ }
+
+ public double getFalsePositive() {
+ return Math.max(0, (1 - probActual) - getTrueNegative());
+ }
+
+ public double getFalseNegative() {
+ return Math.max(0, probActual - getTruePositive());
+ }
+
+ @Override
+ public String toString() {
+ return action + " with probability " + probHypothesis;
+ }
+}
=======================================
--- /src/bots/mctsbot/ai/opponentmodels/weka/ARFFFile.java Thu May 27
13:49:11 2010
+++ /src/bots/mctsbot/ai/opponentmodels/weka/ARFFFile.java Tue Nov 23
08:42:27 2010
@@ -1,14 +1,10 @@
package bots.mctsbot.ai.opponentmodels.weka;
-import java.io.BufferedInputStream;
import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
-import java.io.InputStream;
import java.io.Writer;
+import java.util.ArrayList;
import weka.classifiers.Classifier;
import weka.classifiers.trees.M5P;
@@ -23,85 +19,228 @@
public class ARFFFile {
private final String nl = InstancesBuilder.nl;
-
- private File arffFile;
- private File path;
+ private final String path;
+ private final Object player;
+ private final String name;
private Writer file;
- private double count;
-
- private boolean modelReady;
-
- public ARFFFile(String path, Object player, String name, String
attributes, boolean overwrite) throws IOException {
- String playerPath = player.toString().replace("\\", "").replace("/", "");
-
- this.path = new File(path, playerPath);
-
- arffFile = new File(this.path, "/arff/" + name);
- if (!arffFile.getParentFile().exists()) {
- arffFile.getParentFile().mkdirs();
- }
- boolean fileExists = arffFile.exists();
- file = new BufferedWriter(new FileWriter(arffFile, !overwrite));
-
- if (overwrite || !fileExists) {
- file.write(attributes);
- file.flush();
- }
-
- count = countDataLines();
- if (count >= WekaOptions.getModelCreationTreshold())
- modelReady = true;
- }
-
- private double countDataLines() throws IOException {
- InputStream is = new BufferedInputStream(new FileInputStream(arffFile));
- byte[] c = new byte[1024];
- int count = 0;
- int readChars = 0;
- boolean startReading = false;
- while ((readChars = is.read(c)) != -1) {
- for (int i = 0; i < readChars; ++i) {
- if (c[i] == '\n' && startReading)
- ++count;
- else if (!startReading && i >= 4 && c[i - 4] == '@' && c[i - 3] == 'd'
&& c[i - 2] == 'a' && c[i - 1] == 't' && c[i] == 'a')
- startReading = true;
- }
- }
- is.close();
- return count + (count > 0 ? -1 : 0);
- }
+ private long count = 0;
+ private WekaOptions config;
+
+ private Instances instances;
+ private ArrayList<Prediction> predictions;
+ private M5P cl = null;
+
+ private boolean echo = false;
+
+ public ARFFFile(String path, Object player, String name, String
attributes, WekaOptions config) throws Exception {
+ // if (name.equals("PreFoldCallRaise.arff")) echo = true;
+ this.path = path;
+ this.player = player;
+
this.name = name;
+ this.config = config;
+
+ // TODO: false => !config.arffOverwrite()
+ file = new BufferedWriter(new FileWriter(path + player + name, false));
+ file.write(attributes);
+ file.flush();
+
+ DataSource source = new DataSource(path + player + name);
+ instances = source.getDataSet();
+ // make it clean
+ instances.delete();
+
+ predictions = new ArrayList<Prediction>();
+
+ // initiate accuracies
+ for (int i = 0; i < MAX_DECREASE; i++) {
+ accuracies[i] = -1;
+ }
+ }
+
+ // private double countDataLines() {
+ // InputStream is;
+ // try {
+ // is = new BufferedInputStream(new FileInputStream(path + player +
name));
+ // byte[] c = new byte[1024];
+ // int count = 0;
+ // int readChars = 0;
+ // boolean startReading = false;
+ // while ((readChars = is.read(c)) != -1) {
+ // for (int i = 0; i < readChars; ++i) {
+ // if (c[i] == '\n' && startReading)
+ // ++count;
+ // else if (!startReading && i >= 4 && c[i - 4] == '@'
+ // && c[i - 3] == 'd' && c[i - 2] == 'a'
+ // && c[i - 1] == 't' && c[i] == 'a')
+ // startReading = true;
+ // }
+ // }
+ // is.close();
+ // return count + (count > 0 ? -1 : 0);
+ // } catch (FileNotFoundException e) {
+ // e.printStackTrace();
+ // } catch (IOException e) {
+ // e.printStackTrace();
+ // }
+ // return 0;
+ // }
+ //
+ // private boolean fileExists() throws FileNotFoundException {
+ // return new File(path + player + name).exists();
+ // }
public void close() throws IOException {
file.close();
}
public void write(Instance instance) {
+ // System.out.println("Writing instance " + (count +1) + " in file " +
name);
try {
+ count++;
file.write(instance.toString() + nl);
file.flush();
- count++;
- if (count >= WekaOptions.getModelCreationTreshold())
- modelReady = true;
+ instances.add(instance);
+ adjustWindow();
} catch (IOException e) {
- e.printStackTrace();
throw new IllegalStateException(e);
- } catch (ArrayIndexOutOfBoundsException e) {
- e.printStackTrace();
- throw new IllegalStateException(e);
}
}
+
+ public void addPrediction(Prediction p) {
+ // if (echo) System.out.println("Adding " + p);
+ for (int i = 0; i < instances.numInstances() - predictions.size() - 1;
i++)
+ predictions.add(null);
+ predictions.add(p);
+ }
+
+ public double getWindowSize() {
+ return instances.numInstances();
+ }
+
+ public double getAccuracy() {
+ if (predictions.isEmpty())
+ return 0.0;
+ double truePositive = 0.0;
+ double trueNegative = 0.0;
+ double falsePositive = 0.0;
+ double falseNegative = 0.0;
+ for (int i = 0; i < predictions.size(); i++) {
+ Prediction p = predictions.get(i);
+ if (p != null) {
+ truePositive += p.getTruePositive();
+ trueNegative += p.getTrueNegative();
+ falsePositive += p.getFalsePositive();
+ falseNegative += p.getFalseNegative();
+ }
+ }
+ return (trueNegative + truePositive) / (trueNegative + truePositive +
falseNegative + falsePositive);
+ }
+
+ private final int MAX_DECREASE = 20;
+ private double[] accuracies = new double[MAX_DECREASE];
+ private int currentDecrease = 0;
+
+ private boolean decreasingAcc(double accuracy) {
+ currentDecrease++;
+ if (currentDecrease > MAX_DECREASE) {
+ for (int i = 0; i < MAX_DECREASE - 1; i++) {
+ accuracies[i] = accuracies[i + 1];
+ }
+ accuracies[MAX_DECREASE - 1] = accuracy;
+ } else
+ accuracies[currentDecrease - 1] = accuracy;
+
+ double slope = calculateLeastSquaresSlope(accuracies);
+
+ return (slope < 0);
+ }
+
+ private double calculateLeastSquaresSlope(double[] accuracies) {
+ double n = accuracies.length;
+ double sumY = 0.0;
+ double sumX = 0.0;
+ double sumXY = 0.0;
+ double sumX2 = 0.0;
+ for (int i = 0; i < accuracies.length; i++) {
+ if (echo)
+ System.out.print(accuracies[i] + ", ");
+ if (accuracies[i] != -1) {
+ sumY += accuracies[i];
+ sumX += i;
+ sumXY += i * accuracies[i];
+ sumX2 += i * i;
+ }
+ }
+
+ double slope = ((n * sumXY) - (sumX * sumY)) / ((n * sumX2) - (sumX *
sumX));
+ double intercept = (sumY - (sumX * slope)) / n;
+ if (echo)
+ System.out.print("slope: " + slope + ", intercept: " + intercept);
+ if (echo)
+ System.out.println("");
+
+ return slope;
+ }
+
+ private boolean printed = false;
+
+ private void adjustWindow() {
+ if (cl == null)
+ return;
+ double windowSize = instances.numInstances();
+ double coverage = windowSize / cl.measureNumRules();
+ double accuracy = getAccuracy();
+ boolean decreasing = decreasingAcc(accuracy);
+ double l;
+ if ((coverage < config.getCdLowCoverage()) || (accuracy <
config.getCdAccuracy() && decreasing))
+ l = Math.round(0.2 * windowSize);
+ else if (coverage > 2 * config.getCdHighCoverage() && accuracy >
config.getCdAccuracy())
+ l = 2;
+ else if (coverage > config.getCdHighCoverage() && accuracy >
config.getCdAccuracy())
+ l = 1;
+ else
+ l = 0;
+
+ if (echo && !printed) {
+ System.out.println("L \t Accuracy \t Coverage \t Instances \t
Decreasing");
+ printed = true;
+ }
+
+ if (echo)
+ System.out.println(l + "\t" + accuracy + "\t" + coverage + "\t" +
windowSize + "\t" + decreasing);
+
+ for (int i = 0; i < l; i++) {
+ instances.delete(0);
+ if (!predictions.isEmpty())
+ predictions.remove(0);
+ }
+
+ // windowSize = windowSize - l;
+ // System.out.println(name + ", " + windowSize + ", l: " + l + ",
acc: " + accuracy + ", coverage: " + coverage);
+ }
public boolean isModelReady() {
- return modelReady;
+ return count > config.getMinimalLearnExamples();
}
- public Classifier createModel(String fileName, String attribute, String[]
rmAttributes) throws Exception {
- if (!modelReady)
- throw new IllegalStateException("Model didn't reach threshold for
creation!");
-
- DataSource source = new DataSource(new FileInputStream(arffFile));
- Instances data = source.getDataSet();
+ public long getNrExamples() {
+ return count;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Classifier createModel(String fileName, String attribute, String[]
rmAttributes) throws Exception {
+ // System.out.println("Creating model for " + player + name);
+ Instances data;
+ if (config.solveConceptDrift())
+ data = instances;
+ else {
+ DataSource source = new DataSource(path + player + name);
+ data = source.getDataSet();
+ }
if (rmAttributes.length > 0) {
String[] optionsDel = new String[2];
optionsDel[0] = "-R";
@@ -119,22 +258,20 @@
data.setClass(data.attribute(attribute));
// train M5P
- M5P cl = new M5P();
+ cl = new M5P();
cl.setBuildRegressionTree(true);
cl.setUnpruned(false);
cl.setUseUnsmoothed(false);
// further options...
cl.buildClassifier(data);
- // save model + header
- if (WekaOptions.isModelPersistency()) {
- File modelFile = new File(this.path, "/model/" + fileName + ".model");
- if (!modelFile.getParentFile().exists()) {
- modelFile.getParentFile().mkdirs();
- }
-
- SerializationHelper.write(new FileOutputStream(modelFile), cl);
- }
+ // System.out.println("Number of instances: " + data.numInstances());
+ // System.out.println("Number of measures: " + cl.measureNumRules());
+ // System.out.println(cl);
+
+ // save model + header
+ if (config.modelPersistency())
+ SerializationHelper.write(path + "../" + player + fileName + ".model",
cl);
return cl;
}
=======================================
--- /src/bots/mctsbot/ai/opponentmodels/weka/ARFFPlayer.java Thu May 27
13:49:11 2010
+++ /src/bots/mctsbot/ai/opponentmodels/weka/ARFFPlayer.java Tue Nov 23
08:42:27 2010
@@ -1,21 +1,20 @@
package bots.mctsbot.ai.opponentmodels.weka;
+import java.io.File;
import java.io.IOException;
+import java.net.URL;
import org.apache.log4j.Logger;
import weka.core.Instance;
-
-/**
- * This {@link ARFFPlayer} manages and writes ARFFFiles for each
player.<br />
- * After a certain treshold is reached (see {@link WekaOptions} a new
weka-model
- * is created with the data and the default model saved in a given
- * {@link WekaRegressionModel} replaced by the new data.
- */
+import bots.mctsbot.common.elements.player.PlayerId;
+
public class ARFFPlayer {
private final static Logger logger = Logger.getLogger(ARFFPlayer.class);
+ private final String folder
= "../../src/main/resources/org/cspoker/ai/opponentmodels/weka/models/arff/";
+
private final Object player;
private ARFFFile preCheckBetFile;
@@ -24,35 +23,49 @@
private ARFFFile postFoldCallRaiseFile;
private ARFFFile showdownFile;
- private boolean preCheckBetCreated = false;
- private boolean postCheckBetCreated = false;
- private boolean preFoldCallRaiseCreated = false;
- private boolean postFoldCallRaiseCreated = false;
- private boolean showdownCreated = false;
-
private boolean modelCreated = false;
private WekaRegressionModel model = null;
-
- public ARFFPlayer(Object player, WekaRegressionModel baseModel) {
- this.player = player;
-
- if (!modelCreated || (modelCreated &&
WekaOptions.isContinueAfterCreation())) {
- try {
- String path = "./data/mctsbot/";
- this.model = new WekaRegressionModel(baseModel);
-
- boolean overwrite = WekaOptions.isArffOverwrite();
- preCheckBetFile = new ARFFFile(path, player, "PreCheckBet.arff",
ARFFPropositionalizer.getPreCheckBetInstance().toString(), overwrite);
- postCheckBetFile = new ARFFFile(path, player, "PostCheckBet.arff",
ARFFPropositionalizer.getPostCheckBetInstance().toString(), overwrite);
- preFoldCallRaiseFile = new ARFFFile(path,
player, "PreFoldCallRaise.arff",
ARFFPropositionalizer.getPreFoldCallRaiseInstance().toString(),
- overwrite);
- postFoldCallRaiseFile = new ARFFFile(path,
player, "PostFoldCallRaise.arff",
ARFFPropositionalizer.getPostFoldCallRaiseInstance().toString(),
- overwrite);
- showdownFile = new ARFFFile(path, player, "Showdown.arff",
ARFFPropositionalizer.getShowdownInstance().toString(), overwrite);
- } catch (IOException io) {
- throw new RuntimeException(io);
- }
+ private WekaOptions config = new WekaOptions();
+ private ActionTrackingVisitor actions = null;
+
+ private long writeCounter = 0;
+
+ public ARFFPlayer(Object player, WekaRegressionModel baseModel,
WekaOptions config, ActionTrackingVisitor actions) {
+ if (!config.useOnlineLearning())
+ throw new IllegalStateException("ARFFPlayer can only be used with
online learning!");
+
+ this.player = player;
+ this.config = config;
+ this.model = baseModel;
+ this.actions = actions;
+
+ try {
+ // Begin new code -- can be better
+ URL codeSource =
getClass().getProtectionDomain().getCodeSource().getLocation();
+ File f = new File(codeSource.toURI());
+ while (!f.isDirectory()) {
+ f = f.getParentFile();
+ if (f == null) {
+ throw new IOException("Cannot find location for ARFFFiles");
+ }
+ }
+ String path = f.getAbsolutePath();
+ // End new code
+ // String path = (getClass().getProtectionDomain().getCodeSource()
+ // .getLocation().getPath() + folder).replace("%20", " ");
+ // End old code
+
+ preCheckBetFile = new ARFFFile(path, player, "PreCheckBet.arff",
ARFFPropositionalizer.getPreCheckBetInstance().toString(), config);
+ postCheckBetFile = new ARFFFile(path, player, "PostCheckBet.arff",
ARFFPropositionalizer.getPostCheckBetInstance().toString(), config);
+ preFoldCallRaiseFile = new ARFFFile(path,
player, "PreFoldCallRaise.arff",
ARFFPropositionalizer.getPreFoldCallRaiseInstance().toString(), config);
+ postFoldCallRaiseFile = new ARFFFile(path,
player, "PostFoldCallRaise.arff",
ARFFPropositionalizer.getPostFoldCallRaiseInstance().toString(),
+ config);
+ showdownFile = new ARFFFile(path, player, "Showdown.arff",
ARFFPropositionalizer.getShowdownInstance().toString(), config);
+ } catch (IOException io) {
+ throw new RuntimeException(io);
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to create set of instances");
}
}
@@ -65,105 +78,230 @@
showdownFile.close();
}
}
+
+ private String msgModelNotReady(ARFFFile file) {
+ return file.getName().substring(0, file.getName().indexOf(".")) + " is
not ready to be learned " + "(learning examples: " + file.getNrExamples()
+ + " < " + config.getMinimalLearnExamples() + " required)";
+ }
+
+ public double getAccuracy() {
+ return actions.getAccuracy((PlayerId) player);
+ }
+
+ public void learnNewModel() {
+ // if (!(preCheckBetFile.isModelReady() &&
postCheckBetFile.isModelReady() && preFoldCallRaiseFile.isModelReady()
+ // && postFoldCallRaiseFile.isModelReady() &&
showdownFile.isModelReady())) {
+ // System.out.println("\n MODEL NOT READY \n");
+ // return;
+ // }
+ System.out.println("");
+
logger.info("Learning new opponentModel for player " + player);
+ modelCreated = true;
+
+ // learning preCheckBetModel
+ if (preCheckBetFile.isModelReady())
+ learnPreCheckBet();
+ else
+
logger.info(msgModelNotReady(preCheckBetFile));
+ // learning postCheckBetModel
+ if (postCheckBetFile.isModelReady())
+ learnPostCheckBet();
+ else
+
logger.info(msgModelNotReady(postCheckBetFile));
+ // learning preFoldCallRaiseModel
+ if (preFoldCallRaiseFile.isModelReady())
+ learnPreFoldCallRaise();
+ else
+
logger.info(msgModelNotReady(preFoldCallRaiseFile));
+ // learning postFoldCallRaiseModel
+ if (postFoldCallRaiseFile.isModelReady())
+ learnPostFoldCallRaise();
+ else
+
logger.info(msgModelNotReady(postFoldCallRaiseFile));
+ // learning showdownModel
+ if (showdownFile.isModelReady())
+ learnShowdown();
+ else
+
logger.info(msgModelNotReady(showdownFile));
+
+ System.out.println("");
+ }
+
+ public boolean writeAllowed() {
+ return !modelCreated || (modelCreated && (config.continuousLearning() ||
config.continueAfterCreation()));
+ }
+
+ public boolean learningAllowed() {
+ return (modelCreated && config.continuousLearning()) || (!modelCreated
&& (writeCounter >= config.modelCreationTreshold()));
+ }
+
+ public boolean modelCreated() {
+ return modelCreated;
+ }
+
+ public void addPreCheckBetPrediction(Prediction p) {
+ preCheckBetFile.addPrediction(p);
+ }
public void writePreCheckBet(Instance instance) {
- if (preCheckBetCreated && !WekaOptions.isContinueAfterCreation())
- return;
- preCheckBetFile.write(instance);
- if (!preCheckBetCreated && preCheckBetFile.isModelReady()) {
- try {
-
logger.info("Learning preBetModel for player " + player);
- model.setPreBetModel(preCheckBetFile.createModel("preBet", "betProb",
new String[] { "action" }));
- preCheckBetCreated = true;
- } catch (Exception e) {
- e.printStackTrace();
+ if (writeAllowed()) {
+ preCheckBetFile.write(instance);
+ incrementWriteCounter();
+ if (learningAllowed()) {
+ if (modelCreated)
+ learnPreCheckBet();
+ else
+ learnNewModel();
}
}
}
+
+ public void learnPreCheckBet() {
+ try {
+ logger.trace("Learning preBetModel for player " + player);
+ model.setPreBetModel(preCheckBetFile.createModel("preBet", "betProb",
new String[] { "action" }));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void addPostCheckBetPrediction(Prediction p) {
+ postCheckBetFile.addPrediction(p);
+ }
public void writePostCheckBet(Instance instance) {
- if (postCheckBetCreated && !WekaOptions.isContinueAfterCreation())
- return;
- postCheckBetFile.write(instance);
- if (!postCheckBetCreated && postCheckBetFile.isModelReady()) {
- try {
-
logger.info("Learning postBetModel for player " + player);
-
model.setPostBetModel(postCheckBetFile.createModel("postBet", "betProb",
new String[] { "action" }));
- postCheckBetCreated = true;
- } catch (Exception e) {
- e.printStackTrace();
+ if (writeAllowed()) {
+ postCheckBetFile.write(instance);
+ incrementWriteCounter();
+ if (learningAllowed()) {
+ if (modelCreated)
+ learnPostCheckBet();
+ else
+ learnNewModel();
}
}
}
+
+ public void learnPostCheckBet() {
+ try {
+ logger.trace("Learning postBetModel for player " + player);
+
model.setPostBetModel(postCheckBetFile.createModel("postBet", "betProb",
new String[] { "action" }));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void addPreFoldCallRaisePrediction(Prediction p) {
+ preFoldCallRaiseFile.addPrediction(p);
+ }
public void writePreFoldCallRaise(Instance instance) {
- if (preFoldCallRaiseCreated && !WekaOptions.isContinueAfterCreation())
- return;
- preFoldCallRaiseFile.write(instance);
- if (!preFoldCallRaiseCreated && preFoldCallRaiseFile.isModelReady()) {
- try {
-
logger.info("Learning preFoldModel for player " + player);
-
model.setPreFoldModel(preFoldCallRaiseFile.createModel("preFold", "foldProb",
new String[] { "callProb", "raiseProb", "action" }));
-
logger.info("Learning preCallModel for player " + player);
-
model.setPreCallModel(preFoldCallRaiseFile.createModel("preCall", "callProb",
new String[] { "foldProb", "raiseProb", "action" }));
-
logger.info("Learning preRaiseModel for player " + player);
-
model.setPreRaiseModel(preFoldCallRaiseFile.createModel("preRaise", "raiseProb",
new String[] { "callProb", "foldProb", "action" }));
- preFoldCallRaiseCreated = true;
- } catch (Exception e) {
- e.printStackTrace();
+ if (writeAllowed()) {
+ preFoldCallRaiseFile.write(instance);
+ incrementWriteCounter();
+ if (learningAllowed()) {
+ if (modelCreated)
+ learnPreFoldCallRaise();
+ else
+ learnNewModel();
}
}
}
+
+ public void learnPreFoldCallRaise() {
+ try {
+ logger.trace("Learning preFoldModel for player " + player);
+
model.setPreFoldModel(preFoldCallRaiseFile.createModel("preFold", "foldProb",
new String[] { "callProb", "raiseProb", "action" }));
+ logger.trace("Learning preCallModel for player " + player);
+
model.setPreCallModel(preFoldCallRaiseFile.createModel("preCall", "callProb",
new String[] { "foldProb", "raiseProb", "action" }));
+ logger.trace("Learning preRaiseModel for player " + player);
+
model.setPreRaiseModel(preFoldCallRaiseFile.createModel("preRaise", "raiseProb",
new String[] { "callProb", "foldProb", "action" }));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void addPostFoldCallRaisePrediction(Prediction p) {
+ postFoldCallRaiseFile.addPrediction(p);
+ }
public void writePostFoldCallRaise(Instance instance) {
- if (postFoldCallRaiseCreated && !WekaOptions.isContinueAfterCreation())
- return;
- postFoldCallRaiseFile.write(instance);
- if (!postFoldCallRaiseCreated && postFoldCallRaiseFile.isModelReady()) {
- try {
-
logger.info("Learning postFoldModel for player " + player);
-
model.setPostFoldModel(postFoldCallRaiseFile.createModel("postFold", "foldProb",
new String[] { "callProb", "raiseProb", "action" }));
-
logger.info("Learning postCallModel for player " + player);
-
model.setPostCallModel(postFoldCallRaiseFile.createModel("postCall", "callProb",
new String[] { "foldProb", "raiseProb", "action" }));
-
logger.info("Learning postRaiseModel for player " + player);
-
model.setPostRaiseModel(postFoldCallRaiseFile.createModel("postRaise", "raiseProb",
new String[] { "callProb", "foldProb", "action" }));
- postFoldCallRaiseCreated = true;
- } catch (Exception e) {
- e.printStackTrace();
+ if (writeAllowed()) {
+ postFoldCallRaiseFile.write(instance);
+ incrementWriteCounter();
+ if (learningAllowed()) {
+ if (modelCreated)
+ learnPostFoldCallRaise();
+ else
+ learnNewModel();
}
}
}
+
+ public void learnPostFoldCallRaise() {
+ try {
+ logger.trace("Learning postFoldModel for player " + player);
+
model.setPostFoldModel(postFoldCallRaiseFile.createModel("postFold", "foldProb",
new String[] { "callProb", "raiseProb", "action" }));
+ logger.trace("Learning postCallModel for player " + player);
+
model.setPostCallModel(postFoldCallRaiseFile.createModel("postCall", "callProb",
new String[] { "foldProb", "raiseProb", "action" }));
+ logger.trace("Learning postRaiseModel for player " + player);
+
model.setPostRaiseModel(postFoldCallRaiseFile.createModel("postRaise", "raiseProb",
new String[] { "callProb", "foldProb", "action" }));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void addShowdownPrediction(Prediction p) {
+ showdownFile.addPrediction(p);
+ }
public void writeShowdown(Instance instance) {
- if (showdownCreated && !WekaOptions.isContinueAfterCreation())
- return;
- showdownFile.write(instance);
- if (!showdownCreated && showdownFile.isModelReady()) {
- try {
-
logger.info("Learning showdown0Model for player " + player);
-
model.setShowdown0Model(showdownFile.createModel("showdown0", "part0Prob",
new String[] { "part1Prob", "part2Prob", "part3Prob", "part4Prob",
- "part5Prob", "avgPartition" }));
-
logger.info("Learning showdown1Model for player " + player);
-
model.setShowdown1Model(showdownFile.createModel("showdown1", "part1Prob",
new String[] { "part0Prob", "part2Prob", "part3Prob", "part4Prob",
- "part5Prob", "avgPartition" }));
-
logger.info("Learning showdown2Model for player " + player);
-
model.setShowdown2Model(showdownFile.createModel("showdown5", "part2Prob",
new String[] { "part0Prob", "part1Prob", "part3Prob", "part4Prob",
- "part5Prob", "avgPartition" }));
-
logger.info("Learning showdown3Model for player " + player);
-
model.setShowdown3Model(showdownFile.createModel("showdown3", "part3Prob",
new String[] { "part0Prob", "part1Prob", "part2Prob", "part4Prob",
- "part5Prob", "avgPartition" }));
-
logger.info("Learning showdown4Model for player " + player);
-
model.setShowdown4Model(showdownFile.createModel("showdown4", "part4Prob",
new String[] { "part0Prob", "part1Prob", "part2Prob", "part3Prob",
- "part5Prob", "avgPartition" }));
-
logger.info("Learning showdown5Model for player " + player);
-
model.setShowdown5Model(showdownFile.createModel("showdown5", "part5Prob",
new String[] { "part0Prob", "part1Prob", "part2Prob", "part3Prob",
- "part4Prob", "avgPartition" }));
- // add it to pool
- //OpponentModelPool.getInstance().addModel(player, model);
- showdownCreated = true;
- } catch (Exception e) {
- e.printStackTrace();
+ if (writeAllowed()) {
+ showdownFile.write(instance);
+ incrementWriteCounter();
+ if (learningAllowed()) {
+ if (modelCreated)
+ learnShowdown();
+ else
+ learnNewModel();
}
}
}
-}
+
+ public void learnShowdown() {
+ try {
+ logger.trace("Learning showdown0Model for player " + player);
+
model.setShowdown0Model(showdownFile.createModel("showdown0", "part0Prob",
new String[] { "part1Prob", "part2Prob", "part3Prob", "part4Prob",
+ "part5Prob", "avgPartition" }));
+ logger.trace("Learning showdown1Model for player " + player);
+
model.setShowdown1Model(showdownFile.createModel("showdown1", "part1Prob",
new String[] { "part0Prob", "part2Prob", "part3Prob", "part4Prob",
+ "part5Prob", "avgPartition" }));
+ logger.trace("Learning showdown2Model for player " + player);
+
model.setShowdown2Model(showdownFile.createModel("showdown5", "part2Prob",
new String[] { "part0Prob", "part1Prob", "part3Prob", "part4Prob",
+ "part5Prob", "avgPartition" }));
+ logger.trace("Learning showdown3Model for player " + player);
+
model.setShowdown3Model(showdownFile.createModel("showdown3", "part3Prob",
new String[] { "part0Prob", "part1Prob", "part2Prob", "part4Prob",
+ "part5Prob", "avgPartition" }));
+ logger.trace("Learning showdown4Model for player " + player);
+
model.setShowdown4Model(showdownFile.createModel("showdown4", "part4Prob",
new String[] { "part0Prob", "part1Prob", "part2Prob", "part3Prob",
+ "part5Prob", "avgPartition" }));
+ logger.trace("Learning showdown5Model for player " + player);
+
model.setShowdown5Model(showdownFile.createModel("showdown5", "part5Prob",
new String[] { "part0Prob", "part1Prob", "part2Prob", "part3Prob",
+ "part4Prob", "avgPartition" }));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void incrementWriteCounter() {
+ writeCounter++;
+ String str = "";
+ str += preCheckBetFile.getAccuracy() + "\t" +
preCheckBetFile.getWindowSize() + "\t";
+ str += postCheckBetFile.getAccuracy() + "\t" +
postCheckBetFile.getWindowSize() + "\t";
+ str += preFoldCallRaiseFile.getAccuracy() + "\t" +
preFoldCallRaiseFile.getWindowSize() + "\t";
+ str += postFoldCallRaiseFile.getAccuracy() + "\t" +
postFoldCallRaiseFile.getWindowSize() + "\t";
+ // str += showdownFile.getAccuracy() + "\t" +
showdownFile.getWindowSize()
+ System.out.println(str);
+ // System.out.println("=" + writeCounter + "=");
+ }
+}
=======================================
--- /src/bots/mctsbot/ai/opponentmodels/weka/ARFFPropositionalizer.java Sun
Nov 7 06:35:47 2010
+++ /src/bots/mctsbot/ai/opponentmodels/weka/ARFFPropositionalizer.java Tue
Nov 23 08:42:27 2010
@@ -9,6 +9,7 @@
import bots.mctsbot.ai.opponentmodels.weka.instances.PreCheckBetInstances;
import
bots.mctsbot.ai.opponentmodels.weka.instances.PreFoldCallRaiseInstances;
import bots.mctsbot.ai.opponentmodels.weka.instances.ShowdownInstances;
+import bots.mctsbot.common.elements.player.PlayerId;
/**
* This ARFFPropositionalizer will be called on important GameEvents.
@@ -30,12 +31,15 @@
private final PostFoldCallRaiseInstances postFoldCallRaiseInstance;
private final ShowdownInstances showdownInstance;
- public ARFFPropositionalizer() throws IOException {
+ private final PlayerId bot;
+
+ public ARFFPropositionalizer(PlayerId bot) throws IOException {
this.preCheckBetInstance = getPreCheckBetInstance();
this.postCheckBetInstance = getPostCheckBetInstance();
this.preFoldCallRaiseInstance = getPreFoldCallRaiseInstance();
this.postFoldCallRaiseInstance = getPostFoldCallRaiseInstance();
this.showdownInstance = getShowdownInstance();
+ this.bot = bot;
}
public static PreCheckBetInstances getPreCheckBetInstance() {
@@ -62,7 +66,7 @@
+ "@attribute avgPartition {0,1,2,3,4,5}" + nl);
}
- private ARFFPlayer getARFF(Object actorId) {
+ public ARFFPlayer getARFF(Object actorId) {
if (arffFiles.containsKey(actorId))
return arffFiles.get(actorId);
else {
@@ -80,51 +84,113 @@
@Override
protected void logFold(Object actorId) {
+ if (actorId.equals(bot))
+ return;
if (getRound().equals("preflop")) {
getARFF(actorId).writePreFoldCallRaise(preFoldCallRaiseInstance.getClassifiedInstance(this,
actorId, new Object[] { 1, 0, 0, "fold" }));
} else {
getARFF(actorId).writePostFoldCallRaise(postFoldCallRaiseInstance.getClassifiedInstance(this,
actorId, new Object[] { 1, 0, 0, "fold" }));
}
}
+
+ protected void logFoldProb(Object actorId, Prediction p) {
+ if (actorId.equals(bot))
+ return;
+ if (getRound().equals("preflop")) {
+ getARFF(actorId).addPreFoldCallRaisePrediction(p);
+ } else {
+ getARFF(actorId).addPostFoldCallRaisePrediction(p);
+ }
+ }
@Override
protected void logCall(Object actorId) {
+ if (actorId.equals(bot))
+ return;
if (getRound().equals("preflop")) {
getARFF(actorId).writePreFoldCallRaise(preFoldCallRaiseInstance.getClassifiedInstance(this,
actorId, new Object[] { 0, 1, 0, "call" }));
} else {
getARFF(actorId).writePostFoldCallRaise(postFoldCallRaiseInstance.getClassifiedInstance(this,
actorId, new Object[] { 0, 1, 0, "call" }));
}
}
+
+ protected void logCallProb(Object actorId, Prediction p) {
+ if (actorId.equals(bot))
+ return;
+ if (getRound().equals("preflop")) {
+ getARFF(actorId).addPreFoldCallRaisePrediction(p);
+ } else {
+ getARFF(actorId).addPostFoldCallRaisePrediction(p);
+ }
+ }
@Override
protected void logRaise(Object actorId, double raiseAmount) {
+ if (actorId.equals(bot))
+ return;
if (getRound().equals("preflop")) {
getARFF(actorId).writePreFoldCallRaise(preFoldCallRaiseInstance.getClassifiedInstance(this,
actorId, new Object[] { 0, 0, 1, "raise" }));
} else {
getARFF(actorId).writePostFoldCallRaise(postFoldCallRaiseInstance.getClassifiedInstance(this,
actorId, new Object[] { 0, 0, 1, "raise" }));
}
}
+
+ protected void logRaiseProb(Object actorId, Prediction p) {
+ if (actorId.equals(bot))
+ return;
+ if (getRound().equals("preflop")) {
+ getARFF(actorId).addPreFoldCallRaisePrediction(p);
+ } else {
+ getARFF(actorId).addPostFoldCallRaisePrediction(p);
+ }
+ }
@Override
protected void logCheck(Object actorId) {
+ if (actorId.equals(bot))
+ return;
if (getRound().equals("preflop")) {
getARFF(actorId).writePreCheckBet(preCheckBetInstance.getClassifiedInstance(this,
actorId, new Object[] { 0, "check" }));
} else {
getARFF(actorId).writePostCheckBet(postCheckBetInstance.getClassifiedInstance(this,
actorId, new Object[] { 0, "check" }));
}
}
+
+ protected void logCheckProb(Object actorId, Prediction p) {
+ if (actorId.equals(bot))
+ return;
+ if (getRound().equals("preflop")) {
+ getARFF(actorId).addPreCheckBetPrediction(p);
+ } else {
+ getARFF(actorId).addPostCheckBetPrediction(p);
+ }
+ }
@Override
protected void logBet(Object actorId, double raiseAmount) {
+ if (actorId.equals(bot))
+ return;
if (getRound().equals("preflop")) {
getARFF(actorId).writePreCheckBet(preCheckBetInstance.getClassifiedInstance(this,
actorId, new Object[] { 1, "bet" }));
} else {
getARFF(actorId).writePostCheckBet(postCheckBetInstance.getClassifiedInstance(this,
actorId, new Object[] { 1, "bet" }));
}
}
+
+ protected void logBetProb(Object actorId, Prediction p) {
+ if (actorId.equals(bot))
+ return;
+ if (getRound().equals("preflop")) {
+ getARFF(actorId).addPreCheckBetPrediction(p);
+ } else {
+ getARFF(actorId).addPostCheckBetPrediction(p);
+ }
+ }
@Override
protected void logShowdown(Object actorId, double[] partitionDistr) {
+ if (actorId.equals(bot))
+ return;
Object[] targets = new Object[partitionDistr.length + 1];
double avgBucket = 0;
for (int i = 0; i < partitionDistr.length; i++) {
@@ -134,4 +200,10 @@
targets[partitionDistr.length] = (int) Math.round(avgBucket);
getARFF(actorId).writeShowdown(showdownInstance.getClassifiedInstance(this,
actorId, targets));
}
-}
+
+ protected void logShowdownProb(Object actorId, Prediction p) {
+ if (actorId.equals(bot))
+ return;
+ getARFF(actorId).addShowdownPrediction(p);
+ }
+}
=======================================
--- /src/bots/mctsbot/ai/opponentmodels/weka/ActionTrackingVisitor.java Sun
Nov 7 06:35:47 2010
+++ /src/bots/mctsbot/ai/opponentmodels/weka/ActionTrackingVisitor.java Tue
Nov 23 08:42:27 2010
@@ -1,50 +1,55 @@
package bots.mctsbot.ai.opponentmodels.weka;
import java.io.IOException;
+import java.util.HashMap;
import org.apache.log4j.Logger;
-import bots.mctsbot.client.common.gamestate.DetailedHoldemTableState;
+import weka.classifiers.evaluation.Prediction;
+import bots.mctsbot.ai.bots.bot.gametree.action.BetAction;
+import bots.mctsbot.ai.bots.bot.gametree.action.CallAction;
+import bots.mctsbot.ai.bots.bot.gametree.action.CheckAction;
+import bots.mctsbot.ai.bots.bot.gametree.action.FoldAction;
+import bots.mctsbot.ai.bots.bot.gametree.action.RaiseAction;
+import bots.mctsbot.ai.bots.bot.gametree.action.SearchBotAction;
+import bots.mctsbot.ai.bots.bot.gametree.mcts.MCTSBot;
+import bots.mctsbot.ai.bots.bot.gametree.mcts.nodes.INode;
+import bots.mctsbot.ai.bots.bot.gametree.mcts.nodes.InnerNode;
+import bots.mctsbot.ai.opponentmodels.OpponentModel;
+import bots.mctsbot.client.common.gamestate.GameState;
import bots.mctsbot.client.common.gamestate.modifiers.AllInState;
import bots.mctsbot.client.common.gamestate.modifiers.BetState;
-import bots.mctsbot.client.common.gamestate.modifiers.BlindState;
import bots.mctsbot.client.common.gamestate.modifiers.CallState;
import bots.mctsbot.client.common.gamestate.modifiers.CheckState;
-import bots.mctsbot.client.common.gamestate.modifiers.ConfigChangeState;
import bots.mctsbot.client.common.gamestate.modifiers.FoldState;
-import bots.mctsbot.client.common.gamestate.modifiers.JoinTableState;
-import bots.mctsbot.client.common.gamestate.modifiers.LeaveTableState;
-import
bots.mctsbot.client.common.gamestate.modifiers.NewCommunityCardsState;
-import bots.mctsbot.client.common.gamestate.modifiers.NewDealState;
-import bots.mctsbot.client.common.gamestate.modifiers.NewPocketCardsState;
-import bots.mctsbot.client.common.gamestate.modifiers.NewRoundState;
-import bots.mctsbot.client.common.gamestate.modifiers.NextPlayerState;
import bots.mctsbot.client.common.gamestate.modifiers.RaiseState;
-import bots.mctsbot.client.common.gamestate.modifiers.ShowHandState;
-import bots.mctsbot.client.common.gamestate.modifiers.SitInState;
-import bots.mctsbot.client.common.gamestate.modifiers.SitOutState;
-import bots.mctsbot.client.common.gamestate.modifiers.WinnerState;
-import bots.mctsbot.client.common.playerstate.PlayerState;
-import bots.mctsbot.common.elements.table.Round;
-
-import com.biotools.meerkat.Hand;
+import bots.mctsbot.common.elements.player.PlayerId;
+import bots.mctsbot.common.util.Util;
+
+import com.google.common.collect.ImmutableList;
/**
* The ActionTrackingVisitor currently is used to observe the game
* and delegate important states to an {@link ARFFPropositionalizer}<br>
- * <br>
- * TODO: this classes extend {@link PlayerTrackingVisitor} though I think
it doesn't
- * really uses much of its functions (anymore). We should directly
- * implement GameVisitor ?
- *
*/
public class ActionTrackingVisitor extends PlayerTrackingVisitor {
- private final static Logger logger =
Logger.getLogger(ActionTrackingVisitor.class);
-
- public ActionTrackingVisitor() {
+ private final static Logger logger =
Logger.getLogger(ARFFPropositionalizer.class);
+
+ private class AccuracyData {
+ double truePositive = 0.0;
+ double trueNegative = 0.0;
+ double falsePositive = 0.0;
+ double falseNegative = 0.0;
+ }
+
+ private HashMap<PlayerId, AccuracyData> accuracyData;
+
+ public ActionTrackingVisitor(OpponentModel opponentModel, PlayerId bot) {
+ super(opponentModel);
try {
- this.propz = new ARFFPropositionalizer();
+ this.propz = new ARFFPropositionalizer(bot);
+ accuracyData = new HashMap<PlayerId, AccuracyData>();
} catch (IOException e) {
e.printStackTrace();
}
@@ -54,128 +59,261 @@
return (ARFFPropositionalizer) this.propz;
}
- @Override
- public void visitAllInState(AllInState allInState) {
- logger.trace("(" +
allInState.getPlayer(allInState.getNextToAct()).getName() + ")
AllInState: " + allInState.getRound());
- propz.signalAllIn(allInState.getEvent().getPlayerId(),
allInState.getEvent().getMovedAmount());
+ private InnerNode getNode(GameState state) {
+ try {
+ return (InnerNode) parentOpponentModel.getChosenNode();
+ } catch (ClassCastException e) {
+ return null;
+ }
}
- @Override
- public void visitBetState(BetState betState) {
- logger.trace("(" + betState.getPlayer(betState.getNextToAct()).getName()
+ ") BetState: " + betState.getEvent().getAmount());
- propz.signalBet(false, betState.getEvent().getPlayerId(),
betState.getEvent().getAmount());
+ public void printAccuracy() {
+ for (PlayerId id : accuracyData.keySet()) {
+ AccuracyData data = accuracyData.get(id);
+ System.out.print(id + "\t" + //" Accuracy : " +
+ (data.trueNegative + data.truePositive) / (data.trueNegative +
data.truePositive + data.falseNegative + data.falsePositive));
+ System.out.print("\t");
+ }
+ System.out.println("");
}
- @Override
- public void visitCallState(CallState callState) {
- logger.trace("(" +
callState.getPlayer(callState.getNextToAct()).getName() + ") CallState");
- propz.signalCall(false, callState.getEvent().getPlayerId());
+ private Prediction getProbability(GameState gameState) {
+ return getProbability(gameState, 0);
}
- @Override
- public void visitCheckState(CheckState checkState) {
- logger.trace("(" +
checkState.getPlayer(checkState.getNextToAct()).getName() + ") CheckState");
- propz.signalCheck(checkState.getEvent().getPlayerId());
- }
-
- @Override
- public void visitFoldState(FoldState foldState) {
- logger.trace("(" +
foldState.getPlayer(foldState.getNextToAct()).getName() + ") FoldState");
- propz.signalFold(foldState.getEvent().getPlayerId());
- }
-
- @Override
- public void visitInitialGameState(DetailedHoldemTableState
initialGameState) {
-
- }
-
- @Override
- public void visitJoinTableState(JoinTableState joinTableState) {
-
- }
-
- @Override
- public void visitLeaveTableState(LeaveTableState leaveTableState) {
-
+ /**
+ * To calculate the accuracy of the opponentmodel we need the
probabilities
+ * of considered actions of opponents when the {@link MCTSBot} calculates
+ * the best action for him to take. For this we use the {@link INode} that
+ * contains the action made by the bot. If it is an {@link InnerNode} the
+ * children contain the probabilities of actions the opponent could make.
+ * Probalities of raises are grouped to give a probability for the action
+ * Raise. To consider consecutive actions by opponents we adjust the
+ * {@link INode} to become the correct child, which is the actual action
+ * made by the opponent. In case of a raise, the raise amongst the
children
+ * nearest to the actual one is chosen.
+ * The probabilities are returned as a {@link Prediction}.
+ *
+ * @param gameState
+ * the {@link GameState} for which we want to calculate the
+ * probability
+ * @param raiseAmount
+ * the bet/raise amount, otherwise 0
+ * @return a {@link Prediction} of the considered action.
+ *
+ * <br>
+ * <br>
+ * TODO: grouping probalities of raises could be improved.
+ */
+ private Prediction getProbability(GameState gameState, double
raiseAmount) {
+ // This method should only be called after MCTSBot has acted
+ if (parentOpponentModel.getChosenNode() == null)
+ return null;
+
+ HashMap<Class<?>, SearchBotAction> actions = new HashMap<Class<?>,
SearchBotAction>();
+ HashMap<Class<?>, Double> probs = new HashMap<Class<?>, Double>();
+ Class<?> cProb = null;
+ RaiseAction raiseAction = null;
+ BetAction betAction = null;
+ String errorStr = "";
+ InnerNode node = getNode(gameState);
+ if (node != null) {
+ errorStr = (">-----------------------------");
+ errorStr += ("\n" + getPlayerName(gameState) + " State " +
gameState.getClass());
+ ImmutableList<INode> children = node.getChildren();
+ if (children != null) {
+ for (INode n : children) {
+ Class<?> c = n.getLastAction().getAction().getClass();
+ // Same actions are grouped to make one probability (bet/raise)
+ if (!probs.containsKey(c))
+ probs.put(c, n.getLastAction().getProbability());
+ else
+ probs.put(c, n.getLastAction().getProbability() + probs.get(c));
+ actions.put(c, n.getLastAction().getAction());
+
+ if
(gameState.getClass().equals(n.getLastAction().getAction().getUnwrappedStateAfterAction().getClass())
||
+ // TODO: you shouldn't get BetAction in RaiseState (but it does
happen somehow...)
+ (gameState.getClass().equals(RaiseState.class) &&
n.getLastAction().getAction().getClass().equals(BetAction.class))) {// ||
+ // // TODO: idem with Raise-/BetAction in AllinState (now this
situation is ignored)
+ // (gameState.getClass().equals(AllInState.class) &&
+ //
n.getLastAction().getAction().getClass().equals(BetAction.class))) {
+ if (cProb == null) {
+ errorStr += "\n Setting chosen node with action " +
n.getLastAction().getAction();
+ parentOpponentModel.setChosenNode(n);
+ }
+ cProb = c;
+ if (raiseAction == null && c.equals(RaiseAction.class))
+ raiseAction = (RaiseAction) n.getLastAction().getAction();
+ else if (betAction == null && c.equals(BetAction.class))
+ betAction = (BetAction) n.getLastAction().getAction();
+ }
+
+ // Correct child node is chosen for bet/raise
+ if (cProb != null) {
+ if (raiseAction != null && c.equals(RaiseAction.class)) {
+ RaiseAction newRaiseAction = (RaiseAction)
n.getLastAction().getAction();
+ if (Math.abs(newRaiseAction.amount - raiseAmount) <
Math.abs(raiseAction.amount - raiseAmount)) {
+ raiseAction = newRaiseAction;
+ errorStr += "\n Setting chosen node with action " +
n.getLastAction().getAction();
+ parentOpponentModel.setChosenNode(n);
+ }
+ } else if (betAction != null && c.equals(BetAction.class)) {
+ BetAction newBetAction = (BetAction) n.getLastAction().getAction();
+ if (Math.abs(newBetAction.amount - raiseAmount) <
Math.abs(betAction.amount - raiseAmount)) {
+ betAction = newBetAction;
+ errorStr += "\n Setting chosen node with action " +
n.getLastAction().getAction();
+ parentOpponentModel.setChosenNode(n);
+ }
+ }
+ }
+ errorStr += ("\nState " +
n.getLastAction().getAction().getUnwrappedStateAfterAction().getClass() + "
with action "
+ + n.getLastAction().getAction() + "\t with probability " + (double)
Math.round(n.getLastAction().getProbability() * 10000) / 100
+ + "% and totalProb " + (double) Math.round(probs.get(c) * 10000) /
100 + "%");
+ }
+ errorStr += ("\n> Chosen child with action " +
parentOpponentModel.getChosenNode().getLastAction().getAction());
+ } else {
+ errorStr += ("\nNo children for node with action " +
node.getLastAction().getAction());
+ }
+ errorStr += ("\n-----------------------------<");
+ }
+
+ // chosen node of opponentmodel should have changed
+ SearchBotAction action =
parentOpponentModel.getChosenNode().getLastAction().getAction();
+ if (parentOpponentModel.getChosenNode() == node || cProb == null) {
+ // System.err.println(str);
+ return null;
+ }
+
+ // System.out.println(">----------------------------");
+ // for (Class<?> c : probs.keySet()) {
+ // if (c.equals(cProb))
+ // assimilatePrediction(new Prediction(action, 1, probs.get(cProb)));
+ // else
+ // assimilatePrediction(new Prediction(actions.get(c), 0,
probs.get(c)));
+ // }
+ // System.out.println("-----------------------------<");
+
+ return new Prediction(action, 1, probs.get(cProb));
}
- @Override
- public void visitNewCommunityCardsState(NewCommunityCardsState
newCommunityCardsState) {
- logger.trace("NewCommunityCardsState: " +
newCommunityCardsState.getRound() + " ");
-
- logger.trace(" " + newCommunityCardsState.getCommunityCards());
- propz.signalCommunityCards(newCommunityCardsState.getCommunityCards());
+ private void assimilatePrediction(PlayerId id, Prediction p) {
+ if (p == null || p.getAction() == null)
+ return;
+ // System.out.println(p + ", TP: " + p.getTruePositive() + ", TN: " +
p.getTrueNegative()
+ // + ", FP: " + p.getFalsePositive() + ", FN: " +
p.getFalseNegative());
+ if (!accuracyData.containsKey(id))
+ accuracyData.put(id, new AccuracyData());
+
+ AccuracyData data = accuracyData.get(id);
+ data.truePositive += p.getTruePositive();
+ data.trueNegative += p.getTrueNegative();
+ data.falsePositive += p.getFalsePositive();
+ data.falseNegative += p.getFalseNegative();
+ // printAccuracy();
}
- @Override
- public void visitNewDealState(NewDealState newDealState) {
- logger.trace("(" +
newDealState.getPlayer(newDealState.getDealer()).getName() + ")
NewDealState");
- propz.signalBBAmount(newDealState.getTableConfiguration().getBigBlind());
- propz.signalNewGame();
- for (PlayerState player : newDealState.getAllSeatedPlayers()) {
- propz.signalSeatedPlayer(player.getStack(), player.getPlayerId());
- }
+ public double getAccuracy(PlayerId id) {
+ AccuracyData data = accuracyData.get(id);
+ if (data == null)
+ return 0.0;
+ else
+ return (data.trueNegative + data.truePositive) / (data.trueNegative +
data.truePositive + data.falseNegative + data.falsePositive);
}
@Override
- public void visitNewPocketCardsState(NewPocketCardsState
newPocketCardsState) {
-
- }
-
- @Override
- public void visitNewRoundState(NewRoundState newRoundState) {
- logger.trace("NewRoundState: " + newRoundState.getRound());
- if (newRoundState.getRound() == Round.FLOP) {
- propz.signalFlop();
- } else if (newRoundState.getRound() == Round.TURN) {
- propz.signalTurn();
- } else if (newRoundState.getRound() == Round.FINAL) {
- propz.signalRiver();
- }
- }
-
- @Override
- public void visitNextPlayerState(NextPlayerState nextPlayerState) {
-
+ public void visitCallState(CallState callState) {
+ InnerNode node = getNode(callState);
+ if (node != null
&& !callState.getNextToAct().equals(parentOpponentModel.getBotId())) {
+ Prediction p = getProbability(callState);
+ assimilatePrediction(callState.getNextToAct(), p);
+ getPropz().logCallProb(callState.getNextToAct(), p);
+ logger.trace(getPlayerName(callState) + " " + p);
+ } else {
+ logger.trace(getPlayerName(callState) + " CallState");
+ }
+ propz.signalCall(false, callState.getEvent().getPlayerId());
}
@Override
public void visitRaiseState(RaiseState raiseState) {
- logger.trace("(" +
raiseState.getPlayer(raiseState.getNextToAct()).getName() + ")
RaiseState: " + raiseState.getLargestBet());
+ InnerNode node = getNode(raiseState);
+ if (node != null
&& !raiseState.getNextToAct().equals(parentOpponentModel.getBotId())) {
+ Prediction p = getProbability(raiseState, raiseState.getLargestBet());
+ assimilatePrediction(raiseState.getNextToAct(), p);
+ getPropz().logRaiseProb(raiseState.getNextToAct(), p);
+ logger.trace(getPlayerName(raiseState) + " Raise " +
Util.parseDollars(raiseState.getLargestBet()) + " - with <" + p + ">");
+ } else {
+ logger.trace(getPlayerName(raiseState) + " RaiseState: " +
Util.parseDollars(raiseState.getLargestBet()));
+ }
propz.signalRaise(false, raiseState.getLastEvent().getPlayerId(),
raiseState.getLargestBet());
}
@Override
- public void visitShowHandState(ShowHandState showHandState) {
- Hand cardset =
showHandState.getLastEvent().getShowdownPlayer().getHandCards();
- logger.trace("(" +
showHandState.getPlayer(showHandState.getLastEvent().getShowdownPlayer().getPlayerId()).getName()
+ ") ShowHandState: "
- + cardset.getFirstCard() + ", " + cardset.getSecondCard());
-
propz.signalCardShowdown(showHandState.getLastEvent().getShowdownPlayer().getPlayerId(),
cardset.getFirstCard(), cardset.getSecondCard());
+ public void visitFoldState(FoldState foldState) {
+ InnerNode node = getNode(foldState);
+ if (node != null
&& !foldState.getNextToAct().equals(parentOpponentModel.getBotId())) {
+ Prediction p = getProbability(foldState);
+ assimilatePrediction(foldState.getNextToAct(), p);
+ getPropz().logFoldProb(foldState.getNextToAct(), p);
+ logger.trace(getPlayerName(foldState) + " " + p);
+ } else {
+ logger.trace(getPlayerName(foldState) + " FoldState");
+ }
+ propz.signalFold(foldState.getEvent().getPlayerId());
}
@Override
- public void visitSitInState(SitInState sitInState) {
-
+ public void visitCheckState(CheckState checkState) {
+ InnerNode node = getNode(checkState);
+ if (node != null
&& !checkState.getNextToAct().equals(parentOpponentModel.getBotId())) {
+ Prediction p = getProbability(checkState);
+ assimilatePrediction(checkState.getNextToAct(), p);
+ getPropz().logCheckProb(checkState.getNextToAct(), p);
+ logger.trace(getPlayerName(checkState) + " " + p);
+ } else {
+ logger.trace(getPlayerName(checkState) + " CheckState");
+ }
+ propz.signalCheck(checkState.getEvent().getPlayerId());
}
@Override
- public void visitSitOutState(SitOutState sitOutState) {
-
+ public void visitBetState(BetState betState) {
+ InnerNode node = getNode(betState);
+ if (node != null
&& !betState.getNextToAct().equals(parentOpponentModel.getBotId())) {
+ Prediction p = getProbability(betState,
betState.getEvent().getAmount());
+ assimilatePrediction(betState.getNextToAct(), p);
+ getPropz().logBetProb(betState.getNextToAct(), p);
+ logger.trace(getPlayerName(betState) + " Bet " +
Util.parseDollars(betState.getEvent().getAmount()) + " - with <" + p + ">");
+ } else {
+ logger.trace(getPlayerName(betState) + " BetState: " +
Util.parseDollars(betState.getEvent().getAmount()));
+ }
+ propz.signalBet(false, betState.getEvent().getPlayerId(),
betState.getEvent().getAmount());
}
@Override
- public void visitBlindState(BlindState blindState) {
- logger.trace("(" +
blindState.getPlayer(blindState.getLastEvent().getPlayerId()).getName()
+ ") BlindState: " + blindState.getRound());
- propz.signalBlind(false, blindState.getLastEvent().getPlayerId(),
blindState.getLastEvent().getAmount());
- }
-
- @Override
- public void visitWinnerState(WinnerState winnerState) {
- logger.trace("(" + winnerState.getLastEvent().getWinners().toArray()[0]
+ ") WinnerState: " + winnerState.getRound());
- }
-
- @Override
- public void visitConfigChangeState(ConfigChangeState configChangeState) {
-
propz.signalBBAmount(configChangeState.getLastEvent().getTableConfig().getBigBlind());
+ public void visitAllInState(AllInState allInState) {
+ InnerNode node = getNode(allInState);
+ if (node != null
&& !allInState.getNextToAct().equals(parentOpponentModel.getBotId())) {
+ Prediction p = getProbability(allInState,
allInState.getEvent().getMovedAmount());
+ assimilatePrediction(allInState.getNextToAct(), p);
+
+ if (p != null) {
+ if (p.getAction() instanceof CallAction)
+ getPropz().logCallProb(allInState.getNextToAct(), p);
+ if (p.getAction() instanceof FoldAction)
+ getPropz().logFoldProb(allInState.getNextToAct(), p);
+ if (p.getAction() instanceof RaiseAction)
+ getPropz().logRaiseProb(allInState.getNextToAct(), p);
+ if (p.getAction() instanceof CheckAction)
+ getPropz().logCheckProb(allInState.getNextToAct(), p);
+ if (p.getAction() instanceof BetAction)
+ getPropz().logBetProb(allInState.getNextToAct(), p);
+ }
+
+ logger.trace(getPlayerName(allInState) + " All-in " +
Util.parseDollars(allInState.getEvent().getMovedAmount()) + " - with <" + p
+ ">");
+ } else {
+ logger.trace(getPlayerName(allInState) + " AllInState");
+ }
+ propz.signalAllIn(allInState.getEvent().getPlayerId(),
allInState.getEvent().getMovedAmount());
}
}
=======================================
--- /src/bots/mctsbot/ai/opponentmodels/weka/PlayerTrackingVisitor.java Sun
Nov 7 06:35:47 2010
+++ /src/bots/mctsbot/ai/opponentmodels/weka/PlayerTrackingVisitor.java Tue
Nov 23 08:42:27 2010
@@ -17,6 +17,7 @@
import org.apache.log4j.Logger;
+import bots.mctsbot.ai.opponentmodels.OpponentModel;
import bots.mctsbot.client.common.gamestate.DetailedHoldemTableState;
import bots.mctsbot.client.common.gamestate.GameState;
import bots.mctsbot.client.common.gamestate.GameStateVisitor;
@@ -42,6 +43,8 @@
import bots.mctsbot.client.common.playerstate.PlayerState;
import bots.mctsbot.common.elements.table.Round;
+import com.biotools.meerkat.Card;
+
public class PlayerTrackingVisitor implements GameStateVisitor, Cloneable {
private final static Logger logger =
Logger.getLogger(PlayerTrackingVisitor.class);
@@ -49,6 +52,16 @@
private GameState previousStartState;
protected Propositionalizer propz = new Propositionalizer();
+
+ protected OpponentModel parentOpponentModel;
+
+ public PlayerTrackingVisitor(OpponentModel opponentModel) {
+ this.parentOpponentModel = opponentModel;
+ }
+
+ protected OpponentModel getOpponentModel() {
+ return this.parentOpponentModel;
+ }
public void readHistory(GameState gameState) {
try {
@@ -79,31 +92,46 @@
public Propositionalizer getPropz() {
return propz;
}
+
+ protected String getPlayerName(GameState gameState) {
+ return gameState.getRound() + " - (" +
gameState.getPlayer(gameState.getNextToAct()).getName() + ")";
+ }
@Override
public void visitAllInState(AllInState allInState) {
+ logger.trace("(" +
allInState.getPlayer(allInState.getNextToAct()).getName() + ")
AllInState: " + allInState.getRound());
propz.signalAllIn(allInState.getEvent().getPlayerId(),
allInState.getEvent().getMovedAmount());
}
@Override
public void visitBetState(BetState betState) {
+ logger.trace("(" + betState.getPlayer(betState.getNextToAct()).getName()
+ ") BetState: " + betState.getEvent().getAmount());
propz.signalBet(false, betState.getEvent().getPlayerId(),
betState.getEvent().getAmount());
}
@Override
public void visitCallState(CallState callState) {
+ logger.trace("(" +
callState.getPlayer(callState.getNextToAct()).getName() + ") CallState");
propz.signalCall(false, callState.getEvent().getPlayerId());
}
@Override
public void visitCheckState(CheckState checkState) {
+ logger.trace("(" +
checkState.getPlayer(checkState.getNextToAct()).getName() + ") CheckState");
propz.signalCheck(checkState.getEvent().getPlayerId());
}
@Override
public void visitFoldState(FoldState foldState) {
+ logger.trace("(" +
foldState.getPlayer(foldState.getNextToAct()).getName() + ") FoldState");
propz.signalFold(foldState.getEvent().getPlayerId());
}
+
+ @Override
+ public void visitRaiseState(RaiseState raiseState) {
+ logger.trace("(" +
raiseState.getPlayer(raiseState.getNextToAct()).getName() + ")
RaiseState: " + raiseState.getLargestBet());
+ propz.signalRaise(false, raiseState.getLastEvent().getPlayerId(),
raiseState.getLargestBet());
+ }
@Override
public void visitInitialGameState(DetailedHoldemTableState
initialGameState) {
@@ -122,11 +150,14 @@
@Override
public void visitNewCommunityCardsState(NewCommunityCardsState
newCommunityCardsState) {
-
+ logger.trace("NewCommunityCardsState: " +
newCommunityCardsState.getRound() + " ");
+ logger.trace(" " + newCommunityCardsState.getCommunityCards());
+ propz.signalCommunityCards(newCommunityCardsState.getCommunityCards());
}
@Override
public void visitNewDealState(NewDealState newDealState) {
+ logger.trace("(" +
newDealState.getPlayer(newDealState.getDealer()).getName() + ")
NewDealState");
propz.signalBBAmount(newDealState.getTableConfiguration().getBigBlind());
propz.signalNewGame();
for (PlayerState player : newDealState.getAllSeatedPlayers()) {
@@ -136,11 +167,14 @@
@Override
public void visitNewPocketCardsState(NewPocketCardsState
newPocketCardsState) {
-
+ // System.out.println("--------------------");
+ // System.out.print("(" + newPocketCardsState.getPlayer().getName()
+ ") Pocket cards: ");
+ newPocketCardsState.getPlayerCards();
}
@Override
public void visitNewRoundState(NewRoundState newRoundState) {
+ logger.trace("NewRoundState: " + newRoundState.getRound());
if (newRoundState.getRound() == Round.FLOP) {
propz.signalFlop();
} else if (newRoundState.getRound() == Round.TURN) {
@@ -154,14 +188,14 @@
public void visitNextPlayerState(NextPlayerState nextPlayerState) {
}
-
- @Override
- public void visitRaiseState(RaiseState raiseState) {
- propz.signalRaise(false, raiseState.getLastEvent().getPlayerId(),
raiseState.getLargestBet());
- }
@Override
public void visitShowHandState(ShowHandState showHandState) {
+ Card[] cardset = new Card[] {};
+ cardset =
showHandState.getLastEvent().getShowdownPlayer().getHandCards().toArray(cardset);
+ logger.trace("(" +
showHandState.getPlayer(showHandState.getLastEvent().getShowdownPlayer().getPlayerId()).getName()
+ ") ShowHandState: " + cardset[0]
+ + ", " + cardset[1]);
+
propz.signalCardShowdown(showHandState.getLastEvent().getShowdownPlayer().getPlayerId(),
cardset[0], cardset[1]);
}
@Override
@@ -176,11 +210,13 @@
@Override
public void visitBlindState(BlindState blindState) {
+ logger.trace("(" +
blindState.getPlayer(blindState.getLastEvent().getPlayerId()).getName()
+ ") BlindState: " + blindState.getRound());
propz.signalBlind(false, blindState.getLastEvent().getPlayerId(),
blindState.getLastEvent().getAmount());
}
@Override
public void visitWinnerState(WinnerState winnerState) {
+ logger.trace("(" + winnerState.getLastEvent() + ") WinnerState: " +
winnerState.getRound());
}
@Override
=======================================
--- /src/bots/mctsbot/ai/opponentmodels/weka/WekaOptions.java Sun Nov 7
06:35:47 2010
+++ /src/bots/mctsbot/ai/opponentmodels/weka/WekaOptions.java Tue Nov 23
08:42:27 2010
@@ -1,50 +1,128 @@
package bots.mctsbot.ai.opponentmodels.weka;
public class WekaOptions {
-
- private static boolean arffPersistency = true;
- private static boolean arffOverwrite = true;
- private static long modelCreationTreshold = 500;
- private static boolean continueAfterCreation = false;
- private static boolean modelPersistency = true;
-
- public static boolean isArffPersistency() {
- return arffPersistency;
+
+ private boolean useOnlineLearning = true;
+ /** Continuous learning will start after threshold */
+ private boolean continuousLearning = true;
+
+ /** if continuousLearning is false, a new model will be learned
+ * after X actions by an opponent, where X is modelCreationTreshold */
+ private long modelCreationTreshold = 500;
+ private long minimalLearnExamples = 1;
+
+ /** continuousLearning must be true for using solveConceptDrift */
+ private boolean solveConceptDrift = true;
+ private double cdHighCoverage = 50;
+ private double cdLowCoverage = 1;
+ private double cdAccuracy = 0.8;
+ /** if solveConceptDrift is false, a new model must be learned at
intervals
+ * based on the number of reported actions */
+ private long learningInterval = 1;
+
+ // TODO: keep files of previous online learning
+ private boolean arffOverwrite = true;
+ /** only available when continuousLearning if false */
+ private boolean continueAfterCreation = true;
+
+ private boolean modelPersistency = true;
+
+ public boolean useOnlineLearning() {
+ return useOnlineLearning;
}
- public static void setArffPersistency(boolean arffPersistency) {
- WekaOptions.arffPersistency = arffPersistency;
+ public void setUseOnlineLearning(boolean useOnlineLearning) {
+ this.useOnlineLearning = useOnlineLearning;
}
- public static boolean isArffOverwrite() {
- return arffOverwrite;
+ public boolean continuousLearning() {
+ return continuousLearning;
}
- public static void setArffOverwrite(boolean arffOverwrite) {
- WekaOptions.arffOverwrite = arffOverwrite;
+ public void setContinuousLearning(boolean continuousLearning) {
+ this.continuousLearning = continuousLearning;
}
- public static long getModelCreationTreshold() {
+ public long modelCreationTreshold() {
return modelCreationTreshold;
}
- public static void setModelCreationTreshold(long modelCreationTreshold) {
- WekaOptions.modelCreationTreshold = modelCreationTreshold;
+ public void setModelCreationTreshold(long modelCreationTreshold) {
+ this.modelCreationTreshold = modelCreationTreshold;
}
- public static boolean isContinueAfterCreation() {
+ public long getMinimalLearnExamples() {
+ return minimalLearnExamples;
+ }
+
+ public void setMinimalLearnExamples(long minimalLearnExamples) {
+ this.minimalLearnExamples = minimalLearnExamples;
+ }
+
+ public boolean solveConceptDrift() {
+ return solveConceptDrift;
+ }
+
+ public void setSolveConceptDrift(boolean solveConceptDrift) {
+ if (!continuousLearning && solveConceptDrift)
+ throw new IllegalStateException("Cannot use concept drift solver
without continuous learning!");
+ this.solveConceptDrift = solveConceptDrift;
+ }
+
+
+ public long getLearningInterval() {
+ return learningInterval;
+ }
+
+ public void setLearningInterval(long learningInterval) {
+ this.learningInterval = learningInterval;
+ }
+
+ public boolean arffOverwrite() {
+ return arffOverwrite;
+ }
+
+ public void setArffOverwrite(boolean arffOverwrite) {
+ this.arffOverwrite = arffOverwrite;
+ }
+
+ public boolean continueAfterCreation() {
return continueAfterCreation;
}
- public static void setContinueAfterCreation(boolean
continueAfterCreation) {
- WekaOptions.continueAfterCreation = continueAfterCreation;
+ public void setContinueAfterCreation(boolean continueAfterCreation) {
+ this.continueAfterCreation = continueAfterCreation;
}
- public static boolean isModelPersistency() {
+ public boolean modelPersistency() {
return modelPersistency;
}
- public static void setModelPersistency(boolean modelPersistency) {
- WekaOptions.modelPersistency = modelPersistency;
+ public void setModelPersistency(boolean modelPersistency) {
+ this.modelPersistency = modelPersistency;
+ }
+
+ public double getCdHighCoverage() {
+ return cdHighCoverage;
+ }
+
+ public void setCdHighCoverage(double cdHighCoverage) {
+ this.cdHighCoverage = cdHighCoverage;
+ }
+
+ public double getCdLowCoverage() {
+ return cdLowCoverage;
+ }
+
+ public void setCdLowCoverage(double cdLowCoverage) {
+ this.cdLowCoverage = cdLowCoverage;
+ }
+
+ public double getCdAccuracy() {
+ return cdAccuracy;
+ }
+
+ public void setCdAccuracy(double cdAccuracy) {
+ this.cdAccuracy = cdAccuracy;
}
}
==============================================================================
Revision: 4b0bece8896a
Author: thijs
Date: Sat Nov 27 02:53:21 2010
Log: still updating to CSPoker 1396
http://code.google.com/p/opentestbed/source/detail?r=4b0bece8896a
Added:
/lib/annotations-1.0.jar
/src/bots/mctsbot/ai/bots/bot/gametree/action/IllegalActionException.java
/src/bots/mctsbot/ai/opponentmodels/listeners/OpponentModelListener.java
/src/bots/mctsbot/ai/opponentmodels/weka/WekaLearningModel.java
Deleted:
/src/bots/mctsbot/ai/opponentmodels/weka/WekaLearningOpponentModel.java
Modified:
/.classpath
/src/bots/mctsbot/ai/bots/bot/gametree/action/SearchBotAction.java
/src/bots/mctsbot/ai/opponentmodels/OpponentModel.java
/src/bots/mctsbot/ai/opponentmodels/weka/ActionTrackingVisitor.java
/src/bots/mctsbot/ai/opponentmodels/weka/WekaRegressionModelFactory.java
/src/bots/mctsbot/client/common/gamestate/modifiers/NewPocketCardsState.java
=======================================
--- /dev/null
+++ /lib/annotations-1.0.jar Sat Nov 27 02:53:21 2010
@@ -0,0 +1,59 @@
+PK
+ 6²Ã4 META-INF/þÊ PK
+ 5²Ã4âú ¾^ j META-INF/MANIFEST.MFóMÌËLK-.Ñ
+K-*ÎÌϳR0Ô3àårÌC q,HLÎHU Š %ÍôLy¹œ‹R KRSt *AêMõâ
+Ìt“L 4‚Kó |3“‹ò‹+‹KRs‹ <ó’õ4y¹x¹ PK
+ 6²Ã4 net/PK
+ 6²Ã4 net/jcip/PK
+ 6²Ã4 net/jcip/annotations/PK
+ 6²Ã4Ì,]. ´ $ net/jcip/annotations/GuardedBy.class
+ OOÂ@ Åß`¡ŠŠøçâA%
+ˆ^l<{ÒX” Ä”êÅÓR&Í6eKÚ- _̓ À e
+< ;û²ó{o²óýóù à Ç.š. ]
+ ª3•–L8¹ºî%j¦¼T™Ø Ú\›øŽP fe
+qG§Â4žJ• yü0¿Y „Ó 4VOø] z”ò½1™UVg¦ œÅ©eà U
+³•äËÍ}?å Χ,PµÓõ{ „Zß Ÿ "Z›] [1‰ Oû ä5Ku4 Ð
+Þ^Ânß'œ ¶^ ééš¡ð–¿%4W‘ƒQ‘%\lœ²ZA›@¨ÈÙ’ “CpP UAí¯ºØ–»%jG ç F
+»‹²‡ýÅ £ ƒ_PK
+ 6²Ã4¤aŒ®ú ® $ net/jcip/annotations/Immutable.class
+ ÏJ 1 Æ¿©«UkõæA«
+ztñìI°
+‚ ʺ
+â) CÉ’MJ7[è«yð |(鬇Ö Édæûå ˜ïŸÏ/ ×8Žp ¡ áˆÐ~öå\óÐX&tFy^ 5±|•©
+"œ$¥ &çWS éÞ:çƒ
+Æ»‚pq_1±Un «µ ßy]æì Ü Në™Tͧ
+Do-”-eðe=7°\Y¥Ë ÜL߯ Ây=›p T^BöÿAÆÞ ½ 0J^
+Óу¸ž9 q¦Íìχ"^ïƒÐÝX>M2Ö Ð« ²YRŸ@hHl¡:
+4 ï ¶%÷¤ IÞ }÷
+Ähc ûUÅ8@g PK
+ 6²Ã4´Ù
+½þ ¶ ( net/jcip/annotations/NotThreadSafe.class
+ ÏJÃ@ Æ¿©Ñú¯öæAª=ôhðìI°BAkI£ ž¶éX7lwK²)ôÕ<ø }(qâÁ* \˜ Ùý~ó
+Ìúóý À%Ú Ž ´
+ šcWd ßjÄöÐùø-c5
+«W¾HÕR N¢Âz=ç' ë‰ákk W^;› ÎïJ&4ÊÎBõ#„7.)æl=O¯ §ÕL¬² {Ñ Ke
+ Þæú†K«xµ` ëñó¨O8«f#ö‚J%dï däŒNV Ñã0
+Ü‹kײ ÓD/~5ä០Z Û‡Iʉ't*'m Õ# j [(O
+õï» mÉ
+ù
+$û b4±‡ýòÅ8Àá PK
+ 6²Ã4%‡àxü ° % net/jcip/annotations/ThreadSafe.class
+ MK 1 †ßÔÖhýhõæAª
+ztñìIh
+‚ e ñ”¦cÍ’fËn¶Ð¿æÁ Ð %Îzp=, H&3ï3ïÀl¾>> \áX¢#Ñ•8 hOÒ"3tk
+ tÔ{Fz6Ñot™è• 8‰ 삞mn§Žn¼Oƒ 6õ¹Àù]ÉDNûy¤
+h šbA>ÐìZà´žQ:›S`½µÒ®àÉ õÜÐQi¥ÖKb¸©^ÆC ³z6¦À(ÿ˜ìÿƒŒSgÍšA ?=¨Ñ=»ö<
+(1vù§! ª
+ t+ÏÇiB&pSí˜jK} ß-”§ æÏÛÂ6Ç
+W%Ç
+Öw_! mìa¿Ì 8ü PK
+ 6²Ã4 íA META-INF/þÊ PK
+ 5²Ã4âú ¾^ j ¤ + META-INF/MANIFEST.MFPK
+ 6²Ã4 íA» net/PK
+ 6²Ã4 íAÝ net/jcip/PK
+ 6²Ã4 íA net/jcip/annotations/PK
+ 6²Ã4Ì,]. ´ $ ¤ 7 net/jcip/annotations/GuardedBy.classPK
+ 6²Ã4¤aŒ®ú ® $ ¤ „ net/jcip/annotations/Immutable.classPK
+ 6²Ã4´Ù
+½þ ¶ ( ¤ À net/jcip/annotations/NotThreadSafe.classPK
+ 6²Ã4%‡àxü ° % ¤ net/jcip/annotations/ThreadSafe.classPK
v C
=======================================
--- /dev/null
+++
/src/bots/mctsbot/ai/bots/bot/gametree/action/IllegalActionException.java
Sat Nov 27 02:53:21 2010
@@ -0,0 +1,38 @@
+/**
+ * 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 bots.mctsbot.ai.bots.bot.gametree.action;
+
+/**
+ * Thrown to indicate that the tried action is not a valid action.
+ */
+public class IllegalActionException
+ extends Exception {
+
+ private static final long serialVersionUID = -5675804638273023229L;
+
+ public IllegalActionException(String message) {
+ super(message);
+ }
+
+ public IllegalActionException(Throwable e) {
+ super(e);
+ }
+
+ public IllegalActionException(String message, Throwable e) {
+ super(message, e);
+ }
+}
=======================================
--- /dev/null
+++
/src/bots/mctsbot/ai/opponentmodels/listeners/OpponentModelListener.java
Sat Nov 27 02:53:21 2010
@@ -0,0 +1,16 @@
+package bots.mctsbot.ai.opponentmodels.listeners;
+
+import bots.mctsbot.ai.opponentmodels.OpponentModel;
+import bots.mctsbot.client.common.gamestate.GameState;
+import bots.mctsbot.common.elements.player.PlayerId;
+
+public interface OpponentModelListener {
+
+ public void onGetCheckProbabilities(GameState state, PlayerId actor);
+
+ public void onGetFoldCallRaiseProbabilities(GameState state, PlayerId
actor);
+
+ public void onGetShowdownProbilities(GameState state, PlayerId actor);
+
+ public void setOpponentModel(OpponentModel opponentModel);
+}
=======================================
--- /dev/null
+++ /src/bots/mctsbot/ai/opponentmodels/weka/WekaLearningModel.java Sat Nov
27 02:53:21 2010
@@ -0,0 +1,175 @@
+package bots.mctsbot.ai.opponentmodels.weka;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.log4j.Logger;
+
+import bots.mctsbot.ai.bots.bot.gametree.mcts.MCTSBot;
+import bots.mctsbot.ai.bots.bot.gametree.mcts.nodes.INode;
+import bots.mctsbot.ai.opponentmodels.OpponentModel;
+import bots.mctsbot.ai.opponentmodels.listeners.OpponentModelListener;
+import bots.mctsbot.client.common.gamestate.GameState;
+import bots.mctsbot.client.common.playerstate.PlayerState;
+import bots.mctsbot.common.elements.player.PlayerId;
+import bots.mctsbot.common.util.Pair;
+import bots.mctsbot.common.util.Triple;
+
+/**
+ * This OpponentModel delegates to a provided default {@link WekaModel}
for its opponent-model.
+ * In addition it observes the game and (configured by {@link
WekaOptions}) replaces
+ * the opponent-model for each villain after enough data has been
collected.
+ *
+ */
+public class WekaLearningModel implements OpponentModel {
+
+ protected static final Logger logger =
Logger.getLogger(WekaLearningModel.class);
+
+ private PlayerTrackingVisitor permanentVisitor;
+ private ActionTrackingVisitor actionTrackingVisitor;
+ private final Deque<PlayerTrackingVisitor> visitors = new
ArrayDeque<PlayerTrackingVisitor>();
+
+ Map<PlayerId, WekaRegressionModel> opponentModels = new HashMap<PlayerId,
WekaRegressionModel>();
+ private final WekaRegressionModel defaultModel;
+ private final WekaOptions config;
+
+ private final PlayerId bot;
+
+ private final OpponentModelListener[] listeners;
+ private INode node;
+
+ public WekaLearningModel(PlayerId botId, WekaRegressionModel
defaultModel, WekaOptions config, OpponentModelListener... listeners) {
+ this.permanentVisitor = new PlayerTrackingVisitor(this);
+ this.visitors.add(permanentVisitor);
+ this.defaultModel = defaultModel;
+ this.config = config;
+ this.bot = botId;
+ this.listeners = listeners;
+ for (int i = 0; i < listeners.length; i++)
+ listeners[i].setOpponentModel(this);
+ if (config.useOnlineLearning()) {
+ this.actionTrackingVisitor = new ActionTrackingVisitor(this, bot);
+ }
+ }
+
+ public WekaOptions getConfig() {
+ return config;
+ }
+
+ // these methods are used by KullbackLeiblerListener
+ // TODO: better design (this is messy)
+ public Map<PlayerId, WekaRegressionModel> getOpponentModels() {
+ return opponentModels;
+ }
+
+ public WekaRegressionModel getDefaultModel() {
+ return defaultModel;
+ }
+
+ public Propositionalizer getCurrentGamePropositionalizer() {
+ return visitors.peek().getPropz();
+ }
+
+ // *************************************************
+
+ @Override
+ public void assumePermanently(GameState gameState) {
+ // make sure we have created Models for all players
+ Set<PlayerState> seatedPlayers = gameState.getAllSeatedPlayers();
+ for (PlayerState playerState : seatedPlayers) {
+ getWekaModel(playerState.getPlayerId());
+ }
+ permanentVisitor.readHistory(gameState);
+ if (actionTrackingVisitor != null) {
+ actionTrackingVisitor.readHistory(gameState);
+ }
+ }
+
+ @Override
+ public void assumeTemporarily(GameState gameState) {
+ PlayerTrackingVisitor root = visitors.peek();
+ PlayerTrackingVisitor clonedTopVisitor = root.clone();
+ clonedTopVisitor.readHistory(gameState);
+ visitors.push(clonedTopVisitor);
+ }
+
+ @Override
+ public void forgetLastAssumption() {
+ visitors.pop();
+ // the permanentVisitor should never be popped
+ if (visitors.isEmpty()) {
+ throw new IllegalStateException("'forgetAssumption' was called more
often than 'assumeTemporarily'");
+ }
+ }
+
+ private WekaRegressionModel getWekaModel(PlayerId actor) {
+ WekaRegressionModel model = opponentModels.get(actor);
+ if (model == null) {
+ model = new WekaRegressionModel(defaultModel);
+ if (config.useOnlineLearning() && !actor.equals(bot)) {
+ opponentModels.put(actor, model);
+ actionTrackingVisitor.getPropz().addPlayer(actor, new
ARFFPlayer(actor, model, config, actionTrackingVisitor));
+ }
+ }
+ return model;
+ }
+
+ public ARFFPlayer getPlayer(PlayerId actor) {
+ if (config.useOnlineLearning() && !actor.equals(bot)) {
+ return actionTrackingVisitor.getPropz().getARFF(actor);
+ } else
+ return null;
+ }
+
+ public double getPlayerAccuracy(PlayerId actor) {
+ if (config.useOnlineLearning() && !actor.equals(bot)) {
+ return actionTrackingVisitor.getAccuracy(actor);
+ } else
+ return 0.0;
+ }
+
+ @Override
+ public Pair<Double, Double> getCheckBetProbabilities(GameState gameState,
PlayerId actor) {
+ for (int i = 0; i < listeners.length; i++)
+ listeners[i].onGetCheckProbabilities(gameState, actor);
+ return getWekaModel(actor).getCheckBetProbabilities(actor,
getCurrentGamePropositionalizer());
+ }
+
+ @Override
+ public Triple<Double, Double, Double>
getFoldCallRaiseProbabilities(GameState gameState, PlayerId actor) {
+ for (int i = 0; i < listeners.length; i++)
+ listeners[i].onGetFoldCallRaiseProbabilities(gameState, actor);
+ return getWekaModel(actor).getFoldCallRaiseProbabilities(actor,
getCurrentGamePropositionalizer());
+ }
+
+ @Override
+ public double[] getShowdownProbabilities(GameState gameState, PlayerId
actor) throws UnsupportedOperationException {
+ for (int i = 0; i < listeners.length; i++)
+ listeners[i].onGetShowdownProbilities(gameState, actor);
+ return getWekaModel(actor).getShowdownProbabilities(actor,
getCurrentGamePropositionalizer());
+ }
+
+ /**
+ * Saves the node with the last move played by {@link MCTSBot}.
+ * Is used to get probabilities of the opponents moves in order
+ * to calculate the accuracy of predictions by the opponentmodel.
+ * @param node INode containing last action by MCTSBot
+ */
+ @Override
+ public void setChosenNode(INode node) {
+ this.node = node;
+ }
+
+ @Override
+ public INode getChosenNode() {
+ return this.node;
+ }
+
+ @Override
+ public PlayerId getBotId() {
+ return bot;
+ }
+}
=======================================
--- /src/bots/mctsbot/ai/opponentmodels/weka/WekaLearningOpponentModel.java
Sun May 23 13:04:51 2010
+++ /dev/null
@@ -1,103 +0,0 @@
-package bots.mctsbot.ai.opponentmodels.weka;
-
-import java.util.ArrayDeque;
-import java.util.Deque;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.log4j.Logger;
-
-import bots.mctsbot.ai.opponentmodels.OpponentModel;
-import bots.mctsbot.client.common.gamestate.GameState;
-import bots.mctsbot.client.common.playerstate.PlayerState;
-import bots.mctsbot.common.elements.player.PlayerId;
-import bots.mctsbot.common.util.Pair;
-import bots.mctsbot.common.util.Triple;
-
-/**
- * This OpponentModel delegates to a provided default {@link WekaModel}
for its opponent-model.
- * In addition it observes the game and (configured by {@link
WekaOptions}) replaces
- * the opponent-model for each villain after enough data has been
collected.
- *
- */
-public final class WekaLearningOpponentModel implements OpponentModel {
-
- protected static final Logger logger =
Logger.getLogger(WekaRegressionModel.class);
-
- private PlayerTrackingVisitor permanentVisitor;
- private ActionTrackingVisitor actionTrackingVisitor;
- private final Deque<PlayerTrackingVisitor> visitors = new
ArrayDeque<PlayerTrackingVisitor>();
-
- Map<PlayerId, WekaRegressionModel> opponentModels = new HashMap<PlayerId,
WekaRegressionModel>();
- WekaRegressionModel defaultModel;
-
- public WekaLearningOpponentModel(WekaRegressionModel defaultModel) {
- this.permanentVisitor = new PlayerTrackingVisitor();
- this.visitors.add(permanentVisitor);
- this.defaultModel = defaultModel;
- if (WekaOptions.isArffPersistency()) {
- this.actionTrackingVisitor = new ActionTrackingVisitor();
- }
- }
-
- @Override
- public void assumePermanently(GameState gameState) {
- // make sure we have created Models for all players
- Set<PlayerState> seatedPlayers = gameState.getAllSeatedPlayers();
- for (PlayerState playerState : seatedPlayers) {
- getWekaModel(playerState.getPlayerId());
- }
- permanentVisitor.readHistory(gameState);
- if (actionTrackingVisitor != null) {
- actionTrackingVisitor.readHistory(gameState);
- }
- }
-
- @Override
- public void assumeTemporarily(GameState gameState) {
- PlayerTrackingVisitor root = visitors.peek();
- PlayerTrackingVisitor clonedTopVisitor = root.clone();
- clonedTopVisitor.readHistory(gameState);
- visitors.push(clonedTopVisitor);
- }
-
- @Override
- public void forgetLastAssumption() {
- visitors.pop();
- // the permanentVisitor should never be popped
- if (visitors.isEmpty()) {
- throw new IllegalStateException("'forgetAssumption' was called more
often than 'assumeTemporarily'");
- }
- }
-
- private Propositionalizer getCurrentGamePropositionalizer() {
- return visitors.peek().getPropz();
- }
-
- private WekaRegressionModel getWekaModel(PlayerId actor) {
- WekaRegressionModel model = opponentModels.get(actor);
- if (model == null) {
- model = new WekaRegressionModel(defaultModel);
- opponentModels.put(actor, model);
- actionTrackingVisitor.getPropz().addPlayer(actor, new ARFFPlayer(actor,
model));
- }
- return model;
- }
-
- @Override
- public Pair<Double, Double> getCheckBetProbabilities(GameState gameState,
PlayerId actor) {
- return getWekaModel(actor).getCheckBetProbabilities(actor,
getCurrentGamePropositionalizer());
- }
-
- @Override
- public Triple<Double, Double, Double>
getFoldCallRaiseProbabilities(GameState gameState, PlayerId actor) {
- return getWekaModel(actor).getFoldCallRaiseProbabilities(actor,
getCurrentGamePropositionalizer());
- }
-
- @Override
- public double[] getShowdownProbabilities(GameState gameState, PlayerId
actor) throws UnsupportedOperationException {
- return getWekaModel(actor).getShowdownProbabilities(actor,
getCurrentGamePropositionalizer());
- }
-
-}
=======================================
--- /.classpath Sun Nov 7 06:35:47 2010
+++ /.classpath Sat Nov 27 02:53:21 2010
@@ -6,6 +6,7 @@
<classpathentry exported="true" kind="lib" path="lib/meerkat-api.jar"
sourcepath="/home/guy/Werk/cspoker/Meerkat-API/docs"/>
<classpathentry kind="lib" path="lib/commons-io-1.4-sources.jar"/>
<classpathentry kind="lib" path="lib/protobuf-java-2.3.0.jar"/>
+ <classpathentry kind="lib" path="lib/annotations-1.0.jar"/>
<classpathentry kind="con"
path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry exported="true" kind="lib" path="lib/commons-io-1.4.jar"/>
<classpathentry kind="lib" path="lib/jfreechart-1.0.13.jar"
sourcepath="/home/guy/Werk/cspoker/jfreechart-1.0.13/source"/>
=======================================
--- /src/bots/mctsbot/ai/bots/bot/gametree/action/SearchBotAction.java Sun
Nov 7 06:35:47 2010
+++ /src/bots/mctsbot/ai/bots/bot/gametree/action/SearchBotAction.java Sat
Nov 27 02:53:21 2010
@@ -15,6 +15,8 @@
*/
package bots.mctsbot.ai.bots.bot.gametree.action;
+import java.rmi.RemoteException;
+
import bots.mctsbot.client.common.gamestate.GameState;
import bots.mctsbot.client.common.gamestate.modifiers.NewRoundState;
import bots.mctsbot.client.common.gamestate.modifiers.NextPlayerState;
@@ -41,7 +43,9 @@
return this;
}
- public abstract void perform(RemoteHoldemPlayerContext context);
+ public abstract void perform(RemoteHoldemPlayerContext context) throws
RemoteException, IllegalActionException;
+
+ public abstract GameState getUnwrappedStateAfterAction();
public abstract GameState getStateAfterAction() throws
GameEndedException, DefaultWinnerException;
=======================================
--- /src/bots/mctsbot/ai/opponentmodels/OpponentModel.java Sun Nov 7
06:35:47 2010
+++ /src/bots/mctsbot/ai/opponentmodels/OpponentModel.java Sat Nov 27
02:53:21 2010
@@ -15,6 +15,7 @@
*/
package bots.mctsbot.ai.opponentmodels;
+import bots.mctsbot.ai.bots.bot.gametree.mcts.nodes.INode;
import bots.mctsbot.client.common.gamestate.GameState;
import bots.mctsbot.common.elements.player.PlayerId;
import bots.mctsbot.common.util.Pair;
@@ -34,6 +35,10 @@
double[] getShowdownProbabilities(GameState gameState, PlayerId actor)
throws UnsupportedOperationException;
+ void setChosenNode(INode node);
+
+ INode getChosenNode();
+
/**
* Assume the given game state permanently.
*/
@@ -49,9 +54,19 @@
*/
void forgetLastAssumption();
+ /**
+ * Get id of bot
+ */
+ PlayerId getBotId();
+
+ // /**
+ // * Return a clone of opponentmodel
+ // */
+ // OpponentModel clone();
+
static interface Factory {
- OpponentModel create();
+ OpponentModel create(PlayerId bot);
}
}
=======================================
--- /src/bots/mctsbot/ai/opponentmodels/weka/ActionTrackingVisitor.java Tue
Nov 23 08:42:27 2010
+++ /src/bots/mctsbot/ai/opponentmodels/weka/ActionTrackingVisitor.java Sat
Nov 27 02:53:21 2010
@@ -5,7 +5,6 @@
import org.apache.log4j.Logger;
-import weka.classifiers.evaluation.Prediction;
import bots.mctsbot.ai.bots.bot.gametree.action.BetAction;
import bots.mctsbot.ai.bots.bot.gametree.action.CallAction;
import bots.mctsbot.ai.bots.bot.gametree.action.CheckAction;
=======================================
---
/src/bots/mctsbot/ai/opponentmodels/weka/WekaRegressionModelFactory.java
Sun Nov 7 06:35:47 2010
+++
/src/bots/mctsbot/ai/opponentmodels/weka/WekaRegressionModelFactory.java
Sat Nov 27 02:53:21 2010
@@ -24,14 +24,23 @@
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
+import net.jcip.annotations.ThreadSafe;
+
import org.apache.log4j.Logger;
import weka.classifiers.Classifier;
import bots.mctsbot.ai.opponentmodels.OpponentModel;
-
+import bots.mctsbot.ai.opponentmodels.listeners.OpponentModelListener;
+import bots.mctsbot.common.elements.player.PlayerId;
+
+@ThreadSafe
public class WekaRegressionModelFactory implements OpponentModel.Factory {
- public static WekaRegressionModelFactory createForZip(String zippedModel)
throws IOException, ClassNotFoundException {
+ private OpponentModelListener[] listeners = {};
+ private WekaOptions config;
+
+ public static WekaRegressionModelFactory createForZip(String zippedModel,
WekaOptions config, OpponentModelListener... listeners) throws IOException,
+ ClassNotFoundException {
ZipInputStream zis = null;
ClassLoader classLoader =
WekaRegressionModelFactory.class.getClassLoader();
@@ -51,15 +60,16 @@
zis.close();
fis.close();
- return new WekaRegressionModelFactory(classifiers.get("preBet.model"),
classifiers.get("preFold.model"), classifiers.get("preCall.model"),
- classifiers.get("preRaise.model"), classifiers.get("postBet.model"),
classifiers.get("postFold.model"), classifiers.get("postCall.model"),
- classifiers.get("postRaise.model"),
classifiers.get("showdown0.model"), classifiers.get("showdown1.model"),
classifiers.get("showdown2.model"),
- classifiers.get("showdown3.model"),
classifiers.get("showdown4.model"), classifiers.get("showdown5.model"));
+ return new WekaRegressionModelFactory(config, listeners,
classifiers.get("preBet.model"), classifiers.get("preFold.model"),
classifiers
+ .get("preCall.model"), classifiers.get("preRaise.model"),
classifiers.get("postBet.model"), classifiers.get("postFold.model"),
classifiers
+ .get("postCall.model"), classifiers.get("postRaise.model"),
classifiers.get("showdown0.model"), classifiers.get("showdown1.model"),
classifiers
+ .get("showdown2.model"), classifiers.get("showdown3.model"),
classifiers.get("showdown4.model"), classifiers.get("showdown5.model"));
}
private final static Logger logger =
Logger.getLogger(WekaRegressionModelFactory.class);
- public static WekaRegressionModelFactory createForDir(String models)
throws IOException, ClassNotFoundException {
+ public static WekaRegressionModelFactory createForDir(String models,
WekaOptions config, OpponentModelListener... listeners) throws IOException,
+ ClassNotFoundException {
Classifier preBetModel, preFoldModel, preCallModel, preRaiseModel,
postBetModel, postFoldModel, postCallModel, postRaiseModel, showdown0Model,
showdown1Model, showdown2Model, showdown3Model, showdown4Model,
showdown5Model;
ClassLoader classLoader =
WekaRegressionModelFactory.class.getClassLoader();
ObjectInputStream in = new
ObjectInputStream(classLoader.getResourceAsStream(models + "preBet.model"));
@@ -104,13 +114,15 @@
in = new ObjectInputStream(classLoader.getResourceAsStream(models
+ "showdown5.model"));
showdown5Model = (Classifier) in.readObject();
in.close();
- return new WekaRegressionModelFactory(preBetModel, preFoldModel,
preCallModel, preRaiseModel, postBetModel, postFoldModel, postCallModel,
- postRaiseModel, showdown0Model, showdown1Model, showdown2Model,
showdown3Model, showdown4Model, showdown5Model);
+ return new WekaRegressionModelFactory(config, listeners, preBetModel,
preFoldModel, preCallModel, preRaiseModel, postBetModel, postFoldModel,
+ postCallModel, postRaiseModel, showdown0Model, showdown1Model,
showdown2Model, showdown3Model, showdown4Model, showdown5Model);
}
- public WekaRegressionModelFactory(Classifier preBetModel, Classifier
preFoldModel, Classifier preCallModel, Classifier preRaiseModel,
- Classifier postBetModel, Classifier postFoldModel, Classifier
postCallModel, Classifier postRaiseModel, Classifier showdown0Model,
- Classifier showdown1Model, Classifier showdown2Model, Classifier
showdown3Model, Classifier showdown4Model, Classifier showdown5Model) {
+ public WekaRegressionModelFactory(WekaOptions config,
OpponentModelListener[] listeners, Classifier preBetModel, Classifier
preFoldModel,
+ Classifier preCallModel, Classifier preRaiseModel, Classifier
postBetModel, Classifier postFoldModel, Classifier postCallModel,
+ Classifier postRaiseModel, Classifier showdown0Model, Classifier
showdown1Model, Classifier showdown2Model, Classifier showdown3Model,
+ Classifier showdown4Model, Classifier showdown5Model) {
+ this.listeners = listeners;
this.preBetModel = preBetModel;
this.preFoldModel = preFoldModel;
this.preCallModel = preCallModel;
@@ -125,15 +137,17 @@
this.showdown3Model = showdown3Model;
this.showdown4Model = showdown4Model;
this.showdown5Model = showdown5Model;
+ this.config = config;
}
private final Classifier preBetModel, preFoldModel, preCallModel,
preRaiseModel, postBetModel, postFoldModel, postCallModel, postRaiseModel,
showdown0Model, showdown1Model, showdown2Model, showdown3Model,
showdown4Model, showdown5Model;
@Override
- public OpponentModel create() {
- return new WekaLearningOpponentModel(new
WekaRegressionModel(preBetModel, preFoldModel, preCallModel, preRaiseModel,
postBetModel, postFoldModel,
- postCallModel, postRaiseModel, showdown0Model, showdown1Model,
showdown2Model, showdown3Model, showdown4Model, showdown5Model));
+ public OpponentModel create(PlayerId bot) {
+ return new WekaLearningModel(bot, new WekaRegressionModel(preBetModel,
preFoldModel, preCallModel, preRaiseModel, postBetModel, postFoldModel,
+ postCallModel, postRaiseModel, showdown0Model, showdown1Model,
showdown2Model, showdown3Model, showdown4Model, showdown5Model), config,
+ listeners);
}
@Override
=======================================
---
/src/bots/mctsbot/client/common/gamestate/modifiers/NewPocketCardsState.java
Sun Nov 7 06:35:47 2010
+++
/src/bots/mctsbot/client/common/gamestate/modifiers/NewPocketCardsState.java
Sat Nov 27 02:53:21 2010
@@ -16,6 +16,7 @@
package bots.mctsbot.client.common.gamestate.modifiers;
import java.util.ArrayList;
+import java.util.EnumSet;
import java.util.List;
import bots.mctsbot.client.common.gamestate.ForwardingGameState;
@@ -27,7 +28,7 @@
import
bots.mctsbot.common.api.lobby.holdemtable.holdemplayer.event.NewPocketCardsEvent;
import bots.mctsbot.common.elements.player.PlayerId;
-import com.biotools.meerkat.Hand;
+import com.biotools.meerkat.Card;
public class NewPocketCardsState extends ForwardingGameState {
@@ -42,7 +43,7 @@
this.playerState = new ForwardingPlayerState(super.getPlayer(playerId)) {
@Override
- public Hand getCards() {
+ public EnumSet<Card> getCards() {
return NewPocketCardsState.this.event.getPocketCards();
}
@@ -76,6 +77,14 @@
};
}
+
+ public EnumSet<Card> getPlayerCards() {
+ return playerState.getCards();
+ }
+
+ public PlayerState getPlayer() {
+ return playerState;
+ }
@Override
public PlayerState getPlayer(PlayerId playerId) {
==============================================================================
Revision: 53fecd2eed22
Author: thijs
Date: Wed Dec 8 02:17:51 2010
Log: updated to cspoker revision 1396
http://code.google.com/p/opentestbed/source/detail?r=53fecd2eed22
Modified:
/src/bots/mctsbot/ai/bots/bot/gametree/mcts/FixedSampleMCTSBot.java
=======================================
--- /src/bots/mctsbot/ai/bots/bot/gametree/mcts/FixedSampleMCTSBot.java Sun
Nov 7 06:35:47 2010
+++ /src/bots/mctsbot/ai/bots/bot/gametree/mcts/FixedSampleMCTSBot.java Wed
Dec 8 02:17:51 2010
@@ -15,9 +15,12 @@
*/
package bots.mctsbot.ai.bots.bot.gametree.mcts;
+import java.rmi.RemoteException;
+
import org.apache.log4j.Logger;
import bots.mctsbot.ai.bots.bot.AbstractBot;
+import bots.mctsbot.ai.bots.bot.gametree.action.IllegalActionException;
import bots.mctsbot.ai.bots.bot.gametree.mcts.listeners.MCTSListener;
import bots.mctsbot.ai.bots.bot.gametree.mcts.nodes.Config;
import bots.mctsbot.ai.bots.bot.gametree.mcts.nodes.INode;
@@ -26,7 +29,6 @@
import bots.mctsbot.client.common.gamestate.GameState;
import
bots.mctsbot.common.api.lobby.holdemtable.holdemplayer.context.RemoteHoldemPlayerContext;
import bots.mctsbot.common.elements.player.PlayerId;
-import bots.mctsbot.common.elements.table.Round;
public class FixedSampleMCTSBot extends AbstractBot {
@@ -106,12 +108,20 @@
iterate(root);
iterate(root);
} while (root.getNbSamples() < nbSamples);
- if (printed && gameState.getRound() == r)
- printed = false;
- if (logger.isDebugEnabled()) {
- logger.debug("Stopped MCTS.");
- }
-
root.selectChild(config.getMoveSelectionStrategy()).getLastAction().getAction().perform(playerContext);
+ // if (printed && gameState.getRound() == r)
+ // printed = false;
+ // if (logger.isDebugEnabled()) {
+ // logger.debug("Stopped MCTS.");
+ // }
+ try {
+
root.selectChild(config.getMoveSelectionStrategy()).getLastAction().getAction().perform(playerContext);
+ } catch (RemoteException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IllegalActionException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
MCTSListener[] listeners = createListeners(gameState, botId);
for (MCTSListener listener : listeners) {
@@ -119,24 +129,9 @@
}
}
- public static boolean printed = false;
long nbSamples;
- long currentCount = 0;
- long lastCount = 0;
- private final static Round r = Round.PREFLOP;
private void iterate(RootNode root) {
- Round round = gameStateContainer.getGameState().getRound();
- if (printed && round == r) {
- currentCount = root.getNbSamples();
- if (currentCount - lastCount != 1) {
- for (long i = lastCount + 1; i <= currentCount; i++)
- System.out.println(i + " - " + root.getEV() + " - " +
root.getEVStdDev());
- } else {
- System.out.println(currentCount + " - " + root.getEV() + " - " +
root.getEVStdDev());
- }
- lastCount = currentCount;
- }
INode selectedLeaf = root.selectRecursively();
selectedLeaf.expand();
double value = selectedLeaf.simulate();
==============================================================================
Revision: 22da981dc500
Author: thijs
Date: Wed Dec 8 08:36:14 2010
Log: updated to CSPoker revision 1396
http://code.google.com/p/opentestbed/source/detail?r=22da981dc500
Modified:
/src/bots/mctsbot/ai/bots/bot/gametree/action/BetAction.java
/src/bots/mctsbot/ai/bots/bot/gametree/action/CallAction.java
/src/bots/mctsbot/ai/bots/bot/gametree/action/CheckAction.java
/src/bots/mctsbot/ai/bots/bot/gametree/action/FoldAction.java
/src/bots/mctsbot/ai/bots/bot/gametree/action/RaiseAction.java
/src/bots/mctsbot/ai/bots/bot/gametree/mcts/FixedSampleMCTSBot.java
/src/bots/mctsbot/ai/bots/bot/gametree/mcts/FixedSampleMCTSBotFactory.java
/src/bots/mctsbot/ai/bots/bot/gametree/mcts/MCTSBot.java
/src/bots/mctsbot/ai/bots/bot/gametree/mcts/MCTSBotFactory.java
/src/bots/mctsbot/ai/bots/bot/gametree/mcts/MCTSMeerkatBot.java
/src/bots/mctsbot/ai/bots/bot/gametree/search/BotActionNode.java
/src/bots/mctsbot/ai/bots/bot/gametree/search/SearchBotFactory.java
/src/bots/mctsbot/ai/opponentmodels/simple/HistogramModel.java
/src/bots/mctsbot/ai/opponentmodels/simple/HistogramModelFactory.java
/src/bots/mctsbot/ai/opponentmodels/weka/ARFFFile.java
/src/bots/mctsbot/ai/opponentmodels/weka/ARFFPlayer.java
/src/bots/mctsbot/ai/opponentmodels/weka/PlayerTrackingVisitor.java
/src/bots/mctsbot/client/common/gamestate/modifiers/NewPocketCardsState.java
=======================================
--- /src/bots/mctsbot/ai/bots/bot/gametree/action/BetAction.java Sun Nov 7
06:35:47 2010
+++ /src/bots/mctsbot/ai/bots/bot/gametree/action/BetAction.java Wed Dec 8
08:36:14 2010
@@ -15,6 +15,8 @@
*/
package bots.mctsbot.ai.bots.bot.gametree.action;
+import java.rmi.RemoteException;
+
import bots.mctsbot.client.common.gamestate.GameState;
import bots.mctsbot.client.common.gamestate.modifiers.AllInState;
import bots.mctsbot.client.common.gamestate.modifiers.BetState;
@@ -37,12 +39,12 @@
}
@Override
- public void perform(RemoteHoldemPlayerContext context) {
+ public void perform(RemoteHoldemPlayerContext context) throws
RemoteException, IllegalActionException {
context.betOrRaise(amount);
}
@Override
- public GameState getStateAfterAction() {
+ public GameState getUnwrappedStateAfterAction() {
GameState betState;
int stack = gameState.getPlayer(actor).getStack();
if (stack == amount) {
@@ -51,6 +53,12 @@
betState = new BetState(gameState, new BetEvent(actor, amount));
} else
throw new IllegalStateException("Can't bet amount: " + amount + ", with
stack: " + stack);
+ return betState;
+ }
+
+ @Override
+ public GameState getStateAfterAction() {
+ GameState betState = getUnwrappedStateAfterAction();
PlayerState nextToAct = betState.getNextActivePlayerAfter(actor);
if (nextToAct != null) {
return new NextPlayerState(betState, new
NextPlayerEvent(nextToAct.getPlayerId()));
@@ -66,5 +74,4 @@
return "Bet " + Util.parseDollars(amount);
}
}
-
-}
+}
=======================================
--- /src/bots/mctsbot/ai/bots/bot/gametree/action/CallAction.java Sun Nov
7 06:35:47 2010
+++ /src/bots/mctsbot/ai/bots/bot/gametree/action/CallAction.java Wed Dec
8 08:36:14 2010
@@ -15,6 +15,7 @@
*/
package bots.mctsbot.ai.bots.bot.gametree.action;
+import java.rmi.RemoteException;
import java.util.Set;
import bots.mctsbot.client.common.gamestate.GameState;
@@ -36,9 +37,25 @@
}
@Override
- public void perform(RemoteHoldemPlayerContext context) {
+ public void perform(RemoteHoldemPlayerContext context) throws
RemoteException, IllegalActionException {
context.checkOrCall();
}
+
+ @Override
+ public GameState getUnwrappedStateAfterAction() {
+ PlayerState actorState = gameState.getPlayer(actor);
+ int largestBet = gameState.getLargestBet();
+ int stack = actorState.getStack();
+ int bet = actorState.getBet();
+
+ GameState state;
+ if (stack <= largestBet - bet) {
+ state = new AllInState(gameState, new AllInEvent(actor, stack));
+ } else {
+ state = new CallState(gameState, new CallEvent(actor, largestBet -
bet));
+ }
+ return state;
+ }
@Override
public GameState getStateAfterAction() throws GameEndedException {
@@ -51,10 +68,8 @@
}
}
- PlayerState actorState = gameState.getPlayer(actor);
+ GameState state = getUnwrappedStateAfterAction();
int largestBet = gameState.getLargestBet();
- int stack = actorState.getStack();
- int bet = actorState.getBet();
// what if small or big blind all-in?
if (roundEnds && gameState.getRound().equals(Round.PREFLOP) &&
actor.equals(gameState.getSmallBlind())
@@ -62,12 +77,6 @@
roundEnds = false;
}
- GameState state;
- if (stack <= largestBet - bet) {
- state = new AllInState(gameState, new AllInEvent(actor, stack));
- } else {
- state = new CallState(gameState, new CallEvent(actor, largestBet -
bet));
- }
if (roundEnds) {
return getNewRoundState(state);
} else {
=======================================
--- /src/bots/mctsbot/ai/bots/bot/gametree/action/CheckAction.java Sun Nov
7 06:35:47 2010
+++ /src/bots/mctsbot/ai/bots/bot/gametree/action/CheckAction.java Wed Dec
8 08:36:14 2010
@@ -15,6 +15,8 @@
*/
package bots.mctsbot.ai.bots.bot.gametree.action;
+import java.rmi.RemoteException;
+
import bots.mctsbot.client.common.gamestate.GameState;
import bots.mctsbot.client.common.gamestate.modifiers.CheckState;
import bots.mctsbot.client.common.gamestate.modifiers.NextPlayerState;
@@ -32,9 +34,14 @@
}
@Override
- public void perform(RemoteHoldemPlayerContext context) {
+ public void perform(RemoteHoldemPlayerContext context) throws
RemoteException, IllegalActionException {
context.checkOrCall();
}
+
+ @Override
+ public GameState getUnwrappedStateAfterAction() {
+ return new CheckState(gameState, new CheckEvent(actor));
+ }
@Override
public GameState getStateAfterAction() throws GameEndedException {
@@ -43,7 +50,7 @@
boolean newRound = nextToAct.hasChecked() ||
gameState.getRound().equals(Round.PREFLOP) &&
actor.equals(gameState.getBigBlind())
&& gameState.getLargestBet() <=
gameState.getTableConfiguration().getBigBlind();
- CheckState checkState = new CheckState(gameState, new CheckEvent(actor));
+ GameState checkState = getUnwrappedStateAfterAction();
if (!newRound) {
return new NextPlayerState(checkState, new
NextPlayerEvent(nextToAct.getPlayerId()));
}
@@ -54,5 +61,4 @@
public String toString() {
return "Check";
}
-
-}
+}
=======================================
--- /src/bots/mctsbot/ai/bots/bot/gametree/action/FoldAction.java Sun Nov
7 06:35:47 2010
+++ /src/bots/mctsbot/ai/bots/bot/gametree/action/FoldAction.java Wed Dec
8 08:36:14 2010
@@ -15,6 +15,7 @@
*/
package bots.mctsbot.ai.bots.bot.gametree.action;
+import java.rmi.RemoteException;
import java.util.Set;
import bots.mctsbot.client.common.gamestate.GameState;
@@ -34,9 +35,14 @@
}
@Override
- public void perform(RemoteHoldemPlayerContext context) {
+ public void perform(RemoteHoldemPlayerContext context) throws
RemoteException, IllegalActionException {
context.fold();
}
+
+ @Override
+ public GameState getUnwrappedStateAfterAction() {
+ return new FoldState(gameState, new FoldEvent(actor));
+ }
@Override
public GameState getStateAfterAction() throws GameEndedException,
DefaultWinnerException {
@@ -68,7 +74,7 @@
roundEnds = false;
}
- FoldState foldState = new FoldState(gameState, new FoldEvent(actor));
+ GameState foldState = getUnwrappedStateAfterAction();
if (!roundEnds) {
return new NextPlayerState(foldState, new
NextPlayerEvent(foldState.getNextActivePlayerAfter(actor).getPlayerId()));
=======================================
--- /src/bots/mctsbot/ai/bots/bot/gametree/action/RaiseAction.java Sun Nov
7 06:35:47 2010
+++ /src/bots/mctsbot/ai/bots/bot/gametree/action/RaiseAction.java Wed Dec
8 08:36:14 2010
@@ -15,6 +15,8 @@
*/
package bots.mctsbot.ai.bots.bot.gametree.action;
+import java.rmi.RemoteException;
+
import bots.mctsbot.client.common.gamestate.GameState;
import bots.mctsbot.client.common.gamestate.modifiers.AllInState;
import bots.mctsbot.client.common.gamestate.modifiers.NextPlayerState;
@@ -37,12 +39,12 @@
}
@Override
- public void perform(RemoteHoldemPlayerContext context) {
+ public void perform(RemoteHoldemPlayerContext context) throws
RemoteException, IllegalActionException {
context.betOrRaise(amount);
}
@Override
- public GameState getStateAfterAction() {
+ public GameState getUnwrappedStateAfterAction() {
PlayerState actorState = gameState.getPlayer(actor);
int stack = actorState.getStack();
int oldBet = actorState.getBet();
@@ -56,6 +58,12 @@
} else {
raiseState = new RaiseState(gameState, new RaiseEvent(actor, amount,
movedAmount));
}
+ return raiseState;
+ }
+
+ @Override
+ public GameState getStateAfterAction() {
+ GameState raiseState = getUnwrappedStateAfterAction();
return new NextPlayerState(raiseState, new
NextPlayerEvent(raiseState.getNextActivePlayerAfter(actor).getPlayerId()));
}
=======================================
--- /src/bots/mctsbot/ai/bots/bot/gametree/mcts/FixedSampleMCTSBot.java Wed
Dec 8 02:17:51 2010
+++ /src/bots/mctsbot/ai/bots/bot/gametree/mcts/FixedSampleMCTSBot.java Wed
Dec 8 08:36:14 2010
@@ -17,8 +17,6 @@
import java.rmi.RemoteException;
-import org.apache.log4j.Logger;
-
import bots.mctsbot.ai.bots.bot.AbstractBot;
import bots.mctsbot.ai.bots.bot.gametree.action.IllegalActionException;
import bots.mctsbot.ai.bots.bot.gametree.mcts.listeners.MCTSListener;
@@ -32,7 +30,6 @@
public class FixedSampleMCTSBot extends AbstractBot {
- private final static Logger logger =
Logger.getLogger(FixedSampleMCTSBot.class);
private final Config config;
private final MCTSListener.Factory[] MCTSlistenerFactories;
private final int samplesPreFlop;
=======================================
---
/src/bots/mctsbot/ai/bots/bot/gametree/mcts/FixedSampleMCTSBotFactory.java
Sun Nov 7 06:35:47 2010
+++
/src/bots/mctsbot/ai/bots/bot/gametree/mcts/FixedSampleMCTSBotFactory.java
Wed Dec 8 08:36:14 2010
@@ -70,7 +70,7 @@
public Bot createBot(final PlayerId botId, GameStateContainer
gameStateContainer, RemoteHoldemPlayerContext playerContext) {
copies++;
- OpponentModel opponentModel = opponentModelFactory.create();
+ OpponentModel opponentModel = opponentModelFactory.create(botId);
Config config = new Config(opponentModel, showdownNodeFactory,
decisionNodeSelectionStrategy, opponentNodeSelectionStrategy,
moveSelectionStrategy,
backPropStratFactory, sampler);
=======================================
--- /src/bots/mctsbot/ai/bots/bot/gametree/mcts/MCTSBot.java Tue May 18
12:39:11 2010
+++ /src/bots/mctsbot/ai/bots/bot/gametree/mcts/MCTSBot.java Wed Dec 8
08:36:14 2010
@@ -15,9 +15,12 @@
*/
package bots.mctsbot.ai.bots.bot.gametree.mcts;
+import java.rmi.RemoteException;
+
import org.apache.log4j.Logger;
import bots.mctsbot.ai.bots.bot.AbstractBot;
+import bots.mctsbot.ai.bots.bot.gametree.action.IllegalActionException;
import bots.mctsbot.ai.bots.bot.gametree.action.SearchBotAction;
import bots.mctsbot.ai.bots.bot.gametree.mcts.listeners.MCTSListener;
import bots.mctsbot.ai.bots.bot.gametree.mcts.nodes.Config;
@@ -44,6 +47,10 @@
this.MCTSlistenerFactories = MCTSlisteners;
this.decisionTime = decisionTime;
}
+
+ public Config getConfig() {
+ return config;
+ }
@Override
public void doNextAction() {
@@ -88,12 +95,23 @@
iterate(root);
iterate(root);
} while (System.currentTimeMillis() < endTime);
+ INode node = root.selectChild(config.getMoveSelectionStrategy());
+ config.getModel().setChosenNode(node);
// if (printed && tableContext.getGameState().getRound() == r)
// printed = false;
- SearchBotAction action =
root.selectChild(config.getMoveSelectionStrategy()).getLastAction().getAction();
+ SearchBotAction action = node.getLastAction().getAction();
+
if (logger.isInfoEnabled())
logger.info("Stopped MCTS after " + root.getNbSamples() + " samples and
choosing " + action);
- action.perform(playerContext);
+ try {
+ action.perform(playerContext);
+ } catch (RemoteException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IllegalActionException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
MCTSListener[] listeners =
createListeners(gameStateContainer.getGameState(), botId);
for (MCTSListener listener : listeners) {
listener.onMCTS(root);
@@ -133,7 +151,6 @@
private MCTSListener[] createListeners(GameState gameState, PlayerId
actor) {
MCTSListener[] listeners = new
MCTSListener[MCTSlistenerFactories.length];
for (int i = 0; i < MCTSlistenerFactories.length; i++) {
- System.out.println((i + 1) + " listener");
listeners[i] = MCTSlistenerFactories[i].create(gameState, actor);
}
return listeners;
=======================================
--- /src/bots/mctsbot/ai/bots/bot/gametree/mcts/MCTSBotFactory.java Sun
Nov 7 06:35:47 2010
+++ /src/bots/mctsbot/ai/bots/bot/gametree/mcts/MCTSBotFactory.java Wed
Dec 8 08:36:14 2010
@@ -60,7 +60,7 @@
}
public Bot createBot(final PlayerId botId, GameStateContainer
gameStateContainer, RemoteHoldemPlayerContext playerContext) {
- OpponentModel opponentModel = opponentModelFactory.create();
+ OpponentModel opponentModel = opponentModelFactory.create(botId);
Config config = new Config(opponentModel, showdownNodeFactory,
decisionNodeSelectionStrategy, opponentNodeSelectionStrategy,
moveSelectionStrategy,
backPropStratFactory, sampler);
=======================================
--- /src/bots/mctsbot/ai/bots/bot/gametree/mcts/MCTSMeerkatBot.java Sun
Nov 7 06:35:47 2010
+++ /src/bots/mctsbot/ai/bots/bot/gametree/mcts/MCTSMeerkatBot.java Wed
Dec 8 08:36:14 2010
@@ -19,6 +19,7 @@
import
bots.mctsbot.ai.bots.bot.gametree.mcts.strategies.selection.SamplingToFunctionSelector;
import
bots.mctsbot.ai.bots.bot.gametree.mcts.strategies.selection.UCTSelector;
import
bots.mctsbot.ai.bots.bot.gametree.search.expander.sampling.StochasticUniversalSampler;
+import bots.mctsbot.ai.opponentmodels.weka.WekaOptions;
import bots.mctsbot.ai.opponentmodels.weka.WekaRegressionModelFactory;
import bots.mctsbot.client.common.GameStateContainer;
import bots.mctsbot.client.common.gamestate.DetailedHoldemTableState;
@@ -128,8 +129,12 @@
// 2000, // thinking time
// listeners.toArray(new MCTSListener.Factory[0]));
+ //TODO: check WekaOptions
+ WekaOptions config = new WekaOptions();
+ config.setUseOnlineLearning(true);
+
botFactory = new MCTSBotFactory("MCTSBot", //
-
WekaRegressionModelFactory.createForZip("bots/mctsbot/ai/opponentmodels/weka/models/model1.zip"),//
+
WekaRegressionModelFactory.createForZip("bots/mctsbot/ai/opponentmodels/weka/models/model1.zip",
config),//
new SamplingToFunctionSelector(20, new UCTSelector(50000)), //
decisionSelection
new SamplingSelector(),// opponentSelection
new MaxValueSelector(),// moveSelection
=======================================
--- /src/bots/mctsbot/ai/bots/bot/gametree/search/BotActionNode.java Sun
Nov 7 06:35:47 2010
+++ /src/bots/mctsbot/ai/bots/bot/gametree/search/BotActionNode.java Wed
Dec 8 08:36:14 2010
@@ -15,11 +15,13 @@
*/
package bots.mctsbot.ai.bots.bot.gametree.search;
+import java.rmi.RemoteException;
import java.util.List;
import org.apache.log4j.Logger;
import bots.mctsbot.ai.bots.bot.gametree.action.ActionWrapper;
+import bots.mctsbot.ai.bots.bot.gametree.action.IllegalActionException;
import bots.mctsbot.ai.bots.bot.gametree.search.expander.TokenExpander;
import bots.mctsbot.ai.bots.bot.gametree.search.expander.sampling.Sampler;
import bots.mctsbot.ai.bots.bot.gametree.search.nodevisitor.NodeVisitor;
@@ -54,7 +56,15 @@
// for (NodeVisitor visitor : visitors) {
// visitor.leaveNode(bestEvaluatedAction);
// }
- best.getLeft().getAction().perform(context);
+ try {
+ best.getLeft().getAction().perform(context);
+ } catch (RemoteException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IllegalActionException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
}
public Triple<ActionWrapper, GameTreeNode, Distribution>
getBestEvaluatedAction(double lowerBound) {
=======================================
--- /src/bots/mctsbot/ai/bots/bot/gametree/search/SearchBotFactory.java Sun
Nov 7 06:35:47 2010
+++ /src/bots/mctsbot/ai/bots/bot/gametree/search/SearchBotFactory.java Wed
Dec 8 08:36:14 2010
@@ -75,7 +75,7 @@
OpponentModel opponentModel = opponentModels.get(botId);
if (opponentModel == null) {
- opponentModel = modelFactory.create();
+ opponentModel = modelFactory.create(botId);
opponentModels.put(botId, opponentModel);
}
SearchConfiguration config = new SearchConfiguration(opponentModel,
showdownNodeFactory, new SamplingExpander.Factory(), sampler, preflopTokens,
=======================================
--- /src/bots/mctsbot/ai/opponentmodels/simple/HistogramModel.java Sun Nov
7 06:35:47 2010
+++ /src/bots/mctsbot/ai/opponentmodels/simple/HistogramModel.java Wed Dec
8 08:36:14 2010
@@ -17,6 +17,8 @@
import java.util.concurrent.ConcurrentHashMap;
+import net.jcip.annotations.NotThreadSafe;
+import bots.mctsbot.ai.bots.bot.gametree.mcts.nodes.INode;
import bots.mctsbot.ai.opponentmodels.OpponentModel;
import bots.mctsbot.client.common.gamestate.DetailedHoldemTableState;
import bots.mctsbot.client.common.gamestate.GameState;
@@ -45,6 +47,7 @@
import bots.mctsbot.common.util.Pair;
import bots.mctsbot.common.util.Triple;
+@NotThreadSafe
public class HistogramModel implements OpponentModel, GameStateVisitor {
private final ConcurrentHashMap<Pair<PlayerId, Round>,
PlayerRoundHistogram> opponentModels = new ConcurrentHashMap<Pair<PlayerId,
Round>, PlayerRoundHistogram>();
@@ -85,24 +88,21 @@
opponentModels.put(new Pair<PlayerId, Round>(player, Round.PREFLOP), new
PlayerRoundHistogram(10, 1, 11,
(int) Math.round(37556539.0 / 53203232.0 * 10), (int)
Math.round(7410418.0 / 53203232.0 * 10), (int) Math.round(8236275.0 /
53203232.0 * 10),
(int) (Math.round(37556539.0 / 53203232.0 * 10) + Math.round(7410418.0
/ 53203232.0 * 10) + Math.round(8236275.0 / 53203232.0 * 10))));
- opponentModels.put(
- new Pair<PlayerId, Round>(player, Round.FLOP),
- new PlayerRoundHistogram((int) Math.round(5643188.0 / 9067525.0 * 10),
(int) Math.round(3424337.0 / 9067525.0 * 10), (int) (Math
- .round(5643188.0 / 9067525.0 * 10) + Math.round(3424337.0 /
9067525.0 * 10)), (int) Math.round(3012394.0 / 5085650.0 * 10), (int) Math
- .round(1493533.0 / 5085650.0 * 10), (int) Math.round(579723.0 /
5085650.0 * 10), (int) (Math.round(3012394.0 / 5085650.0 * 10)
- + Math.round(1493533.0 / 5085650.0 * 10) + Math.round(579723.0 /
5085650.0 * 10))));
- opponentModels.put(
- new Pair<PlayerId, Round>(player, Round.TURN),
- new PlayerRoundHistogram((int) Math.round(2969602.0 / 4635236.0 * 10),
(int) Math.round(1665634.0 / 4635236.0 * 10), (int) (Math
- .round(2969602.0 / 4635236.0 * 10) + Math.round(1665634.0 /
4635236.0 * 10)), (int) Math.round(1152214.0 / 2172745.0 * 10), (int) Math
- .round(814117.0 / 2172745.0 * 10), (int) Math.round(206414.0 /
2172745.0 * 10), (int) (Math.round(1152214.0 / 2172745.0 * 10)
- + Math.round(814117.0 / 2172745.0 * 10) + Math.round(206414.0 /
2172745.0 * 10))));
- opponentModels.put(
- new Pair<PlayerId, Round>(player, Round.FINAL),
- new PlayerRoundHistogram((int) Math.round(1863381.0 / 2843076.0 * 10),
(int) Math.round(979695.0 / 2843076.0 * 10), (int) (Math
- .round(1863381.0 / 2843076.0 * 10) + Math.round(979695.0 / 2843076.0
* 10)), (int) Math.round(653301.0 / 1150533.0 * 10), (int) Math
- .round(407975.0 / 1150533.0 * 10), (int) Math.round(89257.0 /
1150533.0 * 10), (int) (Math.round(653301.0 / 1150533.0 * 10)
- + Math.round(407975.0 / 1150533.0 * 10) + Math.round(89257.0 /
1150533.0 * 10))));
+ opponentModels.put(new Pair<PlayerId, Round>(player, Round.FLOP), new
PlayerRoundHistogram((int) Math.round(5643188.0 / 9067525.0 * 10), (int)
Math
+ .round(3424337.0 / 9067525.0 * 10), (int) (Math.round(5643188.0 /
9067525.0 * 10) + Math.round(3424337.0 / 9067525.0 * 10)), (int) Math
+ .round(3012394.0 / 5085650.0 * 10), (int) Math.round(1493533.0 /
5085650.0 * 10), (int) Math.round(579723.0 / 5085650.0 * 10), (int) (Math
+ .round(3012394.0 / 5085650.0 * 10)
+ + Math.round(1493533.0 / 5085650.0 * 10) + Math.round(579723.0 /
5085650.0 * 10))));
+ opponentModels.put(new Pair<PlayerId, Round>(player, Round.TURN), new
PlayerRoundHistogram((int) Math.round(2969602.0 / 4635236.0 * 10), (int)
Math
+ .round(1665634.0 / 4635236.0 * 10), (int) (Math.round(2969602.0 /
4635236.0 * 10) + Math.round(1665634.0 / 4635236.0 * 10)), (int) Math
+ .round(1152214.0 / 2172745.0 * 10), (int) Math.round(814117.0 /
2172745.0 * 10), (int) Math.round(206414.0 / 2172745.0 * 10), (int) (Math
+ .round(1152214.0 / 2172745.0 * 10)
+ + Math.round(814117.0 / 2172745.0 * 10) + Math.round(206414.0 /
2172745.0 * 10))));
+ opponentModels.put(new Pair<PlayerId, Round>(player, Round.FINAL), new
PlayerRoundHistogram((int) Math.round(1863381.0 / 2843076.0 * 10), (int)
Math
+ .round(979695.0 / 2843076.0 * 10), (int) (Math.round(1863381.0 /
2843076.0 * 10) + Math.round(979695.0 / 2843076.0 * 10)), (int) Math
+ .round(653301.0 / 1150533.0 * 10), (int) Math.round(407975.0 /
1150533.0 * 10), (int) Math.round(89257.0 / 1150533.0 * 10), (int) (Math
+ .round(653301.0 / 1150533.0 * 10)
+ + Math.round(407975.0 / 1150533.0 * 10) + Math.round(89257.0 /
1150533.0 * 10))));
}
private void forgetModelsFor(PlayerId player) {
@@ -117,6 +117,16 @@
gameState.acceptHistoryVisitor(this, lastKnownState);
lastKnownState = gameState;
}
+
+ @Override
+ public OpponentModel clone() {
+ HistogramModel hist = new HistogramModel();
+ hist.opponentModels.putAll(this.opponentModels);
+ hist.lastKnownState = this.lastKnownState;
+ hist.round = this.round;
+ hist.started = this.started;
+ return hist;
+ }
@Override
public void visitAllInState(AllInState allInState) {
@@ -242,5 +252,20 @@
public void visitConfigChangeState(ConfigChangeState configChangeState) {
}
+
+ @Override
+ public void setChosenNode(INode node) {
+
+ }
+
+ @Override
+ public INode getChosenNode() {
+ return null;
+ }
+
+ @Override
+ public PlayerId getBotId() {
+ return null;
+ }
}
=======================================
--- /src/bots/mctsbot/ai/opponentmodels/simple/HistogramModelFactory.java
Sun Nov 7 06:35:47 2010
+++ /src/bots/mctsbot/ai/opponentmodels/simple/HistogramModelFactory.java
Wed Dec 8 08:36:14 2010
@@ -16,12 +16,12 @@
package bots.mctsbot.ai.opponentmodels.simple;
import bots.mctsbot.ai.opponentmodels.OpponentModel;
+import bots.mctsbot.common.elements.player.PlayerId;
public class HistogramModelFactory implements OpponentModel.Factory {
@Override
- public OpponentModel create() {
+ public OpponentModel create(PlayerId botId) {
return new HistogramModel();
}
-
-}
+}
=======================================
--- /src/bots/mctsbot/ai/opponentmodels/weka/ARFFFile.java Tue Nov 23
08:42:27 2010
+++ /src/bots/mctsbot/ai/opponentmodels/weka/ARFFFile.java Wed Dec 8
08:36:14 2010
@@ -1,6 +1,9 @@
package bots.mctsbot.ai.opponentmodels.weka;
import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
@@ -19,10 +22,12 @@
public class ARFFFile {
private final String nl = InstancesBuilder.nl;
- private final String path;
- private final Object player;
+ private final File path;
+
private final String name;
+ private File arffFile;
+
private Writer file;
private long count = 0;
private WekaOptions config;
@@ -35,17 +40,23 @@
public ARFFFile(String path, Object player, String name, String
attributes, WekaOptions config) throws Exception {
// if (name.equals("PreFoldCallRaise.arff")) echo = true;
- this.path = path;
- this.player = player;
+ String playerPath = player.toString().replace("\\", "").replace("/", "");
+ this.path = new File(path, playerPath);
this.name = name;
+
this.config = config;
// TODO: false => !config.arffOverwrite()
- file = new BufferedWriter(new FileWriter(path + player + name, false));
+ arffFile = new File(this.path, "/arff/" + name);
+ if (!arffFile.getParentFile().exists()) {
+ arffFile.getParentFile().mkdirs();
+ }
+
+ file = new BufferedWriter(new FileWriter(arffFile, false));
file.write(attributes);
file.flush();
- DataSource source = new DataSource(path + player + name);
+ DataSource source = new DataSource(new FileInputStream(arffFile));
instances = source.getDataSet();
// make it clean
instances.delete();
@@ -238,7 +249,7 @@
if (config.solveConceptDrift())
data = instances;
else {
- DataSource source = new DataSource(path + player + name);
+ DataSource source = new DataSource(new FileInputStream(arffFile));
data = source.getDataSet();
}
if (rmAttributes.length > 0) {
@@ -270,8 +281,15 @@
// System.out.println(cl);
// save model + header
- if (config.modelPersistency())
- SerializationHelper.write(path + "../" + player + fileName + ".model",
cl);
+ // save model + header
+ if (config.modelPersistency()) {
+ File modelFile = new File(this.path, "/model/" + fileName + ".model");
+ if (!modelFile.getParentFile().exists()) {
+ modelFile.getParentFile().mkdirs();
+ }
+
+ SerializationHelper.write(new FileOutputStream(modelFile), cl);
+ }
return cl;
}
=======================================
--- /src/bots/mctsbot/ai/opponentmodels/weka/ARFFPlayer.java Tue Nov 23
08:42:27 2010
+++ /src/bots/mctsbot/ai/opponentmodels/weka/ARFFPlayer.java Wed Dec 8
08:36:14 2010
@@ -13,8 +13,6 @@
private final static Logger logger = Logger.getLogger(ARFFPlayer.class);
- private final String folder
= "../../src/main/resources/org/cspoker/ai/opponentmodels/weka/models/arff/";
-
private final Object player;
private ARFFFile preCheckBetFile;
@@ -50,7 +48,7 @@
throw new IOException("Cannot find location for ARFFFiles");
}
}
- String path = f.getAbsolutePath();
+ String path = "./data/mctsbot/";
// End new code
// String path = (getClass().getProtectionDomain().getCodeSource()
// .getLocation().getPath() + folder).replace("%20", " ");
=======================================
--- /src/bots/mctsbot/ai/opponentmodels/weka/PlayerTrackingVisitor.java Tue
Nov 23 08:42:27 2010
+++ /src/bots/mctsbot/ai/opponentmodels/weka/PlayerTrackingVisitor.java Wed
Dec 8 08:36:14 2010
@@ -43,7 +43,7 @@
import bots.mctsbot.client.common.playerstate.PlayerState;
import bots.mctsbot.common.elements.table.Round;
-import com.biotools.meerkat.Card;
+import com.biotools.meerkat.Hand;
public class PlayerTrackingVisitor implements GameStateVisitor, Cloneable {
@@ -191,11 +191,10 @@
@Override
public void visitShowHandState(ShowHandState showHandState) {
- Card[] cardset = new Card[] {};
- cardset =
showHandState.getLastEvent().getShowdownPlayer().getHandCards().toArray(cardset);
- logger.trace("(" +
showHandState.getPlayer(showHandState.getLastEvent().getShowdownPlayer().getPlayerId()).getName()
+ ") ShowHandState: " + cardset[0]
- + ", " + cardset[1]);
-
propz.signalCardShowdown(showHandState.getLastEvent().getShowdownPlayer().getPlayerId(),
cardset[0], cardset[1]);
+ Hand cardset =
showHandState.getLastEvent().getShowdownPlayer().getHandCards();
+ logger.trace("(" +
showHandState.getPlayer(showHandState.getLastEvent().getShowdownPlayer().getPlayerId()).getName()
+ ") ShowHandState: "
+ + cardset.getCardIndex(1) + ", " + cardset.getCard(2));
+
propz.signalCardShowdown(showHandState.getLastEvent().getShowdownPlayer().getPlayerId(),
cardset.getCard(1), cardset.getCard(2));
}
@Override
=======================================
---
/src/bots/mctsbot/client/common/gamestate/modifiers/NewPocketCardsState.java
Sat Nov 27 02:53:21 2010
+++
/src/bots/mctsbot/client/common/gamestate/modifiers/NewPocketCardsState.java
Wed Dec 8 08:36:14 2010
@@ -16,7 +16,6 @@
package bots.mctsbot.client.common.gamestate.modifiers;
import java.util.ArrayList;
-import java.util.EnumSet;
import java.util.List;
import bots.mctsbot.client.common.gamestate.ForwardingGameState;
@@ -28,7 +27,7 @@
import
bots.mctsbot.common.api.lobby.holdemtable.holdemplayer.event.NewPocketCardsEvent;
import bots.mctsbot.common.elements.player.PlayerId;
-import com.biotools.meerkat.Card;
+import com.biotools.meerkat.Hand;
public class NewPocketCardsState extends ForwardingGameState {
@@ -43,7 +42,7 @@
this.playerState = new ForwardingPlayerState(super.getPlayer(playerId)) {
@Override
- public EnumSet<Card> getCards() {
+ public Hand getCards() {
return NewPocketCardsState.this.event.getPocketCards();
}
@@ -78,7 +77,7 @@
};
}
- public EnumSet<Card> getPlayerCards() {
+ public Hand getPlayerCards() {
return playerState.getCards();
}
==============================================================================
Revision: 46fc7fea811c
Author: thijs
Date: Tue Mar 29 00:27:29 2011
Log: own consolestarter
http://code.google.com/p/opentestbed/source/detail?r=46fc7fea811c
Added:
/src/MyCashGameConsoleStarter.java
Modified:
/src/bots/mctsbot/ai/bots/bot/gametree/mcts/MCTSMeerkatBot.java
=======================================
--- /dev/null
+++ /src/MyCashGameConsoleStarter.java Tue Mar 29 00:27:29 2011
@@ -0,0 +1,58 @@
+import game.CashGameDescription;
+import game.GameIDGenerator;
+import game.GameRunner;
+import game.HandHistoryWriter;
+import game.TableSeater;
+import game.deck.DeckFactory;
+import game.deck.SerializedDeck;
+import game.stats.BankrollGraphUI;
+
+import java.io.FileWriter;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
+
+import bots.BotRepository;
+
+/**
+ * This class starts a simulation on the console and writes a
handhistory-file
+ * to the ./data directory
+ */
+public class MyCashGameConsoleStarter {
+ public static void main(String[] args) throws Exception {
+
+ // number of games
+ int numGames = 1000;
+ // if to permute seats to reduce variance
+ boolean permuteSeats = true;
+ // four Bots fight against each other
+ // valid BotNames can be obtained from the botRepository
+ String[] botNames = new String[]
{ "MCTSBot/MCTSBot", "DemoBot/SimpleBot" };
+
+ BotRepository botRepository = new BotRepository();
+ TableSeater tableSeater = new TableSeater(botRepository, permuteSeats);
+ GameIDGenerator gameIDGenerator = new GameIDGenerator(System.nanoTime());
+ HandHistoryWriter handHistoryWriter = new HandHistoryWriter();
+ String simulationFileName = new
SimpleDateFormat("yyMMdd-hhmm").format(new Date());
+ handHistoryWriter.setWriter(new FileWriter("./data/" +
simulationFileName + "-history.txt"));
+
+ // in the future created via GUI, and persisted via XML to
the ./data/games dir
+ CashGameDescription cashGameDescription = new CashGameDescription();
+ cashGameDescription.setSmallBlind(0.01);
+ cashGameDescription.setBigBlind(0.02);
+ cashGameDescription.setInitialBankRoll(2);
+ cashGameDescription.setNumGames(numGames);
+
+ cashGameDescription.setBotNames(botNames);
+ //cashGameDescription.setInGameNames(new String[] { "Simply #1", "Simply
#2", "Cally #3", "Cally #4" });
+
+ // start the game
+ GameRunner runner = cashGameDescription.createGameRunner();
+ BankrollGraphUI bankrollgraphUI = new BankrollGraphUI();
+ runner.addBankrollObserver(bankrollgraphUI);
+ DeckFactory deckFactory =
SerializedDeck.createFactory("./data/decks/deck-100000.deck");
+ runner.runGame(deckFactory, tableSeater, gameIDGenerator,
Arrays.asList(handHistoryWriter));
+
+ bankrollgraphUI.createGraph(simulationFileName);
+ }
+}
=======================================
--- /src/bots/mctsbot/ai/bots/bot/gametree/mcts/MCTSMeerkatBot.java Wed
Dec 8 08:36:14 2010
+++ /src/bots/mctsbot/ai/bots/bot/gametree/mcts/MCTSMeerkatBot.java Tue Mar
29 00:27:29 2011
@@ -17,7 +17,7 @@
import
bots.mctsbot.ai.bots.bot.gametree.mcts.strategies.selection.MaxValueSelector;
import
bots.mctsbot.ai.bots.bot.gametree.mcts.strategies.selection.SamplingSelector;
import
bots.mctsbot.ai.bots.bot.gametree.mcts.strategies.selection.SamplingToFunctionSelector;
-import
bots.mctsbot.ai.bots.bot.gametree.mcts.strategies.selection.UCTSelector;
+import
bots.mctsbot.ai.bots.bot.gametree.mcts.strategies.selection.WeightedUCTSelector;
import
bots.mctsbot.ai.bots.bot.gametree.search.expander.sampling.StochasticUniversalSampler;
import bots.mctsbot.ai.opponentmodels.weka.WekaOptions;
import bots.mctsbot.ai.opponentmodels.weka.WekaRegressionModelFactory;
@@ -135,7 +135,7 @@
botFactory = new MCTSBotFactory("MCTSBot", //
WekaRegressionModelFactory.createForZip("bots/mctsbot/ai/opponentmodels/weka/models/model1.zip",
config),//
- new SamplingToFunctionSelector(20, new UCTSelector(50000)), //
decisionSelection
+ new SamplingToFunctionSelector(20, new
WeightedUCTSelector(108.6957)), // decisionSelection
new SamplingSelector(),// opponentSelection
new MaxValueSelector(),// moveSelection
new MCTSBucketShowdownNode.Factory(), // showdown evaluation