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]); }
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; }
private Task HealGamer(GameSessionMember healingTarget) => _frontend.SendMessageToGamer(healingTarget.GamerAccount, "Доктор пришел подлечить тебя :)");
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); }
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"); } }
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; } }); }