예제 #1
0
        /// <summary>
        /// Checks if <see cref="Yakus"/> and <see cref="YakusCombinations"/> have to be cancelled because of the temporary furiten rule.
        /// </summary>
        /// <param name="currentRound">The current round</param>
        /// <param name="playerIndex">The player index of the hand.</param>
        /// <returns><c>True</c> if temporary furiten; <c>False</c> otherwise.</returns>
        internal bool CancelYakusIfTemporaryFuriten(RoundPivot currentRound, int playerIndex)
        {
            if (currentRound == null)
            {
                return(false);
            }

            int i = 0;

            while (currentRound.PlayerIndexHistory.Count < i &&
                   currentRound.PlayerIndexHistory.ElementAt(i) == playerIndex.RelativePlayerIndex(-(i + 1)) &&
                   playerIndex.RelativePlayerIndex(-(i + 1)) != playerIndex)
            {
                // The tile discarded by the latest player is the tile we ron !
                if (i > 0)
                {
                    TilePivot lastFromDiscard = currentRound.GetDiscard(currentRound.PlayerIndexHistory.ElementAt(i)).LastOrDefault();
                    if (lastFromDiscard != null && IsCompleteFull(new List <TilePivot>(ConcealedTiles)
                    {
                        lastFromDiscard
                    }, DeclaredCombinations.ToList()))
                    {
                        Yakus             = null;
                        YakusCombinations = null;
                        return(true);
                    }
                }
                i++;
            }

            return(false);
        }
예제 #2
0
        /// <summary>
        /// Checks if the hand has finished on a closed wait.
        /// </summary>
        /// <returns><c>True</c> if contains a closed wait; <c>False</c> otherwise.</returns>
        public bool HandWithClosedWait()
        {
            if (YakusCombinations == null)
            {
                return(false);
            }

            // The combination with the last pick.
            TileComboPivot combo = YakusCombinations.FirstOrDefault(c => c.Tiles.Any(t => ReferenceEquals(t, LatestPick)));

            if (combo == null || combo.IsBrelanOrSquare)
            {
                return(false);
            }

            // Other concealed (and not declared) combinations with the same tile.
            List <TileComboPivot> otherCombos =
                YakusCombinations
                .Where(c => c != combo && !DeclaredCombinations.Contains(c) && c.Tiles.Contains(LatestPick))
                .ToList();

            // The real "LatestPick" is closed...
            bool isClosed = combo.IsPair || LatestPick.TileIsMiddleWait(combo) || LatestPick.TileIsEdgeWait(combo);

            // .. but there might be not-closed alternatives with the same tile as "LatestPick" in other combination.
            bool alternative1 = otherCombos.Any(c => c.IsBrelanOrSquare);
            bool alternative2 = otherCombos.Any(c => c.IsSequence && !LatestPick.TileIsMiddleWait(c) && !LatestPick.TileIsEdgeWait(c));

            return(isClosed && !(alternative1 || alternative2));
        }
예제 #3
0
        /// <summary>
        /// Checks if <see cref="Yakus"/> and <see cref="YakusCombinations"/> have to be cancelled because of the furiten rule.
        /// </summary>
        /// <param name="discard">The discard of the current player.</param>
        /// <param name="opponentDiscards">
        /// Aggregation of discards from opponents since the riichi call; includes tiles stolen by another opponent and tiles used to call opened kan.
        /// </param>
        /// <returns><c>True</c> if furiten; <c>False</c> otherwise.</returns>
        internal bool CancelYakusIfFuriten(IEnumerable <TilePivot> discard, IEnumerable <TilePivot> opponentDiscards)
        {
            if (discard?.Any(t => IsCompleteFull(new List <TilePivot>(ConcealedTiles)
            {
                t
            }, DeclaredCombinations.ToList())) == true)
            {
                Yakus             = null;
                YakusCombinations = null;
                return(true);
            }

            if (opponentDiscards?.Any(t => IsCompleteFull(new List <TilePivot>(ConcealedTiles)
            {
                t
            }, DeclaredCombinations.ToList())) == true)
            {
                Yakus             = null;
                YakusCombinations = null;
                return(true);
            }

            return(false);
        }