private double DefaultPolicy(MCTS_Node v) { if (v.winner != -1) { if (v.winner == v.myPlayerID) { //Debug.Log(v.myPlayerID + " Me Winner depth: " + v.depth + " index: " + v.tileState.tile.index); return(1); } else { //Debug.Log(v.myPlayerID + " Opponent Winner depth: " + v.depth + " index: " + v.tileState.tile.index); if (this.mode == 0) { return(-1); } else if (this.mode == 2 || this.mode == 3) { return(0); } else if (this.mode == 4) { return(0); } return(-1); } } int[] win = new int[2]; int totalPlay = 0; List <TileState> possibleMoves = new List <TileState>(v.possibleMoves); List <TileState> changed = new List <TileState>(); List <TileState> myTriedMoves = new List <TileState>(); List <TileState> oppTriedMoves = new List <TileState>(); foreach (TileState ts in v.myTiles) { if (ts.currentState == -1) { ts.currentState = v.myPlayerID; changed.Add(ts); } } foreach (TileState ts in v.opponentTiles) { if (ts.currentState == -1) { ts.currentState = 1 - v.myPlayerID; changed.Add(ts); } } int sizeMoves = possibleMoves.Count; //var board = new Dictionary<string, Tile>(grid); for (int i = 0; i < this.totalSimulation; i++) { //possibleMoves = new List<TileState>(v.possibleMoves); //Debug.Log(i + " inner loop, BeginSizeMoves: " + sizeMoves + " nowSizeMoves: " + possibleMoves.Count); foreach (TileState ts in v.myTiles) { ts.initTileSet(); } foreach (TileState ts in v.opponentTiles) { ts.initTileSet(); } foreach (TileState ts in v.possibleMoves) { ts.currentState = -1; ts.initTileSet(); } foreach (var t in v.myTiles) { t.updateTileSet(); } foreach (var t in v.opponentTiles) { t.updateTileSet(); } int currentTurn = v.myPlayerID; int c = 0; while (possibleMoves.Count > 0) { if (++c > 100) { Debug.LogError("Simulation exceeded budget"); return(0); } var move = MovesBank.addRandomMove(possibleMoves); if (move == null) { Debug.Log("Weird! No moves available whereas game is not finised !?"); break; } possibleMoves.Remove(move); if (currentTurn == v.myPlayerID) { v.myTiles.Add(move); myTriedMoves.Add(move); } else { v.opponentTiles.Add(move); oppTriedMoves.Add(move); } //Debug.Log(i + " PossibleMoves size: " + possibleMoves.Count + " myTriedMoves size: " + myTriedMoves.Count + " oppTriedMoves size: " + oppTriedMoves.Count); move.currentState = currentTurn; move.updateTileSet(); //int cl = move.tileSet.GetRoot().chainLength; int cl = 0; int winner = -1; int maxChainLength = 0; if (currentTurn == v.myPlayerID) { foreach (var t in v.myTiles) { if (t.tileSet.GetRoot().chainLength > maxChainLength) { maxChainLength = t.tileSet.GetRoot().chainLength; } } cl = maxChainLength; if (cl >= 7) { winner = v.myPlayerID; } } else { maxChainLength = 0; foreach (var t in v.opponentTiles) { if (t.tileSet.GetRoot().chainLength > maxChainLength) { maxChainLength = t.tileSet.GetRoot().chainLength; } } cl = maxChainLength; if (cl >= 7) { winner = 1 - v.myPlayerID; } } //if (cl >= 7) //{ // if (currentTurn == v.myPlayerID) // winner = v.myPlayerID; // else // winner = 1 - v.myPlayerID; //} //if (possibleMoves.Count == 0) //{ // int chainLength = 0; // if (currentTurn == v.myPlayerID) // { // chainLength = HexGridUtil.evaluate(v.myTiles, v.myPlayerID); // if (chainLength >= 7) // winner = v.myPlayerID; // } // else // { // chainLength = HexGridUtil.evaluate(v.opponentTiles, 1 - v.myPlayerID); // if (chainLength >= 7) // winner = 1 - v.myPlayerID; // } // Debug.LogError("PossibleMoves got to zero, isTerminal? winner: " + winner + " chainlength: " + chainLength + " cl: " + cl + " move.root" + (move.tileSet == move.tileSet.GetRoot())); // Debug.Log("Game: " + i + ", opponentTiles: " + v.opponentTiles.Count + ", myTiles: " + v.myTiles.Count + ", BeginSizeMoves: " + sizeMoves + " PossibleMoves size: " + possibleMoves.Count + " myTriedMoves size: " + myTriedMoves.Count + " oppTriedMoves size: " + oppTriedMoves.Count); //} currentTurn = 1 - currentTurn; //Debug.Log("calc winner: " + winner); if (winner != -1) { totalPlay++; win[winner]++; //Debug.Log("Simulation terminal point: " + winner); break; } } foreach (TileState ts in myTriedMoves) { v.myTiles.Remove(ts); ts.currentState = -1; possibleMoves.Add(ts); } myTriedMoves.Clear(); foreach (TileState ts in oppTriedMoves) { v.opponentTiles.Remove(ts); ts.currentState = -1; possibleMoves.Add(ts); } oppTriedMoves.Clear(); } foreach (TileState ts in changed) { ts.currentState = -1; } if (totalPlay == 0) { return(0); } //return win[v.myPlayerID] / (double)totalPlay; double score = 0; if (this.mode == 0) { score = win[v.myPlayerID] / (double)totalPlay * 1 - win[1 - v.myPlayerID] / (double)totalPlay * 1; } else if (this.mode == 2 || this.mode == 3) { score = win[v.myPlayerID]; } else if (this.mode == 4) { score = win[v.myPlayerID] / (double)totalPlay; } return(score); }
public List <Node> Children(int playerID, int depth, bool randomMoveInLevels) { /* * Defense mechanism * Find Wayout of a blocked column */ children = new List <Node>(); TileState ts = null; #region testmoves //Tile[] testMoves = GameObject.FindObjectOfType<GameController>().testMoves; //if (testMoves.Length > AlphaBeta.testMoveNo - 1) //{ // Tile t = testMoves[AlphaBeta.testMoveNo - 1]; // var s = t.GetComponent<TileState>(); // if (s.currentState == -1) // createNode(s, children, "TestMove " + AlphaBeta.testMoveNo); //} #endregion //ts = MovesBank.BridgeTowardsGoal_Player_2(playerID, this.playerMaxTiles, this.playerMinTiles, this.grid, null, true); //createNode(ts, children, "BridgeSimple: TRUE"); //ts = MovesBank.BridgeTowardsGoal_Player_2(playerID, this.playerMaxTiles, this.playerMinTiles, this.grid, null, false); //createNode(ts, children, "BridgeSimple: False"); //ts = MovesBank.BridgeTowardsGoal(playerID, this.playerMaxTiles, this.playerMinTiles, this.grid, null, true); //createNode(ts, children, "BridgeTowardsGoal: TRUE"); //ts = MovesBank.BridgeTowardsGoal(playerID, this.playerMaxTiles, this.playerMinTiles, this.grid, null, false); //createNode(ts, children, "BridgeTowardsGoal: FALSE"); //ts = MovesBank.maxSafePattern(this.grid, playerID, true); //createNode(ts, children, "maxSafePattern: TRUE"); //ts = MovesBank.maxSafePattern(this.grid, playerID, false); //createNode(ts, children, "maxSafePattern: FALSE"); //if (ts == null && AlphaBeta.testMoveNo > 1) //{ // ts = MovesBank.addRandomMove(this.availableTiles); // createNode(ts, children, "RANDOM"); //} List <TileState> currentTiles = new List <TileState>(this.availableTiles); int totalRandomMoves = 100; if (randomMoveInLevels) { if (depth == 1) { totalRandomMoves = 100; } else if (depth == 2) { totalRandomMoves = 50; } else if (depth == 3) { totalRandomMoves = 10; } else if (depth > 3) { totalRandomMoves = 2; } } for (int i = 0; i < totalRandomMoves; i++) { ts = MovesBank.addRandomMove(currentTiles); currentTiles.Remove(ts); createNode(ts, children, "RANDOM"); } AlphaBeta.TreeSize += children.Count; if (AlphaBeta.MaxTreeSize < AlphaBeta.TreeSize) { AlphaBeta.MaxTreeSize = AlphaBeta.TreeSize; } //Debug.Log(depth + " Total children added: " + this.children.Count); // Create your subtree here and return the results return(children); }