public void CreateChildren() { virtualMarble = GM.CreateVirtualMarble(); tempMarbles.Add(virtualMarble); virtualMarble.owner = this.tree.player; lastTile = this.tile; if (this.parent != null) { lastTile = parent.tile; } tile.CurrentMarble = virtualMarble; virtualMarble.SetCurrentTile(tile); tile.Occupied = true; if (!jumping || virtualMarble.MoveAgainCheck(lastTile).Count < 1) { tile.Occupied = false; tile.CurrentMarble = null; virtualMarble = null; GM.MiniMaxNodeValueFinder(this); } else { GM.CreateChildNodes(this); //Startar ChildCreator-coroutinen } } public IEnumerator ChildCreator() //Gjord till en coroutine för att kunna använda WaitUntil, vilket skapar en childnode i taget och undviker stack overflow { foreach (TileScript jump in virtualMarble.MoveAgainCheck(lastTile)) { bool skip = false; foreach(TileScript previousTile in this.path) { if (previousTile == jump) skip = true; } if (skip) continue; stateCheck = null; GM.StateCheck(this, jump); yield return new WaitUntil(() => stateCheck != null); if ((bool)stateCheck) { moreJumps = true; MiniMaxNode child = CreateInstance(); child.Init(this.tree, this, path, jump, marble, true, GM, pathStates); children.Add(child); } } foreach (MiniMaxNode child in children) { child.CreateChildren(); yield return new WaitUntil(() => child.Done == true); } tile.Occupied = false; tile.CurrentMarble = null; virtualMarble = null; if (!moreJumps) { GM.MiniMaxNodeValueFinder(this); } } public IEnumerator StateCheck(TileScript potentialJump) //Gjord till en coroutine för att kunna använda WaitUntil och undvika stack overflow { yield return null; string stateToTry = GetVirtualState(); string state; StreamReader oldStatesReader = File.OpenText(Application.persistentDataPath + "/allStates.dat"); int lines = 0; while ((state = oldStatesReader.ReadLine()) != null) { lines++; } string s; oldStatesReader.DiscardBufferedData(); oldStatesReader.BaseStream.Seek(0, SeekOrigin.Begin); using (oldStatesReader) { StreamWriter newStatesWriter = new StreamWriter(Application.persistentDataPath + "/newStates.dat"); using (newStatesWriter) { while ((s = oldStatesReader.ReadLine()) != null) { if (lines > 100) //Sparar endast de 100 senaste statesen för att undvika stack overflow { lines--; continue; } newStatesWriter.WriteLine(s); } } } File.Delete(Application.persistentDataPath + "/allStates.dat"); using (StreamReader newStatesReader = File.OpenText(Application.persistentDataPath + "/newStates.dat")) { string stateToWrite; using (StreamWriter finalStatesWriter = File.CreateText(Application.persistentDataPath + "/allStates.dat")) { while ((stateToWrite = newStatesReader.ReadLine()) != null) { finalStatesWriter.WriteLine(stateToWrite); } } } File.Delete(Application.persistentDataPath + "/newStates.dat"); using (StreamReader finalStatesReader = File.OpenText(Application.persistentDataPath + "/allStates.dat")) { while ((state = finalStatesReader.ReadLine()) != null) { if (state == stateToTry) { finalStatesReader.Close(); stateCheck = false; break; } } if (stateCheck == null) foreach (string virtualState in this.pathStates) { if (virtualState == stateToTry) { finalStatesReader.Close(); stateCheck = false; break; } } } if (stateCheck == null) stateCheck = true; } public IEnumerator FindValue() //Gjord till en coroutine för att kunna använda WaitUntil och undvika stack overflow { this.value = ((tree.originalDistance - Vector3.Distance(tile.transform.position, tree.player.goalTile.transform.position)) * 100f) + (10 * tree.originalDistance); this.value += FindBlocking(); if (this.tree.CurrentAI) { foreach (PlayerScript opponent in GM.Players) { if (opponent != this.tree.player) { if (opponent is HumanPlayerScript) { AIPlayerScript humanOpponent = GM.CreateAIPlayer(); tempAIs.Add(humanOpponent); humanOpponent.goalTile = opponent.goalTile; humanOpponent.myMarbles = opponent.myMarbles; foreach (MarbleScript marble in humanOpponent.myMarbles) { MiniMaxTree playerMoves = CreateInstance(); //Anpassar draget för att undvika att ge spelaren bra drag under sin runda playerMoves.Init(humanOpponent, GM, marble, false); playerMoves.StartTree(); yield return new WaitUntil(() => playerMoves.Done == true); this.value -= (playerMoves.ReportValue() / 20); } } else foreach (MarbleScript marble in opponent.myMarbles) { { MiniMaxTree opponentMoves = CreateInstance(); //Anpassar draget för att undvika att ge de andra AI-motståndarna bra drag under sina rundor opponentMoves.Init(opponent as AIPlayerScript, GM, marble, false); opponentMoves.StartTree(); yield return new WaitUntil(() => opponentMoves.Done == true); this.value -= (opponentMoves.ReportValue() / 20); } } } } } if (this.tree.player.WinCheck()) { this.value = Mathf.Infinity; } if (this.marble.LastTile == this.tile) { this.value -= 1000; } SendReport(); }