Exemple #1
0
        public LiarResult Liar(int playerId)
        {
            //if (_game.CurrentGamePlayer.PlayerId != playerId) return null;
            var player = _game.GamePlayers.Single(x => x.PlayerId == playerId);

            if (player.NumberOfDice == 0)
            {
                return(null);
            }

            var liarCall = new LiarCall()
            {
                GamePlayer      = player,
                Round           = _game.CurrentRound,
                GamePlayerRound = player.CurrentGamePlayerRound,
                ParentAction    = _game.CurrentRound.LatestAction,
            };

            if (_game.CurrentRound.LatestAction is not Bid previousBid)
            {
                return(null);                                                        //throw error?
            }
            var        PlayerWhoBidLast    = previousBid.GamePlayer;
            var        PlayerWhoCalledLiar = player;
            GamePlayer PlayerWhoLostDice;
            var        liarResult = new LiarResult
            {
                BidQuantity = previousBid.Quantity,
                BidPips     = previousBid.Pips
            };


            var actualQuantity = GetNumberOfDiceMatchingBid(previousBid.Pips);

            liarResult.ActualQuantity = actualQuantity;

            if (previousBid.Quantity <= actualQuantity)
            {
                // Bidder was correct
                liarResult.DiceLost     = GetDiceLost((actualQuantity - previousBid.Quantity) + 1, PlayerWhoCalledLiar.NumberOfDice);
                liarResult.IsSuccessful = false;
                PlayerWhoLostDice       = PlayerWhoCalledLiar;

                DecrementDice(PlayerWhoCalledLiar, liarResult.DiceLost);

                SetGamePlayerTurn(PlayerWhoCalledLiar.Id);
            }
            else // Liar caller was correct
            {
                liarResult.DiceLost     = GetDiceLost(previousBid.Quantity - actualQuantity, PlayerWhoBidLast.NumberOfDice);
                liarResult.IsSuccessful = true;
                PlayerWhoLostDice       = PlayerWhoBidLast;

                DecrementDice(PlayerWhoBidLast, liarResult.DiceLost);

                SetGamePlayerTurn(PlayerWhoBidLast.Id);
            }

            _db.Actions.Add(liarCall);
            _db.SaveChanges();

            liarResult.PlayerWhoBidLast    = PlayerWhoBidLast.ToPlayerObject();
            liarResult.PlayerWhoCalledLiar = PlayerWhoCalledLiar.ToPlayerObject();
            liarResult.PlayerWhoLostDice   = PlayerWhoLostDice.ToPlayerObject();


            return(liarResult);
        }
