public bool isLeaf(Node p) { return p.children.Count == 0; }
public Node select(Node p, float c) { float bestValue = 0; Node selected = null; bool ownTurn = (playerSide == 0) ? true : false; if (p.state.isOwnTurn == ownTurn) { foreach (Node child in p.children) { if (child.numVisited == 0) { return child; } float UCTValue = (float)(child.mean + c * Math.Sqrt(Math.Log(p.numVisited) / child.numVisited)); //if (child.move != null) // child.move.print(); //Helpfunctions.Instance.logg("UCTVale = " + UCTValue); if (UCTValue > bestValue) { bestValue = UCTValue; selected = child; } } } else { bestValue = 99999; foreach (Node child in p.children) { if (child.numVisited == 0) { return child; } float UCTValue = (float)(child.mean - c * Math.Sqrt(Math.Log(p.numVisited) / child.numVisited)); if (UCTValue < bestValue) { bestValue = UCTValue; selected = child; } } } if (selected == null) { selected = p.children[GameManager.getRNG().Next(p.children.Count)]; } return selected; }
public int expand(Node p) { int state = 0; Playfield afterState = new Playfield(p.state); //List<Action> moves = Movegenerator.Instance.getMoveList(afterState, false, true, true); //GameManager.Instance.moveCount++; //if (GameManager.Instance.moveCount == 16) //{ // int debug = 1; //} Movegenerator.Instance.getMoveListForPlayfield(afterState, false); if (afterState.moveList.Count == 0) { // no moves available afterState.endTurn(false, false); Node originalNode = new Node(new Playfield(afterState), null, p.depth + 1); p.children.Add(originalNode); state = 1; } foreach (Action move in afterState.moveList) { Node afterNode = new Node(new Playfield(afterState), move, p.depth); afterNode.state.doAction(move); //if (move.actionType == actionEnum.attackWithMinion && move.own.entitiyID == 1008 && move.target.entitiyID == 1003) //{ // GameManager.Instance.moveCount++; // if (GameManager.Instance.moveCount == 3) // { // int debug = 1; // } //} p.children.Add(afterNode); } return state; }
public float sample(Node p) { Playfield startState = new Playfield(p.state); Action move = null; int turn = p.depth; //Helpfunctions.Instance.logg("turn: " + turn); int score = startState.getGameResult(); while (score == -1) { //List<Action> moves = Movegenerator.Instance.getMoveList(startState, false, false, true); //if (move != null) //{ //GameManager.Instance.moveCount++; //if (GameManager.Instance.moveCount == 562) //{ // int debug = 1; //} //var milliseconds = (DateTime.Now - DateTime.MinValue).TotalMilliseconds; Movegenerator.Instance.getMoveListForPlayfield(startState, false); //double time = (DateTime.Now - DateTime.MinValue).TotalMilliseconds - milliseconds; //GameManager.Instance.myTimer += time; //Helpfunctions.Instance.logg("my:" + time + " total:" + GameManager.Instance.myTimer); //milliseconds = (DateTime.Now - DateTime.MinValue).TotalMilliseconds; //List<Action> bruteForceMoves = Movegenerator.Instance.getMoveList(startState, false, true, true); //time = (DateTime.Now - DateTime.MinValue).TotalMilliseconds - milliseconds; //GameManager.Instance.sfTimer += time; //Helpfunctions.Instance.logg("sf:" + time + " total:" + GameManager.Instance.sfTimer); //if (bruteForceMoves.Count != startState.moveList.Count) { // startState.printBoard(); // int debug = 1; // Helpfunctions.Instance.logg("BF Move List:------------------------------------"); // foreach (Action action in bruteForceMoves) // { // action.print(); // } // startState.printMoveList(); //} //} //Helpfunctions.Instance.logg("Count: " + startState.moveList.Count); if (startState.moveList.Count == 0) { startState.endTurn(false, false); //Helpfunctions.Instance.logg("Turn = " + startState.isOwnTurn); if (!isEndReached) { //if (startState.isOwnTurn && this.playerSide == 1 || !startState.isOwnTurn && this.playerSide == 0) //{ // turn++; // //Helpfunctions.Instance.logg("Turn++"); //} turn++; move = null; if (turn == rolloutDepth) //evaluate at deapth == 5 { //startState.printBoard(); float value = startState.getBoardValue(); //Helpfunctions.Instance.logg("value = " + value); if (value > bestValue) { bestBoard = new Playfield(startState); bestValue = value; } return value; } } } else { move = startState.moveList[GameManager.getRNG().Next(startState.moveList.Count)]; startState.doAction(move); } score = startState.getGameResult(); } isEndReached = true; if (playerSide == score) { return 1; } return 0; }
//public void getAllpossibleStates(Playfield state, ref List<Playfield> statesList) //{ // List<Action> moves = Movegenerator.Instance.getMoveList(state, false, true, true); // if (moves.Count == 0) // { // if (tt.addToMap(state) == false) // { // statesList.Add(state); // } // return; // } // foreach (Action action in moves) // { // Playfield afterState = new Playfield(state); // afterState.doAction(action); // //if (tt.addToMap(afterState) == false) // //{ // // statesList.Add(afterState); // getAllpossibleStates(afterState, ref statesList); // //} // } //} public void UCTRun(Node p, float c) { List<Node> visited = new List<Node>(); visited.Add(p); int depth = 0; Node parent = null; List<Action> actions = new List<Action>(); while (!isLeaf(p) && p.depth < rolloutDepth) { parent = p; p = select(p, c); depth++; if (p.move != null && depth == 1) { //Helpfunctions.Instance.logg("=======================MOVE TO SAMPLE==================="); //Helpfunctions.Instance.logg("Turn: " + p.state.isOwnTurn); //p.state.printBoard(); //p.move.print(); } actions.Add(p.move); depth++; visited.Add(p); } float score; if (p.depth == rolloutDepth) { score = p.state.getBoardValue(); } else { int count = expand(p); score = sample(p); } //Helpfunctions.Instance.logg("score = " + score); //update score foreach (Node visitedPos in visited) { float lastMean = visitedPos.mean; visitedPos.mean = (score + lastMean * visitedPos.numVisited) / (visitedPos.numVisited + 1); visitedPos.numVisited++; } }
public Playfield getBestPlayfield() { currentState = new Node(board, null, 0); if (expand(currentState) == 1) return new Playfield(board); // no moves int counter = 0; for (int i = 0; i < 10000; i++) { Helpfunctions.Instance.logg("try: " + i); //counter++; //if (counter == 10) { // Helpfunctions.Instance.logg("try: " + i); // counter = 0; //} //if (i == 752) { // int debug = 1; //} UCTRun(currentState, 0.7f); currentState.state = new Playfield(board); } int maxVisit = 0; Playfield selectedMove = null; Node selectedChild = null; foreach (Node child in currentState.children) { if (child.numVisited > maxVisit) { maxVisit = child.numVisited; selectedMove = child.state; selectedChild = child; } } //Helpfunctions.Instance.logg("Turn of child:" + selectedChild.state.isOwnTurn); //currentState.printChildren(); return selectedMove; }
public override Action getMove() { bestValue = float.MinValue; bestBoard = new Playfield(board); currentState = new Node(board, null, 0); if (expand(currentState) == 1) return null; // no moves bool isEndReachedBefore = isEndReached; for (int i = 0; i < 500; i++) { //Helpfunctions.Instance.logg("try: " + i); //counter++; //if (counter == 10) { // Helpfunctions.Instance.logg("try: " + i); // counter = 0; //} //if (i == 752) { // int debug = 1; //} if (isEndReachedBefore != isEndReached) { //Helpfunctions.Instance.logg("try: " + i + " reach"); break; } else { //Helpfunctions.Instance.logg("try: " + i + " not reach"); } UCTRun(currentState, 0.7f); //currentState.state = new Playfield(board); } if (isEndReachedBefore != isEndReached) { currentState = new Node(board, null, 0); if (expand(currentState) == 1) return null; // no moves for (int i = 0; i < 10000; i++) { UCTRun(currentState, 0.7f); currentState.state = new Playfield(board); } } int maxVisit = 0; Action selectedMove = null; Node selectedChild = null; foreach (Node child in currentState.children) { //child.move.print(); //Helpfunctions.Instance.logg("count = " + child.numVisited); if (child.numVisited > maxVisit) { maxVisit = child.numVisited; selectedMove = child.move; selectedChild = child; } } //Helpfunctions.Instance.logg("Turn of child:" + selectedChild.state.isOwnTurn); //currentState.printChildren(); Helpfunctions.Instance.logg("best value:" + bestValue); bestBoard.printBoard(); return selectedMove; }