예제 #1
0
파일: Notation.cs 프로젝트: terite/HexChess
    public static string Get(BoardState boardState, Move move, List <Promotion> promotions, NotationType notationType = NotationType.LongForm)
    {
        if (move.lastTeam == Team.None)
        {
            return("");
        }

        string fromIndex = move.from.GetKey();
        string toIndex   = move.to.GetKey();
        string piece     = GetStringForPiece(move.lastPiece, move.lastTeam, promotions, move);
        string type      = move.capturedPiece.HasValue ? "x" : move.defendedPiece.HasValue ? "d" : "m";

        // When using freeplace mode, you can swap non-rook pieces, we want to clearly label that as a swap and not a defend unless a rook is involved
        if (type == "d" && !HexachessagonEngine.GetRealPiece((move.lastTeam, move.lastPiece), promotions).IsRook())
        {
            type = "-";
        }

        string otherPiece = type switch {
            "x" => GetStringForPiece(move.capturedPiece.Value, move.lastTeam.Enemy(), promotions, move),
            string t when(t == "d" || t == "-") => GetStringForPiece(move.defendedPiece.Value, move.lastTeam, promotions, move),
            _ => ""
        };

        string freePlaced = "";

        bool shortFormMod = notationType == NotationType.ShortForm;

        if (move.from == Index.invalid && move.to == Index.invalid)
        {
            // No piece moved - skipped move with free place mode
            fromIndex    = "";
            toIndex      = "";
            piece        = "";
            type         = "";
            otherPiece   = "";
            freePlaced   = "skipped";
            shortFormMod = false;
        }
        else if (move.to == Index.invalid)
        {
            // Put in jail with free place mode
            otherPiece   = "";
            type         = "";
            toIndex      = "";
            freePlaced   = " jailed";
            shortFormMod = false;
        }
        else if (move.from == Index.invalid)
        {
            // Freed from jail with free place mode
            fromIndex    = "";
            otherPiece   = "";
            type         = "";
            freePlaced   = " freed to ";
            shortFormMod = false;
        }

        string promo = "";
        Team   lt    = move.lastTeam;
        Piece  lp    = move.lastPiece;

        IEnumerable <Promotion> applicablePromotions = promotions.Where(promo => promo.team == lt && promo.from == lp);

        if (applicablePromotions.Any())
        {
            Promotion applicablePromo = applicablePromotions.First();
            promo = applicablePromo.turnNumber == move.turn + (move.lastTeam == Team.Black).BoolToInt() && move.lastTeam == applicablePromo.team
                ? $"={applicablePromo.to.GetPieceShortString()}"
                : "";
        }

        string check = boardState.checkmate != Team.None ? "#" : boardState.check != Team.None ? "+" : "";

        // modify for shortform
        if (notationType == NotationType.ShortForm && shortFormMod)
        {
            if (piece == "p")
            {
                piece = "";
                if (type != "-")
                {
                    otherPiece = "";
                    type       = type == "x" ? type : "";
                    fromIndex  = type == "x" ? $"{fromIndex.First()}" : "";
                }
            }
            else
            {
                List <Piece> alternatePieces = HexachessagonEngine.GetRealPiece((lt, lp), promotions).GetAlternates().ToList();

                foreach (Promotion potentialAlternate in promotions)
                {
                    if (potentialAlternate.turnNumber < move.turn)
                    {
                        List <Piece?> toAdd = new List <Piece?>();
                        foreach (Piece alt in alternatePieces)
                        {
                            if (potentialAlternate.to == alt)
                            {
                                toAdd.Add(potentialAlternate.from);
                            }
                        }

                        toAdd.ForEach(p => alternatePieces.Add(p.Value));

                        if (potentialAlternate.from == lp)
                        {
                            alternatePieces.Add(potentialAlternate.to);
                        }

                        if (potentialAlternate.to == lp)
                        {
                            alternatePieces.Add(potentialAlternate.from);
                        }
                    }
                }

                type = type == "m" ? "" : type;

                if (alternatePieces.Count > 0)
                {
                    bool fileAmbiguity = false;
                    bool rankAmbiguity = false;

                    foreach (Piece alternate in alternatePieces)
                    {
                        if (boardState.TryGetIndex((lt, alternate), out Index index))
                        {
                            Piece realPiece = HexachessagonEngine.GetRealPiece((lt, alternate), promotions);

                            var possibleMovesConcerningHex = MoveGenerator.GetAllPossibleMoves(index, realPiece, lt, boardState, promotions, true)
                                                             .Where(kvp => kvp.target != null && kvp.target == move.to);

                            if (MoveValidator.ValidateMoves(possibleMovesConcerningHex, (lt, alternate), boardState, promotions).Any())
                            {
                                if (index.col == move.from.col)
                                {
                                    rankAmbiguity = true;
                                }
                                if (index.row == move.from.row)
                                {
                                    fileAmbiguity = true;
                                }
                            }
                        }
                    }

                    if (fileAmbiguity && rankAmbiguity)
                    {
                        fromIndex = move.from.GetKey();
                    }
                    else if (fileAmbiguity)
                    {
                        fromIndex = $"{move.from.GetLetter()}";
                    }
                    else if (rankAmbiguity)
                    {
                        fromIndex = $"{move.from.GetNumber()}";
                    }
                    else
                    {
                        fromIndex = "";
                    }
                }
                else
                {
                    fromIndex = "";
                }
            }
        }

        return($"{piece}{fromIndex}{type}{otherPiece}{freePlaced}{toIndex}{promo}{check}");
    }