public bool GetBestMove(IBoard board, IPiece current, IPiece next, out int bestRotationDelta, out int bestTranslationDelta, out bool rotationBeforeTranslation) { int currentBestTranslationDelta = 0; int currentBestRotationDelta = 0; double currentBestRating = -1.0e+20; // Really bad! int currentBestPriority = 0; //if (current.PosY == board.Height) // TODO: put current totally in board before trying to get best move // current.Translate(0, -1); IBoard tempBoard = board.Clone(); IPiece tempPiece = current.Clone(); MoveManager moveManager = new MoveManager(); //Log.Default.WriteLine(LogLevels.Debug, "Get Best Move for Piece {0} {1}", tempPiece.Value, tempPiece.Index); #region Rotation then translation // Consider all possible rotations for (int trialRotationDelta = 0; trialRotationDelta < current.MaxOrientations; trialRotationDelta++) { // Copy piece tempPiece.CopyFrom(current); // Rotate tempPiece.Rotate(trialRotationDelta); // Get translation range bool isMovePossible; int minDeltaX; int maxDeltaX; BoardHelper.GetAccessibleTranslationsForOrientation(board, tempPiece, out isMovePossible, out minDeltaX, out maxDeltaX); //Log.Default.WriteLine(LogLevels.Debug, "Accessible translation {0} {1} {2} {3} {4} {5} {6}", minDeltaX, maxDeltaX, trialRotationDelta, current.PosX, current.PosY, tempPiece.Value, tempPiece.Index); //StringBuilder sb = new StringBuilder(); //for (int i = 1; i <= tempPiece.TotalCells; i++) //{ // int x, y; // tempPiece.GetCellAbsolutePosition(i, out x, out y); // sb.Append(String.Format("[{0}->{1},{2}]", i, x - tempPiece.PosX, y - tempPiece.PosY)); //} //Log.Log.Default.WriteLine("{0} {1} -> {2} {3}", trialRotationDelta, minDeltaX, maxDeltaX, sb.ToString()); if (isMovePossible) { // Consider all allowed translations for (int trialTranslationDelta = minDeltaX; trialTranslationDelta <= maxDeltaX; trialTranslationDelta++) { // Check if not already evaluated bool found = moveManager.Exists(trialRotationDelta, trialTranslationDelta); if (!found) { // Evaluate this move // Copy piece tempPiece.CopyFrom(current); // Rotate tempPiece.Rotate(trialRotationDelta); // Translate tempPiece.Translate(trialTranslationDelta, 0); // Check if move is acceptable if (board.CheckNoConflict(tempPiece)) { // Copy board tempBoard.CopyFrom(board); // Drop piece tempBoard.DropAndCommit(tempPiece); // Evaluate double trialRating; int trialPriority; EvaluteMove(tempBoard, tempPiece, out trialRating, out trialPriority); //Log.Log.Default.WriteLine("R:{0:0.0000} P:{1} R:{2} T:{3}", trialRating, trialPriority, trialRotationDelta, trialTranslationDelta); // Check if better than previous best if (trialRating > currentBestRating || (Math.Abs(trialRating - currentBestRating) < 0.0001 && trialPriority > currentBestPriority)) { currentBestRating = trialRating; currentBestPriority = trialPriority; currentBestTranslationDelta = trialTranslationDelta; currentBestRotationDelta = trialRotationDelta; } moveManager.Add(trialRotationDelta, trialTranslationDelta, trialRating, trialPriority); } } } } } //Log.Default.WriteLine(LogLevels.Debug, "ROTATION + TRANSLATION: {0} {1} {2:0.000} {3}", currentBestTranslationDelta, currentBestRotationDelta, currentBestRating, currentBestPriority); #endregion #region Translation then rotation bool isTrialMovePossible; int minTrialDeltaX; int maxTrialDeltaX; BoardHelper.GetAccessibleTranslationsForOrientation(board, tempPiece, out isTrialMovePossible, out minTrialDeltaX, out maxTrialDeltaX); if (isTrialMovePossible) { for (int trialTranslationDelta = minTrialDeltaX; trialTranslationDelta <= maxTrialDeltaX; trialTranslationDelta++) { // Copy piece tempPiece.CopyFrom(current); // Translate tempPiece.Translate(trialTranslationDelta, 0); // Consider all rotations for (int trialRotationDelta = 0; trialRotationDelta <= current.MaxOrientations; trialRotationDelta++) { // Rotate tempPiece.Rotate(trialRotationDelta); // Check if not already evaluated bool found = moveManager.Exists(trialRotationDelta, trialTranslationDelta); if (!found) { // Evaluate this move // Copy piece tempPiece.CopyFrom(current); // Rotate tempPiece.Rotate(trialRotationDelta); // Translate tempPiece.Translate(trialTranslationDelta, 0); // Check if move is acceptable if (board.CheckNoConflict(tempPiece)) { // Copy board tempBoard.CopyFrom(board); // Drop piece tempBoard.DropAndCommit(tempPiece); // Evaluate double trialRating; int trialPriority; EvaluteMove(tempBoard, tempPiece, out trialRating, out trialPriority); //Log.Log.Default.WriteLine("R:{0:0.0000} P:{1} R:{2} T:{3}", trialRating, trialPriority, trialRotationDelta, trialTranslationDelta); // Check if better than previous best if (trialRating > currentBestRating || (Math.Abs(trialRating - currentBestRating) < 0.0001 && trialPriority > currentBestPriority)) { currentBestRating = trialRating; currentBestPriority = trialPriority; currentBestTranslationDelta = trialTranslationDelta; currentBestRotationDelta = trialRotationDelta; //Log.Default.WriteLine(LogLevels.Debug, "FOUND BETTER MOVE USING TRANSLATION + ROTATION"); } moveManager.Add(trialRotationDelta, trialTranslationDelta, trialRating, trialPriority); } } } } } //Log.Default.WriteLine(LogLevels.Debug, "TRANSLATION + ROTATION: {0} {1} {2:0.000} {3}", currentBestTranslationDelta, currentBestRotationDelta, currentBestRating, currentBestPriority); #endregion // Commit to this move rotationBeforeTranslation = true; bestTranslationDelta = currentBestTranslationDelta; bestRotationDelta = currentBestRotationDelta; // Log.Default.WriteLine(LogLevels.Debug, "{0} {1} {2:0.000} {3}", bestRotationDelta, bestTranslationDelta, currentBestRating, currentBestPriority); return(true); }