GameRoom.GameProcess.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using System.Threading;
  4. using System.Threading.Tasks;
  5. using MafiaTelegramBot.Controllers;
  6. using MafiaTelegramBot.CustomCollections.Extensions;
  7. using MafiaTelegramBot.DataBase.EntityDao;
  8. using MafiaTelegramBot.Game.GameRoles;
  9. using MafiaTelegramBot.Models;
  10. using MafiaTelegramBot.Resources;
  11. using Org.BouncyCastle.Utilities;
  12. using Telegram.Bot.Types;
  13. using Timer = System.Timers.Timer;
  14. namespace MafiaTelegramBot.Game.GameRooms
  15. {
  16. public partial class GameRoom
  17. {
  18. public void Start()
  19. {
  20. new Task(async () =>
  21. {
  22. IsRunning = true;
  23. await FirstNight();
  24. await FirstDay();
  25. await GameCycle();
  26. await EndOfGame();
  27. }).Start();
  28. }
  29. private async Task FirstDay()
  30. {
  31. IsDay = true;
  32. await PlayersCh.Send(strings.first_day_message);
  33. await Task.Run(async() =>
  34. {
  35. var turnsCount = _turnOrder.Count;
  36. Player firstPlayer = null;
  37. for (var i = 0; i < turnsCount; ++i)
  38. {
  39. var player = _turnOrder.Dequeue();
  40. if(!player.IsPlaying) continue;
  41. await player.CurrentRole.DayAction();
  42. if (firstPlayer != null && player.IsPlaying) _turnOrder.Enqueue(player);
  43. else firstPlayer = player;
  44. }
  45. _turnOrder.Enqueue(firstPlayer);
  46. });
  47. IsFirstCycle = false;
  48. await PlayersCh.Send(strings.city_falls_asleep);
  49. }
  50. private async Task FirstNight()
  51. {
  52. IsFirstCycle = true;
  53. await Task.Run(async() =>
  54. {
  55. await PlayersCh.Send(strings.city_falls_asleep);
  56. var mafia = Players.Values.Where(player => player.GetRole() is Roles.Mafia).ToArray();
  57. var don = Players.Values.FirstOrDefault(player => player.GetRole() is Roles.Don);
  58. var message = strings.your_teammates;
  59. if (don != null) message += $" \\({don.TurnOrder}\\) {don.NickName} - {roles.Don}";
  60. message = mafia.Aggregate(message, (current, player) => current + $" \\({player.TurnOrder}\\) {player.NickName}");
  61. await MafiaCh.Send(message);
  62. var resetEvent = new ManualResetEvent(false);
  63. var timer = new Timer
  64. {
  65. AutoReset = false,
  66. Interval = 10 * 1000
  67. };
  68. timer.Elapsed += (_, _) => resetEvent.Set();
  69. timer.Start();
  70. foreach (var player in Players.Values)
  71. {
  72. player.CurrentRole.KnownRoles.Add(player);
  73. if(player.GetRole() is Roles.Don or Roles.Mafia) player.CurrentRole.KnownRoles.AddRange(
  74. Players.Values.Where(p=> player.Id != p.Id && p.GetRole() is Roles.Mafia or Roles.Don)
  75. );
  76. }
  77. resetEvent.WaitOne();
  78. });
  79. }
  80. private async Task GameCycle()
  81. {
  82. await Task.Run(async () =>
  83. {
  84. var alivePlayers = Players.Values.Where(p => p.IsAlive).ToList();
  85. var aliveMafia = alivePlayers.Where(p => p.GetRole() is Roles.Don or Roles.Mafia).ToList();
  86. var gameNotEnded = alivePlayers.Count > 2 * aliveMafia.Count && aliveMafia.Count > 0;
  87. while (gameNotEnded)
  88. {
  89. IsDay = false;
  90. await NightPhase();
  91. await SummingUpPhase();
  92. IsDay = true;
  93. await DayPhase();
  94. await DefencePhase();
  95. await DispatchPhase();
  96. }
  97. });
  98. }
  99. private async Task DayPhase()
  100. {
  101. var turnsCount = _turnOrder.Count;
  102. Player firstPlayer = null;
  103. for (var i = 0; i < turnsCount; ++i)
  104. {
  105. var player = _turnOrder.Dequeue();
  106. if(!player.IsPlaying) continue;
  107. if (firstPlayer == null) player.IsFirst = true;
  108. await player.CurrentRole.DayAction();
  109. if (player.IsFirst) firstPlayer = player;
  110. else _turnOrder.Enqueue(player);
  111. }
  112. firstPlayer!.IsFirst = false;
  113. _turnOrder.Enqueue(firstPlayer);
  114. }
  115. private async Task NightPhase()
  116. {
  117. await Task.Run(async () =>
  118. {
  119. var resetEvent = new ManualResetEvent(false);
  120. var timer = new Timer{ Interval = 60*1000, AutoReset = false };
  121. foreach (var player in Players.Values.Where(p=>p.IsAlive))
  122. {
  123. await player.CurrentRole.NightAction();
  124. }
  125. timer.Elapsed += (_, _) => resetEvent.Set();
  126. timer.Start();
  127. resetEvent.WaitOne();
  128. });
  129. }
  130. private async Task SummingUpPhase()
  131. {
  132. await Task.Run(async () =>
  133. {
  134. //TODO order of applying with priorities
  135. foreach (var player in Players.Values.Where(p=>p.IsAlive))
  136. {
  137. await player.CurrentRole.ApplyNightActionResult();
  138. }
  139. });
  140. }
  141. private async Task DefencePhase()
  142. {
  143. await Task.Run( () =>
  144. {
  145. });
  146. }
  147. private async Task DispatchPhase()
  148. {
  149. await Task.Run( () =>
  150. {
  151. });
  152. }
  153. public async Task<Message> PutUpVote(long playerId, long targetId)
  154. {
  155. var player = await UserDao.GetPlayerById(playerId);
  156. VoteUpList.AddUnique(Players[targetId]);
  157. if (playerId != targetId)
  158. {
  159. var target = await UserDao.GetPlayerById(targetId);
  160. await PlayersCh.SendExcept(player.ChatId, $"{player.NickName} {strings.vote_to} {target.NickName}");
  161. return await Bot.SendWithMarkdown2(player.ChatId, $"{strings.you_vote_player} {target.NickName}");
  162. }
  163. await PlayersCh.SendExcept(player.ChatId, $"{player.NickName} {strings.vote_to_self}");
  164. return await Bot.SendWithMarkdown2(player.ChatId, strings.you_vote_to_self);
  165. }
  166. private async Task EndOfGame()
  167. {
  168. await Task.Run(async () =>
  169. {
  170. foreach (var (_, player) in Players)
  171. {
  172. player.CurrentRole = new NoneRole();
  173. player.IsPlaying = false;
  174. player.IsSpeaker = false;
  175. player.IsAlive = true;
  176. }
  177. IsRunning = false;
  178. IsDay = false;
  179. _turnOrder.Clear();
  180. if (!Players.ContainsKey(Owner.Id) || Players.Count == 0) new Task(async() =>
  181. await RoomController.DissolveRoom(RoomEncrypter.GetCode(RoomName))).Start();
  182. else
  183. {
  184. await Bot.SendWithMarkdown2(Owner.ChatId, strings.thanks_for_game, Keyboards.OwnerGameMenu);
  185. await PlayersCh.SendExcept(Owner.Id, strings.thanks_for_game, Keyboards.PlayerGameMenu);
  186. }
  187. });
  188. }
  189. }
  190. }