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));
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 7
0
        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);
        }