private IEnumerator GetEngineMove() { // This prevents the player from making a move during the calculation. isReady = false; ChangeText("Thinking...", ""); // This checks if it is stalemate for the engine. if (position.IsStalemate(color.Flip())) { StartCoroutine(HandleStrike("You lose!", "Stalemate!")); yield break; } // This checks if there are only kings on the board, which is always a draw. if (position.All(c => c == '_' || c.ToLower() == 'k')) { StartCoroutine(HandleStrike("You lose!", "Kings only!")); yield break; } yield return(_bestMove.Start(position, (MovesLeft * 2) + 1, color == PieceColor.Black)); // This looks convoluted, but it's only asking if the player has made a blunder, to the point of an unwinnable position. if (isWinning && ((color == PieceColor.White && _bestMove.Result.Evaluation != sbyte.MaxValue - (MovesLeft * 2)) || (color == PieceColor.Black && _bestMove.Result.Evaluation != (MovesLeft * 2) + sbyte.MinValue))) { isWinning = false; Log("Rustmate has evaluated that this position is now unwinnable for you. Congratulations."); } ChangeText("Mate in", "", MovesLeft.ToString()); PlaySound(Sounds._1dch.Opponent); // This indicates if the game has ended. if (_bestMove.Result.IsEqual(Position.finishedGame)) { isReady = false; PlaySound(Sounds._1dch.Check); // Stalemate. if (_bestMove.Result.Evaluation == 0) { StartCoroutine(HandleStrike("You lose!", "Stalemate!")); } // Checkmate against the player. else if (color == PieceColor.White ^ _bestMove.Result.Evaluation > 0) { StartCoroutine(HandleStrike("You lose!", "Checkmate!")); } // Checkmate for the player. else { PlaySound(Sounds._1dch.GameEnd, Sounds._1dch.Solve); string message = new[] { "Good game!", "Well played!" }.PickRandom(); Solve(message); ChangeText("Solved!", message); } } else { // This allows the player to make a move again. isReady = true; position = _bestMove .Result .Move(position, this); Log("Rustmate plays {0}, the position is now {1}.", ToLog(_bestMove.Result), position); souvenirPositions.Add(ToLog(_bestMove.Result)); // Having the game end after an engine move always means a loss for the player. if (position.IsGameEnd(color)) { StartCoroutine(HandleStrike("You lose!", position.IsStalemate(color) ? "Stalemate!" : "Checkmate!")); } // This checks if there are only kings on the board, which is always a draw. else if (position.All(c => c == '_' || c.ToLower() == 'k')) { StartCoroutine(HandleStrike("You lose!", "Kings only!")); } else if (MovesLeft == 0) { StartCoroutine(HandleStrike("You lose!", "Out of moves!")); } } RenderPosition(position); }