public Tuple <double, double> Evaluate(bool full = false) { int evalGames = full ? TetrisSettings.EvalutaionGames : TetrisSettings.TrainEvaluationGames; double[] _clearedRows = new double[evalGames]; double[] _placedPieces = new double[evalGames]; for (int i = 0; i < evalGames; i++) { if (full) { this.tetrisGame.ResetGame(TetrisSettings.Width, TetrisSettings.Height); } else { this.tetrisGame.ResetGame(TetrisSettings.TrainWidth, TetrisSettings.TrainHeight); } PlacementPackage[] packages = tetrisGame.GetPackages(); while (packages.Length > 0) { PlacementPackage bestPackage = packages[0]; bestPackage.PackageScore = ann.Evaluate(bestPackage); for (int iPackage = 1; iPackage < packages.Length; iPackage++) { PlacementPackage package = packages[iPackage]; package.PackageScore = ann.Evaluate(package); if (package.PackageScore > bestPackage.PackageScore) { bestPackage = package; } } tetrisGame.ApplyPackage(bestPackage); packages = tetrisGame.GetPackages(); } _clearedRows[i] = tetrisGame.Score; _placedPieces[i] = tetrisGame.PlacedPieces; } double totCleared = 0, totPlaced = 0; for (int i = 0; i < evalGames; i++) { totCleared += _clearedRows[i]; totPlaced += _placedPieces[i]; } this.cleared = totCleared / evalGames; this.placed = placed / evalGames; return(new Tuple <double, double>(cleared, placed)); }
private void NNPlace(object sender, RoutedEventArgs e) { PlacementPackage[] packages = game.GetPackages(currentPiece); if (packages.Length == 0) { ClearBoard(); } else { PlacementPackage bestPackage = packages[0]; bestPackage.PackageScore = ann.Evaluate(bestPackage); for (int iPackage = 1; iPackage < packages.Length; iPackage++) { PlacementPackage package = packages[iPackage]; package.PackageScore = ann.Evaluate(package); if (package.PackageScore > bestPackage.PackageScore) { bestPackage = package; } } int[,] toOccupy = bestPackage.OccupiedCells; this.package = bestPackage; List <int> occupiedRows = new List <int>(); for (int i = 0; i < bestPackage.OccupiedCells.GetLength(0); i++) { if (!occupiedRows.Contains(toOccupy[i, 1])) { occupiedRows.Add(bestPackage.OccupiedCells[i, 1]); } } game.ApplyPackage(bestPackage); for (int i = 0; i < toOccupy.GetLength(0); i++) { if (this.boardOccupation[toOccupy[i, 0], toOccupy[i, 1]]) { //Console.WriteLine("thing"); throw new Exception("Something about a thing"); } this.boardOccupation[toOccupy[i, 0], toOccupy[i, 1]] = true; boardFills[toOccupy[i, 0], toOccupy[i, 1]].Fill = currentPiece.Brush; } //Clear the board as necessary, not optimized. List <int> rowsToOccupy = new List <int>(); for (int i = 0; i < toOccupy.GetLength(0); i++) { if (!rowsToOccupy.Contains(toOccupy[i, 1])) { rowsToOccupy.Add(toOccupy[i, 1]); } } /* * The logic is pretty simple, we don't care about efficiency, so start at the bottom row, if it's full, remove it and bring down all the rows above. * Repeat for that row, once done, test the row up, until every row is tested. */ for (int i = this.height - 1; i >= 0; i--) { bool rowFull = true; for (int j = 0; j < this.width; j++) { if (!this.boardOccupation[j, i]) { rowFull = false; break; } } if (rowFull) { for (int j = i - 1; j >= 0; j--) // Start at the row above to send it down { for (int x = 0; x < width; x++) // Move horizontally along the board { boardFills[x, j + 1].Fill = boardFills[x, j].Fill; //Grid.SetColumn(boardFills[x, j + 1], j + 1); this.boardOccupation[x, j + 1] = this.boardOccupation[x, j]; // set the board occupation for later verification. } } i++; for (int x = 0; x < width; x++) { boardFills[x, 0].Fill = transparentBrush; this.boardOccupation[x, 0] = false; } } } // Verify the two different calculations match if (!this.boardOccupation.ToString().Equals(this.game.Board.ToString())) { Console.WriteLine(this.boardOccupation.ToString()); Console.WriteLine(this.game.Board.ToString()); throw new Exception("TetrisGame and Tetris boards do not match"); } display_score.Text = this.game.Score.ToString(); } newPiece(); }