Example #1
0
        public DiscardResponse OnDiscard(VisibleBoard board, Tile tile, int who, DiscardActions suggestedActions)
        {
            if (suggestedActions.HasFlag(DiscardActions.Ron))
            {
                return(DiscardResponse.Ron());
            }

            // Call value honors if it improves shanten. But don't call if already tenpai (all discards would be furiten)
            var shanten = board.Watashi.Hand.Shanten;

            if (shanten > 0 && suggestedActions.HasFlag(DiscardActions.Pon) && !suggestedActions.HasFlag(DiscardActions.Kan))
            {
                var tileType = tile.TileType;
                if (tileType.TileTypeId >= 31 || tileType == board.RoundWind || tileType == board.Watashi.SeatWind)
                {
                    var t = board.Watashi.Hand.WithPon(tileType);
                    if (t.Shanten < shanten)
                    {
                        var tilesInHand = board.Watashi.ConcealedTiles.Where(i => i.TileType.TileTypeId == tileType.TileTypeId).ToList();

                        var tileTypeId = t.GetHighestUkeIreDiscard();
                        var discard    = board.Watashi.ConcealedTiles.First(i => i.TileType.TileTypeId == tileTypeId);

                        return(DiscardResponse.Pon(tilesInHand[0], tilesInHand[1], discard));
                    }
                }
            }

            return(DiscardResponse.Pass());
        }
Example #2
0
        public DiscardResponse OnDiscard(VisibleBoard board, Tile tile, int who, DiscardActions suggestedActions)
        {
            if ((suggestedActions & DiscardActions.Ron) != 0)
            {
                return(DiscardResponse.Ron());
            }

            if ((suggestedActions & DiscardActions.Kan) != 0)
            {
                return(DiscardResponse.Daiminkan());
            }

            if ((suggestedActions & DiscardActions.Pon) != 0)
            {
                var impossibleToKan = ImpossibleToKan(board);
                if (!impossibleToKan.Contains(tile.TileType))
                {
                    var tiles   = board.Watashi.ConcealedTiles.Where(t => t.TileType == tile.TileType).Take(2).ToList();
                    var discard = FindDiscard(board);
                    return(tiles.Contains(discard) ? DiscardResponse.Pass() : DiscardResponse.Pon(tiles[0], tiles[1], discard));
                }
            }

            return(DiscardResponse.Pass());
        }
            internal override bool CanExecute(VisibleBoard board, DiscardActions possibleActions)
            {
                if (board.CurrentDiscard == null)
                {
                    return(false);
                }

                var tileType = board.CurrentDiscard.TileType;

                return(possibleActions.HasFlag(DiscardActions.Pon) &&
                       _tile0.TileType == tileType &&
                       _tile1.TileType == tileType &&
                       _discardAfterCall.TileType != tileType && // kuikae
                       HasTile(board, _tile0) &&
                       HasTile(board, _tile1) &&
                       HasTile(board, _discardAfterCall));
            }
Example #4
0
        public async Task <DiscardResponse> OnDiscard(DiscardActions actions, int seatIndex)
        {
            var player    = _players[seatIndex];
            var boardView = _boardViews[seatIndex];
            var tile      = boardView.CurrentDiscard !;

            var decider = Task.Run(() => player.OnDiscard(boardView, tile, boardView.ActivePlayerIndex, actions));
            var r       = await Task.WhenAny(decider, Task.Delay(DecisionTimeout));

            if (r.IsCompletedSuccessfully && r is Task <DiscardResponse> {
                IsCompletedSuccessfully : true
            } t&& t.Result.CanExecute(boardView, actions))
            {
                return(t.Result);
            }

            return(DiscardResponse.Pass());
        }
            internal override bool CanExecute(VisibleBoard board, DiscardActions possibleActions)
            {
                if (board.CurrentDiscard == null)
                {
                    return(false);
                }

                var tileType = board.CurrentDiscard.TileType;
                var tileTypeIds = new[] { _tile0.TileType.TileTypeId, _tile1.TileType.TileTypeId, tileType.TileTypeId }.OrderBy(x => x).ToList();

                var isValidDiscardForKanchanCase = tileTypeIds[1] == tileType.TileTypeId && _discardAfterCall.TileType != tileType;
                var isValidDiscard = isValidDiscardForKanchanCase || Kuikae.IsValidDiscardForNonKanchanChii(tileType, _discardAfterCall.TileType);

                return(possibleActions.HasFlag(DiscardActions.Chii) &&
                       tileTypeIds[0] + 1 == tileTypeIds[1] &&
                       tileTypeIds[1] + 1 == tileTypeIds[2] &&
                       isValidDiscard &&
                       HasTile(board, _tile0) &&
                       HasTile(board, _tile1) &&
                       HasTile(board, _discardAfterCall));
            }
Example #6
0
 public DiscardResponse OnDiscard(VisibleBoard board, Tile tile, int who, DiscardActions suggestedActions)
 {
     Delay(50);
     return(_player.OnDiscard(board, tile, who, suggestedActions));
 }
 internal override bool CanExecute(VisibleBoard board, DiscardActions possibleActions)
 {
     return(possibleActions.HasFlag(DiscardActions.Kan));
 }
 internal override bool CanExecute(VisibleBoard board, DiscardActions possibleActions)
 {
     return(true);
 }
 internal abstract bool CanExecute(VisibleBoard board, DiscardActions possibleActions);
Example #10
0
 public Client(int seatIndex, DiscardActions allowedActions)
 {
     _allowedActions = allowedActions;
     SeatIndex       = seatIndex;
 }