現在、ボードゲームのAIを書いていますHex。私はMonte-Carlo-Tree-Searchを使ってそれを実装し、すでに実装しようとしています。しかし、AIは信じられないほど馬鹿な(ランダムな)動きをして、なぜ動作しないのか分かりません。モンテカルロツリー検索が機能しない
import java.util.ArrayList;
import java.util.Random;
/**
* Created by Robin on 18.03.2017.
*/
public class TreeNode {
private static final Random random = new Random();
private static final double epsion=10e-5;
protected double nvisits;
protected double totValue;
protected int move=-1;
private HexBoard board;
protected ArrayList<TreeNode>children ;
public TreeNode(HexBoard board){
this.board =board;
}
//Copy-Constructor
public TreeNode(TreeNode treeNode){
this.nvisits=treeNode.nvisits;
this.totValue=treeNode.totValue;
this.move=treeNode.move;
this.board = new HexBoard(treeNode.board);
}
public void update(double value){
totValue+=value*board.color;
nvisits++;
}
public void expand(){
assert(children==null);
children = new ArrayList<>(121-board.moveCount);
for(int i=0;i<121;i++){
if(board.board[i]!=HexBoard.EMPTY)
continue;
TreeNode newNode = new TreeNode(board);
newNode.move =i;
children.add(newNode);
}
}
public void calculateIteration(){
ArrayList<TreeNode>visited = new ArrayList<>();
TreeNode current =this;
visited.add(current);
while(!current.isLeafNode()){
current =current.select();
board.makeMove(current.move);
visited.add(current);
}
//Found a leaf node
double value;
if(current.board.getWinner()==0){
current.expand();
TreeNode newNode =current.select();
value =playOut(newNode.board);
}else{
value =current.board.getWinner();
}
//update all the nodes
for(int i=1;i<visited.size();i++){
visited.get(i).update(value);
board.undoMove(visited.get(i).move);
}
visited.get(0).update(value);
}
public static int playOut(HexBoard board){
int winner=0;
if(board.moveCount==121) {
winner=board.getWinner();
return winner;
}
//Checking-Movecount vs actual stones on the board
final double left =121-board.moveCount;
double probibility =1/left;
double summe =0;
double p =random.nextDouble();
int randomMove =0;
for(int i=0;i<121;i++){
if(board.board[i]!=HexBoard.EMPTY)
continue;
summe+=probibility;
if(p<=summe && probibility!=0) {
randomMove = i;
break;
}
}
board.makeMove(randomMove);
winner =playOut(board);
board.undoMove(randomMove);
return winner;
}
public TreeNode select(){
TreeNode bestNode=null;
double bestValue =-10000000;
for(TreeNode node : children){
double uctvalue =(node.nvisits==0)?100000:(node.totValue/(node.nvisits)+Math.sqrt((Math.log(this.nvisits))/(2*node.nvisits)));
uctvalue+=epsion*random.nextDouble();
if(uctvalue>bestValue){
bestValue=uctvalue;
bestNode =node;
}
}
return bestNode;
///
}
public boolean isLeafNode(){
return (children==null);
}
}
calcualteIteration()メソッド内の実装は正しいですか?
私はこれを見て非常に魅力的な問題ではないかもしれません知っているが、私は
これは広すぎます。これをより簡単な問題と[最小限のテストケース](https://stackoverflow.com/help/mcve)に絞り込むためにデバッグを行ってください。 –
あなたはどのプレイヤーがどの動きをしたかを実際に把握していますか?あなたは反復の中でターンを交互にしますか?私にはちょうど現プレーヤーがあなたのシミュレーション内でボード全体を埋めるようにしているように見えますが、それは相手がいないというふうに思っています。それとも私は何かが恋しい?また、あなたが実行しているシミュレーションの数を教えて、実際のゲームでどのゲームをプレイするかを最終的に決める方法を教えてください。 –
申し訳ありませんが、私はこれを明確にすべきでした。 board.makemove()関数は2人のプレーヤーを交互に切り替えます。私は100-50000のシミュレーションからすべてを試してみました。結果はほぼ同じでした(悪いランダムな動き)。ルートノードの "ベスト"兄弟は、最も高いuct値を持つもので、AIによって再生されます。 – CheckersGuy