/**
* 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.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;
import bots.mctsbot.client.common.gamestate.CachingNode;
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.util.Pair;
import bots.mctsbot.common.util.Triple;
public class BotActionNode extends ActionNode {
@SuppressWarnings("unused")
private final static Logger logger = Logger.getLogger(BotActionNode.class);
private final TokenExpander expander;
private Triple<ActionWrapper, GameTreeNode, Distribution> best = null;
public BotActionNode(PlayerId botId, GameState gameState, SearchConfiguration config, Sampler sampler, int tokens, int searchId, NodeVisitor... visitors) {
super(botId, botId, new CachingNode(gameState), config, searchId, visitors);
expander = config.getBotNodeExpanderFactory().create(this, tokens, sampler);
}
@Override
public Distribution getValueDistribution(double lowerBound) {
getBestEvaluatedAction(lowerBound);
return best.getRight();
}
public void performbestAction(RemoteHoldemPlayerContext context) {
getBestEvaluatedAction(0.0);
// for (NodeVisitor visitor : visitors) {
// visitor.leaveNode(bestEvaluatedAction);
// }
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) {
if (best == null) {
double maxEv = Double.NEGATIVE_INFINITY;
config.getOpponentModel().assumeTemporarily(gameState);
List<Pair<ActionWrapper, GameTreeNode>> children = getExpander().getChildren(config.isUniformBotActionTokens());
for (int i = 0; i < children.size(); i++) {
Pair<ActionWrapper, GameTreeNode> pair = children.get(i);
GameTreeNode child = pair.getRight();
double upperWinBound = child.getUpperWinBound();
double nextLowerBound = Math.max(lowerBound, maxEv);
if (config.isUseAlphaBetaPruning() && upperWinBound < nextLowerBound) {
//prune
Distribution distribution = new Distribution(upperWinBound, 0, true);
if (upperWinBound > maxEv) {
//take the best insufficient child as an upper bound
maxEv = upperWinBound;
best = new Triple<ActionWrapper, GameTreeNode, Distribution>(pair.getLeft(), pair.getRight(), distribution);
}
for (NodeVisitor visitor : visitors) {
visitor.pruneSubTree(pair, distribution, nextLowerBound);
}
continue;
}
for (NodeVisitor visitor : visitors) {
visitor.enterNode(pair, nextLowerBound);
}
Distribution valueDistribution = child.getValueDistribution(nextLowerBound);
for (NodeVisitor visitor : visitors) {
visitor.leaveNode(pair, valueDistribution);
}
if (valueDistribution.getMean() > maxEv) {
maxEv = valueDistribution.getMean();
best = new Triple<ActionWrapper, GameTreeNode, Distribution>(pair.getLeft(), pair.getRight(), valueDistribution);
}
}
if (best == null) {
throw new IllegalStateException();
}
config.getOpponentModel().forgetLastAssumption();
}
return best;
}
protected TokenExpander getExpander() {
return expander;
}
public int getNbTokens() {
return expander.tokens;
}
@Override
public String toString() {
return "Bot Action Node";
}
}