Exemple #2
0
        public async Task LiarAsync(params string[] stringArray)
        {
            // check if game is in progress
            if (await ValidateStateAsync(GameState.InProgress) == false)
            {
                return;
            }

            // get inprogress game
            var game = await GetGameAsync(GameState.InProgress);

            // get latest bid and make sure not null or 0 (because liar or exact from last round
            //will have quant&pips of 0&0
            var previousBid = game.CurrentRound.LatestAction as Bid;

            var lastAction = game.CurrentRound.LatestAction;

            //_db.Actions
            //    .AsQueryable()
            //    .Where(g => g.GameId == game.Id)
            //    .LastOrDefault();

            if (lastAction is Bid == false || lastAction == null)
            {
                return;
            }
            if (previousBid == null)
            {
                return;
            }
            if (previousBid.Quantity == 0)
            {
                return;
            }

            //get the player who's turn it is right now
            var playerWhoseTurnItIs         = GetCurrentPlayer(game);
            var originalPlayerWhoseTurnItIs = GetCurrentPlayer(game);

            var activePlayer = GetActivePlayer(game);


            // create liar call object
            var liarCall = new LiarCall()
            {
                GamePlayer      = playerWhoseTurnItIs,
                Round           = game.CurrentRound,
                GamePlayerRound = playerWhoseTurnItIs.CurrentGamePlayerRound,
                ParentAction    = previousBid,
                IsSuccess       = true,
                IsOutOfTurn     = false
            };

            if (playerWhoseTurnItIs.CurrentGamePlayerRound.IsAutoLiarSet)
            {
                liarCall.IsAutoAction = true;
            }
            else if (game.CanCallLiarAnytime)
            {
                // get the player making the liar call with at least on die,
                var gamePlayer = _db.GamePlayers.AsQueryable()
                                 .Where(x => x.GameId == game.Id)
                                 .Where(x => x.NumberOfDice > 0)
                                 .Where(x => x.Player.Username == Context.User.Username)
                                 .SingleOrDefault();

                // if none found (not in game) exit
                if (gamePlayer == null)
                {
                    return;
                }

                // check if calling player is calling out of turn
                if (game.PlayerTurnId != gamePlayer.Id)
                {
                    //player is calling out of turn

                    // change the game's current player to the out of turn player
                    game.PlayerTurnId   = gamePlayer.Id;
                    liarCall.GamePlayer = gamePlayer;

                    // save changes so game is updated
                    _db.SaveChanges();

                    // biddingPlayer
                    playerWhoseTurnItIs  = GetCurrentPlayer(game);
                    liarCall.IsOutOfTurn = true;
                }
            }
            else // not liar anytime
            {
                // make sure player calling liar is the player who should go next
                if (playerWhoseTurnItIs.Player.Username != Context.User.Username)
                {
                    if (!activePlayer.HasActiveDeal)
                    {
                        return;
                    }
                }
            }

            var playerWhoCalledLiar = _perudoGameService.GetGamePlayers(game).Where(x => x.NumberOfDice > 0).Single(x => x.Player.Username == Context.User.Username);

            if (activePlayer.HasActiveDeal && Context.User.Id != activePlayer.Player.UserId)
            {
                playerWhoCalledLiar.PendingUserDealIds = $"{playerWhoCalledLiar.PendingUserDealIds},{activePlayer.Id}";

                await SendMessageAsync($":money_mouth: {playerWhoCalledLiar.Player.Nickname} has accepted the deal! {playerWhoCalledLiar.Player.Nickname}, on your turn use `!payup @{activePlayer.Player.Nickname}` to force them to take your turn for you.");
            }

            // set bidding style to dice (for everything but faceoff round)
            var biddingObject = previousBid.Pips.GetEmoji();
            var biddingName   = "dice";

            // if its faceoff round, and it's enabled, use pips instead
            if (_perudoGameService.GetGamePlayers(game).Sum(x => x.NumberOfDice) == 2 && game.FaceoffEnabled)
            {
                biddingObject = ":record_button:";
                biddingName   = "pips";
            }

            DeleteCommandFromDiscord();
            // send message that liar has been called, w/ details
            var dealer = "";

            if (originalPlayerWhoseTurnItIs.Id != playerWhoCalledLiar.Id &&
                (originalPlayerWhoseTurnItIs.HasActiveDeal || game.DealCurrentGamePlayerId == playerWhoCalledLiar.Id))
            {
                dealer = $" (calling for {originalPlayerWhoseTurnItIs.Player.Nickname})";
            }
            await SendMessageAsync($"{playerWhoCalledLiar.Player.Nickname}{dealer} called **liar**{(liarCall.IsOutOfTurn ? " (out of turn)" : "")} on `{previousBid.Quantity}` ˣ {biddingObject}.");

            // for the dramatic affect
            Thread.Sleep(4000);

            // GetNumberOfDiceMatchingBid
            int numberOfDiceMatchingBid = GetNumberOfDiceMatchingBid(game, previousBid.Pips);

            if (numberOfDiceMatchingBid >= previousBid.Quantity)
            {
                // there are more matching dice than previous bid (previous bid was good)
                liarCall.IsSuccess = false;

                //determine penalty
                var penalty = (numberOfDiceMatchingBid - previousBid.Quantity) + 1; // if variable penalty
                if (game.Penalty != 0)
                {
                    penalty = game.Penalty;                    // penalty is set to 0 for variable penalty games
                }
                if (PlayerEligibleForSafeguard(game, playerWhoseTurnItIs.NumberOfDice, penalty))
                {
                    if (game.PenaltyGainDice)
                    {
                        penalty = 5 - playerWhoseTurnItIs.NumberOfDice;
                    }
                    else
                    {
                        penalty = playerWhoseTurnItIs.NumberOfDice - 1;
                    }

                    await SendMessageAsync($":shield: Snowball shield activated. :shield:");

                    Thread.Sleep(2000);
                }

                var loses = "loses";
                if (game.PenaltyGainDice)
                {
                    loses = "gains";
                }
                // send outcome of unsuccessful liar call
                await SendMessageAsync($"There was actually `{numberOfDiceMatchingBid}` {biddingName}. :axe: {GetUser(playerWhoseTurnItIs.Player.Username).Mention} {loses} {penalty} dice. :axe:");

                // if matching dice is exactly what previous bid was, send that taunt!
                if (numberOfDiceMatchingBid == previousBid.Quantity)
                {
                    var rattles = _db.Rattles.SingleOrDefault(x => x.Username == previousBid.GamePlayer.Player.Username);
                    if (rattles != null)
                    {
                        await SendMessageAsync(rattles.Tauntrattle);
                    }
                }

                await SendRoundSummaryForBots(game);
                await SendRoundSummary(game);

                await CheckGhostAttempts(game);

                // make player with unsuccessful liar call the next to go
                await DecrementDieFromPlayerAndSetThierTurnAsync(game, playerWhoseTurnItIs, penalty);
            }
            else
            {
                liarCall.IsSuccess = true;

                // do same with penalty as in the if statement
                var penalty = previousBid.Quantity - numberOfDiceMatchingBid;
                if (game.Penalty != 0)
                {
                    penalty = game.Penalty;
                }

                if (PlayerEligibleForSafeguard(game, previousBid.GamePlayer.NumberOfDice, penalty))
                {
                    if (game.PenaltyGainDice)
                    {
                        penalty = 5 - previousBid.GamePlayer.NumberOfDice;
                    }
                    else
                    {
                        penalty = previousBid.GamePlayer.NumberOfDice - 1;
                    }

                    await SendMessageAsync($":shield: Snowball shield activated. :shield:");

                    Thread.Sleep(2000);
                }

                var loses = "loses";
                if (game.PenaltyGainDice)
                {
                    loses = "gains";
                }

                await SendMessageAsync($"There was actually `{numberOfDiceMatchingBid}` {biddingName}. :axe: {GetUser(previousBid.GamePlayer.Player.Username).Mention} {loses} {penalty} dice. :axe:");

                await SendRoundSummaryForBots(game);
                await SendRoundSummary(game);

                await CheckGhostAttempts(game);
                await DecrementDieFromPlayerAndSetThierTurnAsync(game, previousBid.GamePlayer, penalty);
            }
            liarCall.SetDuration();
            _db.Actions.Add(liarCall);
            _db.SaveChanges();

            // wait to start new round
            Thread.Sleep(4000);

            RemoveActiveDeals(game);
            RemovePayupPlayer(game);

            await RollDiceStartNewRoundAsync(game);
        }