public SubmittedMoveResponse MakeMove(string origin, string destination, string promotion) { SubmittedMoveResponse response = new SubmittedMoveResponse() { Success = true, Error = null }; if (promotion != null && promotion.Length != 1) { response.Success = false; response.Error = "Invalid promotion."; response.Correct = SubmittedMoveResponse.INVALID_MOVE; return(response); } MoveType type = Current.Game.MakeMove(new Move(origin, destination, Current.Game.WhoseTurn, promotion?[0]), false); if (type == MoveType.Invalid) { response.Success = false; response.Error = "Invalid move."; response.Correct = SubmittedMoveResponse.INVALID_MOVE; } string promotionUpper = promotion?.ToUpperInvariant(); Moves.Add(string.Format("{0}-{1}{2}", origin, destination, promotion == null ? "" : "=" + promotionUpper)); string moveStr = origin + "-" + destination + (promotion != null ? "=" + promotionUpper : ""); return(MakeMoveAndDropCommon(response, moveStr)); }
void PuzzleFinished(SubmittedMoveResponse response, bool correct) { CurrentPuzzleEndedUtc = DateTime.UtcNow; response.Correct = correct ? 1 : -1; response.ExplanationSafe = Current.ExplanationSafe; PastPuzzleIds.Add(Current.ID); if (!correct) { Moves.RemoveAt(Moves.Count - 1); FENs.RemoveAt(FENs.Count - 1); Checks.RemoveAt(Checks.Count - 1); response.FEN = FENs[FENs.Count - 1]; ChessGame correctGame = gameConstructor.Construct(Current.Variant, response.FEN); foreach (string move in PossibleVariations.First()) { string[] p = move.Split('-', '='); correctGame.ApplyMove(new Move(p[0], p[1], correctGame.WhoseTurn, p.Length == 2 ? null : new char?(p[2][0])), true); FENs.Add(correctGame.GetFen()); Checks.Add(correctGame.IsInCheck(correctGame.WhoseTurn) ? correctGame.WhoseTurn.ToString().ToLowerInvariant() : null); Moves.Add(move); } } response.ReplayFENs = FENs; response.ReplayChecks = Checks; response.ReplayMoves = Moves; }
public SubmittedMoveResponse ApplyDrop(string role, string pos) { SubmittedMoveResponse response = new SubmittedMoveResponse() { Success = true, Error = null }; if (!(Current.Game is CrazyhouseChessGame)) { response.Success = false; response.Error = "Not a crazyhouse puzzle."; response.Correct = SubmittedMoveResponse.INVALID_MOVE; return(response); } CrazyhouseChessGame zhCurrentGame = Current.Game as CrazyhouseChessGame; Piece p = Utilities.GetByRole(role, zhCurrentGame.WhoseTurn); if (p == null) { response.Success = false; response.Error = "Invalid drop piece."; response.Correct = SubmittedMoveResponse.INVALID_MOVE; return(response); } Drop drop = new Drop(p, new Position(pos), zhCurrentGame.WhoseTurn); if (!zhCurrentGame.ApplyDrop(drop, false)) { response.Correct = SubmittedMoveResponse.INVALID_MOVE; return(response); } char pieceChar = char.ToUpper(p.GetFenCharacter()); string moveStr = (pieceChar == 'P' ? "" : pieceChar.ToString()) + "@" + pos; Moves.Add(moveStr); return(MakeMoveAndDropCommon(response, moveStr)); }
SubmittedMoveResponse MakeMoveAndDropCommon(SubmittedMoveResponse response, string moveStr) { response.Check = Current.Game.IsInCheck(Current.Game.WhoseTurn) ? Current.Game.WhoseTurn.ToString().ToLowerInvariant() : null; Checks.Add(response.Check); string fen = Current.Game.GetFen(); response.FEN = fen; FENs.Add(fen); Dictionary <string, int> pocket = Current.Game.GenerateJsonPocket(); response.Pocket = pocket; Pockets.Add(pocket); if (Current.Game.IsWinner(ChessUtilities.GetOpponentOf(Current.Game.WhoseTurn))) { PuzzleFinished(response, true); return(response); } if (!PossibleVariations.Any(x => CompareMoves(x.First(), moveStr) == 0)) { PuzzleFinished(response, false); return(response); } PossibleVariations = PossibleVariations.Where(x => CompareMoves(x.First(), moveStr) == 0).Select(x => x.Skip(1)); if (PossibleVariations.Any(x => x.Count() == 0)) { PuzzleFinished(response, true); return(response); } string moveToPlay = PossibleVariations.First().First(); if (!moveToPlay.Contains("@")) { string[] parts = moveToPlay.Split('-', '='); Current.Game.MakeMove(new Move(parts[0], parts[1], Current.Game.WhoseTurn, parts.Length == 2 ? null : new char?(parts[2][0])), true); } else { string[] parts = moveToPlay.Split('@'); CrazyhouseChessGame zhCurrent = Current.Game as CrazyhouseChessGame; Piece toDrop = zhCurrent.MapPgnCharToPiece(parts[0] == "" ? 'P' : parts[0][0], zhCurrent.WhoseTurn); Drop drop = new Drop(toDrop, new Position(parts[1]), zhCurrent.WhoseTurn); zhCurrent.ApplyDrop(drop, true); } response.Play = moveToPlay; Moves.Add(moveToPlay); response.FenAfterPlay = Current.Game.GetFen(); FENs.Add(response.FenAfterPlay); response.CheckAfterAutoMove = Current.Game.IsInCheck(Current.Game.WhoseTurn) ? Current.Game.WhoseTurn.ToString().ToLowerInvariant() : null; Checks.Add(response.CheckAfterAutoMove); response.Moves = Current.Game.GetValidMoves(Current.Game.WhoseTurn); response.Correct = 0; response.PocketAfterAutoMove = Current.Game.GenerateJsonPocket(); Pockets.Add(response.PocketAfterAutoMove); PossibleVariations = PossibleVariations.Select(x => x.Skip(1)); if (PossibleVariations.Any(x => !x.Any())) { PuzzleFinished(response, true); } return(response); }
void PuzzleFinished(SubmittedMoveResponse response, bool correct) { CurrentPuzzleEndedUtc = DateTime.UtcNow; response.Correct = correct ? 1 : -1; response.ExplanationSafe = Current.ExplanationSafe; if (!PastPuzzleIds.Contains(Current.ID)) { PastPuzzleIds.Add(Current.ID); } string analysisUrl = "https://lichess.org/analysis/{0}/{1}"; string analysisUrlVariant; switch (Current.Variant) { case "Atomic": analysisUrlVariant = "atomic"; break; case "Antichess": analysisUrlVariant = "antichess"; break; case "Crazyhouse": analysisUrlVariant = "crazyhouse"; break; case "Horde": analysisUrlVariant = "horde"; break; case "KingOfTheHill": analysisUrlVariant = "kingOfTheHill"; break; case "ThreeCheck": analysisUrlVariant = "threeCheck"; break; case "RacingKings": analysisUrlVariant = "racingKings"; break; default: analysisUrlVariant = "unknown"; break; } response.AnalysisUrl = string.Format(analysisUrl, analysisUrlVariant, Current.InitialFen.Replace(' ', '_')); List <string> replayFens = new List <string>(FENs); List <string> replayChecks = new List <string>(Checks); List <string> replayMoves = new List <string>(Moves); List <Dictionary <string, int> > replayPockets = new List <Dictionary <string, int> >(Pockets); if (!correct) { Moves.RemoveAt(Moves.Count - 1); FENs.RemoveAt(FENs.Count - 1); Checks.RemoveAt(Checks.Count - 1); Pockets.RemoveAt(Pockets.Count - 1); replayFens.RemoveAt(replayFens.Count - 1); replayMoves.RemoveAt(replayMoves.Count - 1); replayChecks.RemoveAt(replayChecks.Count - 1); replayPockets.RemoveAt(replayPockets.Count - 1); response.FEN = FENs[FENs.Count - 1]; response.Pocket = Pockets[Pockets.Count - 1]; ChessGame correctGame = gameConstructor.Construct(Current.Variant, Current.InitialFen); int i = 0; var full = replayMoves.Concat(PossibleVariations.First()); foreach (string move in full) { if (move == null) { i++; continue; } if (!move.Contains("@")) { string[] p = move.Split('-', '='); correctGame.MakeMove(new Move(p[0], p[1], correctGame.WhoseTurn, p.Length == 2 ? null : new char?(p[2][0])), true); } else { string[] p = move.Split('@'); if (string.IsNullOrEmpty(p[0])) { p[0] = "P"; } Drop drop = new Drop(correctGame.MapPgnCharToPiece(p[0][0], correctGame.WhoseTurn), new Position(p[1]), correctGame.WhoseTurn); (correctGame as CrazyhouseChessGame).ApplyDrop(drop, true); } if (i >= Moves.Count) { replayFens.Add(correctGame.GetFen()); replayChecks.Add(correctGame.IsInCheck(correctGame.WhoseTurn) ? correctGame.WhoseTurn.ToString().ToLowerInvariant() : null); replayMoves.Add(move); replayPockets.Add(correctGame.GenerateJsonPocket()); } i++; } Current.Game = gameConstructor.Construct(Current.Variant, response.FEN); response.Moves = Current.Game.GetValidMoves(Current.Game.WhoseTurn); response.Check = Current.Game.IsInCheck(Player.White) ? "white" : (Current.Game.IsInCheck(Player.Black) ? "black" : null); } response.ReplayFENs = replayFens; response.ReplayChecks = replayChecks; response.ReplayMoves = replayMoves; response.ReplayPockets = replayPockets; }
public SubmittedMoveResponse SubmitMove(Move move) { SubmittedMoveResponse response = new SubmittedMoveResponse(); MoveType type = Game.ApplyMove(move, false); if (type == MoveType.Invalid) { response.Success = false; response.Error = "Invalid move."; response.Correct = -3; return(response); } response.Success = true; response.Check = Game.IsInCheck(Game.WhoseTurn) ? Game.WhoseTurn.ToString().ToLowerInvariant() : null; response.FEN = Game.GetFen(); if (Game.IsWinner(ChessUtilities.GetOpponentOf(Game.WhoseTurn))) { response.Correct = 1; return(response); } else if (Game.IsWinner(Game.WhoseTurn)) { response.Correct = -3; return(response); } else if (Game.DrawCanBeClaimed) { response.Correct = -1; return(response); } else if (Game.IsStalemated(Game.WhoseTurn)) { response.Correct = -2; return(response); } response.Correct = 0; Move chosen = null; if (Game is AtomicChessGame) { Position whiteKing = null; Position blackKing = null; for (int i = 0; i < 8; i++) { for (int j = 1; j < 9; j++) { if (Game.GetPieceAt((File)i, j) == new King(Player.White)) { whiteKing = new Position((File)i, j); } if (Game.GetPieceAt((File)i, j) == new King(Player.Black)) { blackKing = new Position((File)i, j); } if (whiteKing != null && blackKing != null) { break; } } } ReadOnlyCollection <Move> validKingMoves = Game.GetValidMoves(blackKing); List <Move> validKingMovesToAdjacentKings = new List <Move>(); foreach (Move validMove in validKingMoves) { PositionDistance distance = new PositionDistance(whiteKing, validMove.NewPosition); if (distance.DistanceX <= 1 && distance.DistanceY <= 1) { validKingMovesToAdjacentKings.Add(validMove); } } if (validKingMovesToAdjacentKings.Count > 0) { chosen = validKingMovesToAdjacentKings[rnd.Next(0, validKingMovesToAdjacentKings.Count)]; } else { chosen = validKingMoves[rnd.Next(0, validKingMoves.Count)]; } } else // (Game is AntichessGame) { ReadOnlyCollection <Move> validMovesBlack = Game.GetValidMoves(Player.Black); foreach (Move validMove in validMovesBlack) { AntichessGame copy = new AntichessGame(Game.GetFen()); copy.ApplyMove(validMove, true); ReadOnlyCollection <Move> validMovesWhite = copy.GetValidMoves(Player.White); if (validMovesWhite.Any(x => copy.GetPieceAt(x.NewPosition) != null)) { chosen = validMove; break; } if (chosen == null) { bool thisOne = true; foreach (Move vmWhite in validMovesWhite) { AntichessGame copy2 = new AntichessGame(copy.GetFen()); copy2.ApplyMove(vmWhite, true); ReadOnlyCollection <Move> validMovesBlackStep2 = copy2.GetValidMoves(Player.Black); if (validMovesBlackStep2.Any(x => copy2.GetPieceAt(x.NewPosition) != null)) { thisOne = false; } } if (thisOne) { chosen = validMove; } } } if (chosen == null) { chosen = validMovesBlack[rnd.Next(0, validMovesBlack.Count)]; } } Game.ApplyMove(chosen, true); response.CheckAfterAutoMove = Game.IsInCheck(Game.WhoseTurn) ? Game.WhoseTurn.ToString().ToLowerInvariant() : null; response.WinAfterAutoMove = Game.IsWinner(Game.WhoseTurn); response.FenAfterPlay = Game.GetFen(); response.Moves = Game.GetValidMoves(Game.WhoseTurn); response.LastMove = new string[2] { chosen.OriginalPosition.ToString().ToLowerInvariant(), chosen.NewPosition.ToString().ToLowerInvariant() }; if (Game.DrawCanBeClaimed) { response.DrawAfterAutoMove = true; } else { response.DrawAfterAutoMove = false; } return(response); }
public SubmittedMoveResponse ApplyMove(string origin, string destination, string promotion) { SubmittedMoveResponse response = new SubmittedMoveResponse() { Success = true, Error = null }; if (promotion != null && promotion.Length != 1) { response.Success = false; response.Error = "Invalid promotion."; response.Correct = SubmittedMoveResponse.INVALID_MOVE; return(response); } MoveType type = Current.Game.ApplyMove(new Move(origin, destination, Current.Game.WhoseTurn, promotion?[0]), false); if (type == MoveType.Invalid) { response.Success = false; response.Error = "Invalid move."; response.Correct = SubmittedMoveResponse.INVALID_MOVE; } response.Check = Current.Game.IsInCheck(Current.Game.WhoseTurn) ? Current.Game.WhoseTurn.ToString().ToLowerInvariant() : null; Checks.Add(response.Check); string fen = Current.Game.GetFen(); response.FEN = fen; FENs.Add(fen); string promotionUpper = promotion?.ToUpperInvariant(); Moves.Add(string.Format("{0}-{1}={2}", origin, destination, promotion == null ? "" : "=" + promotionUpper)); if (Current.Game.IsWinner(ChessUtilities.GetOpponentOf(Current.Game.WhoseTurn))) { PuzzleFinished(response, true); return(response); } string moveStr = origin + "-" + destination + (promotion != null ? "=" + promotionUpper : ""); if (!PossibleVariations.Any(x => string.Compare(x.First(), moveStr, true) == 0)) { PuzzleFinished(response, false); return(response); } PossibleVariations = PossibleVariations.Where(x => string.Compare(x.First(), moveStr, true) == 0).Select(x => x.Skip(1)); if (PossibleVariations.Any(x => x.Count() == 0)) { PuzzleFinished(response, true); return(response); } response.FEN = fen; string moveToPlay = PossibleVariations.First().First(); string[] parts = moveToPlay.Split('-', '='); Current.Game.ApplyMove(new Move(parts[0], parts[1], Current.Game.WhoseTurn, parts.Length == 2 ? null : new char?(parts[2][0])), true); response.Play = moveToPlay; Moves.Add(moveToPlay); response.FenAfterPlay = Current.Game.GetFen(); FENs.Add(response.FenAfterPlay); response.CheckAfterAutoMove = Current.Game.IsInCheck(Current.Game.WhoseTurn) ? Current.Game.WhoseTurn.ToString().ToLowerInvariant() : null; Checks.Add(response.CheckAfterAutoMove); response.Moves = Current.Game.GetValidMoves(Current.Game.WhoseTurn); response.Correct = 0; PossibleVariations = PossibleVariations.Select(x => x.Skip(1)); if (PossibleVariations.Any(x => !x.Any())) { PuzzleFinished(response, true); } return(response); }