public GameTree MiniMax(GameTree tree, eStoneType player, int depth) { if (depth == 0) { // 自分自身を返す return tree; } else if (tree.GetEnableMoveNodes().Count == 0) // ゲーム終了 { return tree; } // 本来置きたい手を置く場合は最も評価値の高い手を // 相手の手を置く場合は最も低い手を選ぶ bool to_max = (player == tree.StoneType); int top_value = 0; const int inf = (int)(1e9 + 7); if (to_max) top_value = -inf; else top_value = inf; Dictionary<int, List<GameTree>> dict = new Dictionary<int, List<GameTree>>(); foreach (var node in tree.GetEnableMoveNodes()) { int value = MiniMax(node, player, depth - 1).GetScoreDiff(); if (player == eStoneType.White) value *= -1; if (to_max) { if (value > top_value) { top_value = value; dict.Add(value, new List<GameTree>()); } if (value == top_value) { dict[value].Add(node); } } else { if (value < top_value) { top_value = value; dict.Add(value, new List<GameTree>()); } if (value == top_value) { dict[value].Add(node); } } } // 最も良いやつからランダム int n = dict[top_value].Count; return dict[top_value][Random.Range(0, n)]; }
// 実際にシミュレーションする 勝ち 1 引き分け 0.5 負け 0 // 自分相手の手はランダム public float SimulateRandomPlay(eStoneType player) { GameTree node = GameTree; int n = node.GetEnableMoveNodes().Count; while (n != 0) { node = new GameTree(node.GetEnableMoveNodes()[Random.Range(0, n)]); n = node.GetEnableMoveNodes().Count; } int ret = ReversiUtils.JudgeResult(node.Board); if (player == eStoneType.White) ret *= -1; return ret / 2f + 0.5f; }
private int SimulateRandomPlay(GameTree tree, eStoneType player) { GameTree node = tree; int n = node.GetEnableMoveNodes().Count; // ゲームが終了するまでやる while(n != 0) { node = new GameTree(node.GetEnableMoveNodes()[Random.Range(0, n)]); n = node.GetEnableMoveNodes().Count; } int ret = ReversiUtils.JudgeResult(node.Board); if (player == eStoneType.White) ret *= -1; return ret; }
// 未訪問の子ノード private void InitNotVisitChilds() { // 子ノードの順番をランダムに決める int n = NotVisitNum; List<int> order = new List<int>(n); for (int i = 0; i < n; ++i) order.Add(i); for (int i = 0; i < n; ++i) { int tail = n - i - 1; int j = Random.Range(0, tail + 1); int tmp = order[tail]; order[tail] = order[j]; order[j] = tmp; } // 順番通りにキューに入れる var trees = GameTree.GetEnableMoveNodes(); NotVisitChilds = new Queue<Node>(); //string s = ""; for (int i = 0; i < n; ++i) { //s += order[i].ToString(); NotVisitChilds.Enqueue(new Node(trees[order[i]], this)); } //Debug.Log(s); }
// 実際にシミュレーションする 勝ち 1 引き分け 0.5 負け 0 // 相手の手法を引数で渡す public float SimulateSelectedPlay(eStoneType player, BasePlayer opponent) { GameTree node = GameTree; int n = node.GetEnableMoveNodes().Count; while(n != 0) { // 自分の番ならランダムに 相手の番なら指定した手法を用いて考える if(node.StoneType == player) node = new GameTree(node.GetEnableMoveNodes()[Random.Range(0, n)]); else node = opponent.Play(node); n = node.GetEnableMoveNodes().Count; } int ret = ReversiUtils.JudgeResult(node.Board); if (player == eStoneType.White) ret *= -1; return ret / 2f + 0.5f; }
public override GameTree Play(GameTree tree) { int top_value = -10000; Dictionary<int, List<GameTree>> dict = new Dictionary<int, List<GameTree>>(); // 勝った数で比較 foreach(var node in tree.GetEnableMoveNodes()) { int value = 0; for (int i = 0; i < trial_num_; ++i) value += SimulateRandomPlay(node, tree.StoneType); // 勝った数の最大値が複数個あった場合はその中からランダムにできるようにする if(value > top_value) { top_value = value; dict.Add(value, new List<GameTree>()); } if(value == top_value) { dict[value].Add(node); } } int n = dict[top_value].Count; return dict[top_value][Random.Range(0, n)]; }
public override GameTree Play(GameTree tree) { // 最大の取得数の中からランダムにする Dictionary <int, List <GameTree> > dict = new Dictionary <int, List <GameTree> >(); int max_value = -1; foreach (var node in tree.GetEnableMoveNodes()) { int value = ReversiUtils.GetObtainStones(tree.Board, node.PrevPos, tree.StoneType).Count; if (value > max_value) { dict.Add(value, new List <GameTree>()); max_value = value; } if (value == max_value) { dict[value].Add(node); } } int n = dict[max_value].Count; return(dict[max_value][Random.Range(0, n)]); }
public Node(GameTree tree, Node parent) { GameTree = tree; Parent = parent; Childs = new List<Node>(); WinNum = 0; VisitNum = 0; c = Mathf.Sqrt(2); ChildNum = 0; NotVisitNum = tree.GetEnableMoveNodes().Count; child_inited_ = false; }
private GameTree CalcNextNode(GameTree tree) { // パスしかない場合 if (tree.GetEnableMoveNodes().Count == 1) { GameTree head_tree = tree.GetEnableMoveNodes()[0]; if (head_tree.PrevPos == -1) { return(head_tree); } } // マウスの座標はどこか Vector3 pos = Input.mousePosition; pos.z = 10f; pos = Camera.main.ScreenToWorldPoint(pos); // 1.05fずつ pos.x += 1.05f * 4.5f; pos.y += 1.05f * 4.5f; int x = (int)(pos.x / 1.05f + 0.01f); int y = (int)(pos.y / 1.05f + 0.01f); int p = y * 8 + x; foreach (var node in tree.GetEnableMoveNodes()) { if (p == node.PrevPos) { // 置ける return(node); } } return(null); }
private IEnumerator GameFlow() { while (trial_num_ != 0) { // ゲームを初期化 InitGame(); renderer_.Reset(); renderer_.ProcBoard(game_tree_); renderer_.ShowPlayerNames(players_); while (true) { GameTree next_game_tree = null; // 入力を待つ while (next_game_tree == null) { next_game_tree = players_[(int)game_tree_.StoneType - 1].Play(game_tree_); yield return null; } // 現在のノードの更新 game_tree_ = next_game_tree; // 描画情報の更新 renderer_.ProcBoard(game_tree_); // 次の移行先がないなら終了 if (game_tree_.GetEnableMoveNodes().Count == 0) break; yield return new WaitForSeconds(ai_think_time_); } // 勝敗処理 renderer_.ProcResult(); // 終了処理 FinalizeGame(); yield return new WaitForSeconds(0.5f); } }
public override GameTree Play(GameTree tree) { int cnt = tree.GetEnableMoveNodes().Count; return(tree.GetEnableMoveNodes()[Random.Range(0, cnt)]); }