예제 #1
0
        private async Task <bool> ApproveLynch(GameSession session, GameSessionMember gamerForLynch)
        {
            var allowedMembers = session.GetAliveMembers().ToList();

            allowedMembers.Remove(gamerForLynch);
            var approveVotes =
                await _frontend.CreateLynchApprovalVote(session.Room, allowedMembers.ToArray(), gamerForLynch);

            // no votes, skip
            if (!approveVotes.Any())
            {
                return(false);
            }

            var groupedVotes = (from vote in approveVotes
                                group vote by vote.Approve
                                into voteGroup
                                select new { key = voteGroup.Key, voices = voteGroup.Count() }).ToList();
            var topVotes = (from voteItem in groupedVotes
                            where voteItem.voices == groupedVotes.Max(g => g.voices)
                            select voteItem.key).ToList();

            // there are two top result, skip this Lynch... otherwise return it.
            return(topVotes.Count == 1 && topVotes[0]);
        }
예제 #2
0
        private async Task AskForLastWord(GameSession session, GameSessionMember actionTarget)
        {
            await _frontend.SendMessageToGamer(actionTarget.GamerAccount,
                                               "Тебя убили. Ты можешь отправить мне свои последние слова...");

            var lastWords = await _frontend.GetLastWords(actionTarget.GamerAccount);

            // nothing to say, just skip it
            if (lastWords == null)
            {
                return;
            }
            try
            {
                await _frontend.SendMessageToRoom(session.Room,
                                                  $"Свидетели смерти <b>{actionTarget.GamerAccount.NickName}</b> слышали как он кричал: \n <b><i>{lastWords}</i></b>");
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }
 public Task <ActionDescriptor> AskDoctorForAction(GameSessionMember doctor,
                                                   GameSessionMember[] membersToSelect) => AskForAction(
     "Уважаемый доктор. <b>Кого будем лечить?</b> 🚑",
     doctor,
     membersToSelect,
     (member, index) => new (GameActions?, string)[]
 public ActionDescriptor(GameActions?action = null, GameSessionMember target = null)
 {
     Action = action;
     Target = target;
 }
예제 #5
0
 private Task HealGamer(GameSessionMember healingTarget) =>
 _frontend.SendMessageToGamer(healingTarget.GamerAccount, "Доктор пришел подлечить тебя :)");
예제 #6
0
        private async Task <bool> KillGamer(GameSession session, GameRoles killerRole, GameSessionMember actionTarget,
                                            GameSessionMember?healingTarget)
        {
            // healed by doctor
            if (actionTarget.Id == healingTarget?.Id)
            {
                return(false);
            }
            actionTarget.IsDead = true;
            await _frontend.SendMessageToRoom(session.Room,
                                              $"Был убит: <i>{actionTarget.Role.GetRoleName()}</i> <b>{actionTarget.GamerAccount.NickName}</b>");

            AskForLastWord(session, actionTarget).ConfigureAwait(false);
            return(true);
        }
예제 #7
0
        private async Task InspectGamer(GameSession session, GameRoles instectorRole, GameSessionMember inspectorTarget)
        {
            await _frontend.SendMessageToGamer(inspectorTarget.GamerAccount, "Кто-то наводит справки по тебе...");

            var roleName = inspectorTarget.Role switch
            {
                GameRoles.Citizen => "горожанин",
                GameRoles.Cop => "коммисар",
                GameRoles.Doctor => "доктор",
                GameRoles.Mafia => "мафия"
            };
            var messageText =
                $"Наши люди нашли важную информацию: <b>{inspectorTarget.GamerAccount.NickName}</b> это <b>{roleName}</b>.";

            switch (instectorRole)
            {
            case GameRoles.Cop:
            {
                var cop = session.GetCop();
                if (cop == null)
                {
                    Console.WriteLine($"{session.Id} - Cop is null!");
                    return;
                }

                await _frontend.SendMessageToGamer(cop.GamerAccount, messageText);

                break;
            }

            case GameRoles.Mafia:
                var mafiaMembers = session.GetMafia();
                var messageTasks =
                    mafiaMembers.Select(m => _frontend.SendMessageToGamer(m.GamerAccount, messageText));
                await Task.WhenAll(messageTasks);

                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(instectorRole), instectorRole,
                                                      "Supported only for Cop and Mafia");
            }
        }
예제 #8
0
        private void RunGame(GameSession session)
        {
            Task.Run(async() =>
            {
                try
                {
                    // game timer
                    var stopwatch = new Stopwatch();
                    stopwatch.Start();

                    await SendIntroduceMessages(session.GameMembers);

                    var gameFinished = false;
                    var dayNumber    = 1;
                    while (!gameFinished)
                    {
                        #region Night logic

                        var nightKillsCount = 0;
                        await _frontend.SendMessageToRoom(session.Room,
                                                          $@"
<b>Ночь #{dayNumber}</b> 🌃  
На улицах очень тихо, но это пока.

<b>Игроки</b>: 
{session.GetMembersInfo(false, true)}
", true);
                        await Task.Delay(5000);
                        var doctorActionTask = AskDoctorForAction(session).ConfigureAwait(false);
                        var mafiaActionTask  = AskMafiaForAction(session).ConfigureAwait(false);
                        var copActionTask    = AskCopForAction(session).ConfigureAwait(false);

                        // resolving actions
                        var doctorAction = await doctorActionTask;
                        GameSessionMember healingTarget = null;
                        if (doctorAction.Action != null)
                        {
                            healingTarget = doctorAction.Target;
                            await HealGamer(healingTarget);
                        }

                        await Task.Delay(2000);

                        var copAction = await copActionTask;
                        switch (copAction.Action)
                        {
                        case GameActions.Killing:
                            if (await KillGamer(session, GameRoles.Cop, copAction.Target, healingTarget))
                            {
                                nightKillsCount++;
                            }

                            break;

                        case GameActions.Checkup:
                            await InspectGamer(session, GameRoles.Cop, copAction.Target);
                            break;

                        case null:
                            // nothing to do, maybe cop is dead? (or he sleeps)
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }

                        await Task.Delay(2000);
                        var mafiaAction = await mafiaActionTask;
                        switch (mafiaAction.Action)
                        {
                        case GameActions.Killing:
                            if (await KillGamer(session, GameRoles.Mafia, mafiaAction.Target, healingTarget))
                            {
                                nightKillsCount++;
                            }

                            break;

                        case GameActions.Checkup:
                            await InspectGamer(session, GameRoles.Mafia, mafiaAction.Target);
                            break;

                        case null:
                            // nothing to do, maybe mafia sleeps?
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }

                        if (nightKillsCount == 0)
                        {
                            await _frontend.SendMessageToRoom(session.Room, "Удивительно. Все остались живы.");
                        }

                        #endregion

                        await Task.Delay(2000);

                        // ensure this game is over
                        if (await IsGameOver(session, stopwatch))
                        {
                            break;
                        }

                        await Task.Delay(2000);

                        #region Day logic

                        await _frontend.SendMessageToRoom(session.Room,
                                                          $@"
День #{dayNumber} ☀️
Все проснулись под птение птичек. 
Пришло время наказать мафию.

<b>Игроки</b>: 
{session.GetMembersInfo(false, true)}

А теперь давайте обсудим прошедшую ночь, затем будем голосовать. 
Время на обсуждение: 2 минуты.
", true);

                        await Task.Delay(120000);
                        var gamerForLynch = await PublicLynchVote(session);

                        if (gamerForLynch != null)
                        {
                            var lynchApproved = await ApproveLynch(session, gamerForLynch);
                            if (lynchApproved)
                            {
                                await _frontend.SendMessageToRoom(session.Room,
                                                                  @$ "Вешаем {gamerForLynch.GamerAccount.NickName}...");
                                await KillGamer(session, GameRoles.Citizen, gamerForLynch, null);
                            }
                            else
                            {
                                await _frontend.SendMessageToRoom(session.Room,
                                                                  $@"Это удивительно, {gamerForLynch.GamerAccount.NickName} был на волоске от смерти. 
Граждане решили предоставить ему шанс.");
                            }
                        }
                        else
                        {
                            await _frontend.SendMessageToRoom(session.Room,
                                                              "Мнения жителей разошлись. Никого не будем вешать.");
                        }

                        #endregion

                        await Task.Delay(2000);
                        // ensure this game is over
                        if (await IsGameOver(session, stopwatch))
                        {
                            break;
                        }
                        dayNumber++;
                        await Task.Delay(2000);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    throw;
                }
            });
        }